Unstable RenderTexture
This commit is contained in:
commit
8f6ca79e6b
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -150,12 +150,17 @@
|
||||||
<ClCompile Include="Resource\Loaders\CustomLoader.cpp" />
|
<ClCompile Include="Resource\Loaders\CustomLoader.cpp" />
|
||||||
<ClCompile Include="Resource\OResourceHandler.cpp" />
|
<ClCompile Include="Resource\OResourceHandler.cpp" />
|
||||||
<ClCompile Include="Resource\OResource.cpp" />
|
<ClCompile Include="Resource\OResource.cpp" />
|
||||||
|
<ClCompile Include="Thread\OysterMutex.cpp" />
|
||||||
|
<ClCompile Include="Thread\OysterThread_Impl.cpp" />
|
||||||
<ClCompile Include="Utilities.cpp" />
|
<ClCompile Include="Utilities.cpp" />
|
||||||
<ClCompile Include="WinTimer.cpp" />
|
<ClCompile Include="WinTimer.cpp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="Resource\OysterResource.h" />
|
<ClInclude Include="Resource\OysterResource.h" />
|
||||||
<ClInclude Include="Resource\OResource.h" />
|
<ClInclude Include="Resource\OResource.h" />
|
||||||
|
<ClInclude Include="Thread\IThreadObject.h" />
|
||||||
|
<ClInclude Include="Thread\OysterMutex.h" />
|
||||||
|
<ClInclude Include="Thread\OysterThread.h" />
|
||||||
<ClInclude Include="Utilities-InlineImpl.h" />
|
<ClInclude Include="Utilities-InlineImpl.h" />
|
||||||
<ClInclude Include="Utilities.h" />
|
<ClInclude Include="Utilities.h" />
|
||||||
<ClInclude Include="WinTimer.h" />
|
<ClInclude Include="WinTimer.h" />
|
||||||
|
|
|
@ -0,0 +1,72 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup>
|
||||||
|
<Filter Include="Source Files">
|
||||||
|
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||||
|
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Header Files">
|
||||||
|
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||||
|
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Resource Files">
|
||||||
|
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||||
|
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||||
|
</Filter>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="Utilities.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="WinTimer.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="Resource\OResource.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="Resource\OResourceHandler.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="Resource\Loaders\ByteLoader.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="Resource\Loaders\CustomLoader.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<<<<<<< HEAD
|
||||||
|
=======
|
||||||
|
<ClCompile Include="Thread\OysterMutex.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="Thread\OysterThread_Impl.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
>>>>>>> 48c812b0338b859aa6c00c8504dd2f16a4bb44f9
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="Utilities.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="WinTimer.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="Utilities-InlineImpl.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="Resource\OysterResource.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="Resource\OResource.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="Thread\IThreadObject.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="Thread\OysterMutex.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="Thread\OysterThread.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
|
@ -1,3 +1,6 @@
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
// Created by [Dennis Andersen] [2013]
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#include "..\OResource.h"
|
#include "..\OResource.h"
|
||||||
#include "..\..\Utilities.h"
|
#include "..\..\Utilities.h"
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
// Created by [Dennis Andersen] [2013]
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#include "..\OResource.h"
|
#include "..\OResource.h"
|
||||||
#include "..\..\Utilities.h"
|
#include "..\..\Utilities.h"
|
||||||
|
@ -9,7 +12,7 @@ using namespace Oyster::Resource;
|
||||||
|
|
||||||
OResource* OResource::CustomLoader(const wchar_t filename[], CustomLoadFunction fnc)
|
OResource* OResource::CustomLoader(const wchar_t filename[], CustomLoadFunction fnc)
|
||||||
{
|
{
|
||||||
const CustomData &data = fnc();
|
const CustomData &data = fnc(filename);
|
||||||
|
|
||||||
if(!data.loadedData) return 0;
|
if(!data.loadedData) return 0;
|
||||||
if(!data.resourceUnloadFnc) return 0;
|
if(!data.resourceUnloadFnc) return 0;
|
||||||
|
@ -31,7 +34,7 @@ OResource* OResource::CustomReloader()
|
||||||
{
|
{
|
||||||
CustomUnloader();
|
CustomUnloader();
|
||||||
|
|
||||||
const CustomData &data = this->customData->loadingFunction();
|
const CustomData &data = this->customData->loadingFunction(this->resourceFilename.c_str());
|
||||||
this->resourceData = (OHRESOURCE)data.loadedData;
|
this->resourceData = (OHRESOURCE)data.loadedData;
|
||||||
|
|
||||||
if(data.resourceUnloadFnc)
|
if(data.resourceUnloadFnc)
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
// Created by [Dennis Andersen] [2013]
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#include "OResource.h"
|
#include "OResource.h"
|
||||||
|
|
||||||
using namespace Oyster::Resource;
|
using namespace Oyster::Resource;
|
||||||
|
|
|
@ -47,7 +47,7 @@ namespace Oyster
|
||||||
static OResource* Reload (OResource* resource);
|
static OResource* Reload (OResource* resource);
|
||||||
static bool Release (OResource* resource);
|
static bool Release (OResource* resource);
|
||||||
|
|
||||||
Utility::DynamicMemory::RefCount resourceRef;
|
Utility::DynamicMemory::ReferenceCount resourceRef;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static OResource* ByteLoader (const wchar_t filename[], ResourceType type, OResource* old = 0);
|
static OResource* ByteLoader (const wchar_t filename[], ResourceType type, OResource* old = 0);
|
||||||
|
|
|
@ -60,7 +60,8 @@ OHRESOURCE OysterResource::LoadResource(const wchar_t filename[], CustomLoadFunc
|
||||||
|
|
||||||
if(!resourceData) return 0;
|
if(!resourceData) return 0;
|
||||||
|
|
||||||
if(resourceData) resourceData->SetResourceID(CustomId);
|
resourceData->SetResourceID(CustomId);
|
||||||
|
|
||||||
resourcePrivate.SaveResource(resourceData);
|
resourcePrivate.SaveResource(resourceData);
|
||||||
|
|
||||||
return (OHRESOURCE)resourceData->GetResourceHandle();
|
return (OHRESOURCE)resourceData->GetResourceHandle();
|
||||||
|
|
|
@ -13,8 +13,10 @@ namespace Oyster
|
||||||
struct CustomData;
|
struct CustomData;
|
||||||
/** A Resource handle representing various resources */
|
/** A Resource handle representing various resources */
|
||||||
typedef unsigned long OHRESOURCE;
|
typedef unsigned long OHRESOURCE;
|
||||||
typedef void(*CustomUnloadFunction)(void*);
|
/** Typedef on a fuction required for custom unloading */
|
||||||
typedef const CustomData&(*CustomLoadFunction)();
|
typedef void(*CustomUnloadFunction)(void* loadedData);
|
||||||
|
/** Typedef on a fuction required for custom loading */
|
||||||
|
typedef const CustomData&(*CustomLoadFunction)(const wchar_t filename[]);
|
||||||
|
|
||||||
/** An enum class representing all avalible resources that is supported. */
|
/** An enum class representing all avalible resources that is supported. */
|
||||||
enum ResourceType
|
enum ResourceType
|
||||||
|
@ -26,7 +28,7 @@ namespace Oyster
|
||||||
ResourceType_Byte_UNICODE, /**< Handle can be interpeted as char[] or char* */
|
ResourceType_Byte_UNICODE, /**< Handle can be interpeted as char[] or char* */
|
||||||
ResourceType_Byte_UTF16LE, /**< Handle can be interpeted as char[] or char* */
|
ResourceType_Byte_UTF16LE, /**< Handle can be interpeted as char[] or char* */
|
||||||
|
|
||||||
ResourceType_COUNT, /**< Handle can be interpeted as ? */
|
ResourceType_COUNT, /**< Not used. */
|
||||||
|
|
||||||
ResourceType_UNKNOWN = -1, /**< Handle can be interpeted as void* */
|
ResourceType_UNKNOWN = -1, /**< Handle can be interpeted as void* */
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
// Created by [Dennis Andersen] [2013]
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef MISC_I_THREAD_OBJECT_H
|
||||||
|
#define MISC_I_THREAD_OBJECT_H
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
namespace Oyster
|
||||||
|
{
|
||||||
|
namespace Thread
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Inherit this class to get threading compatibility.
|
||||||
|
*/
|
||||||
|
class IThreadObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Override this to get notified when the thread is started.
|
||||||
|
*/
|
||||||
|
virtual void ThreadEntry() { }
|
||||||
|
/**
|
||||||
|
* Override this to get notified when the thread is about to exit.
|
||||||
|
*/
|
||||||
|
virtual void ThreadExit() { }
|
||||||
|
/**
|
||||||
|
* This function is required to get threading working.
|
||||||
|
*/
|
||||||
|
virtual bool DoWork ( ) = 0;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // !MISC_I_THREAD_OBJECT_H
|
||||||
|
|
|
@ -0,0 +1,71 @@
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
// Created by [Dennis Andersen] [2013]
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include "OysterMutex.h"
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
|
#include <thread>
|
||||||
|
#include <future>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
OysterMutex::OysterMutex()
|
||||||
|
{}
|
||||||
|
|
||||||
|
OysterMutex::OysterMutex(bool initialOwnership)
|
||||||
|
{
|
||||||
|
if(initialOwnership)
|
||||||
|
{
|
||||||
|
this->mutex.lock();
|
||||||
|
this->id = std::this_thread::get_id();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
OysterMutex::~OysterMutex()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
void OysterMutex::LockMutex()
|
||||||
|
{
|
||||||
|
if(std::this_thread::get_id() == this->id) return;
|
||||||
|
|
||||||
|
this->mutex.lock();
|
||||||
|
|
||||||
|
this->id = std::this_thread::get_id();
|
||||||
|
}
|
||||||
|
void OysterMutex::LockMutex(unsigned int msec)
|
||||||
|
{
|
||||||
|
if(std::this_thread::get_id() == this->id) return;
|
||||||
|
|
||||||
|
auto start = std::chrono::high_resolution_clock::now();
|
||||||
|
auto end = start + std::chrono::milliseconds(msec);
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if(this->mutex.try_lock())
|
||||||
|
{
|
||||||
|
this->mutex.lock();
|
||||||
|
this->id = std::this_thread::get_id();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} while (std::chrono::high_resolution_clock::now() < end);
|
||||||
|
|
||||||
|
this->mutex.lock();
|
||||||
|
}
|
||||||
|
void OysterMutex::UnlockMutex()
|
||||||
|
{
|
||||||
|
//Let the owner unlock
|
||||||
|
if(std::this_thread::get_id() != this->id) return;
|
||||||
|
|
||||||
|
this->mutex.unlock();
|
||||||
|
this->id = std::thread::id();
|
||||||
|
|
||||||
|
}
|
||||||
|
bool OysterMutex::IsTaken()
|
||||||
|
{
|
||||||
|
return !this->mutex.try_lock();
|
||||||
|
}
|
||||||
|
void OysterMutex::Reset()
|
||||||
|
{
|
||||||
|
if(!this->mutex.try_lock())
|
||||||
|
this->mutex.unlock();
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
// Created by [Dennis Andersen] [2013]
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef MISC_OYSTER_MUTEX_H
|
||||||
|
#define MISC_OYSTER_MUTEX_H
|
||||||
|
|
||||||
|
#include <mutex>
|
||||||
|
#include <thread>
|
||||||
|
#include <atomic>
|
||||||
|
|
||||||
|
class OysterMutex
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
OysterMutex();
|
||||||
|
OysterMutex(bool initialOwnership);
|
||||||
|
virtual~OysterMutex();
|
||||||
|
void LockMutex();
|
||||||
|
void LockMutex(unsigned int timeSpan);
|
||||||
|
void UnlockMutex();
|
||||||
|
/** Returns true if mutex is taken */
|
||||||
|
bool IsTaken();
|
||||||
|
/** This function resets resource locking */
|
||||||
|
void Reset();
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::mutex mutex;
|
||||||
|
std::thread::id id;
|
||||||
|
|
||||||
|
OysterMutex(const OysterMutex&);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // !MISC_OYSTER_MUTEX_H
|
|
@ -0,0 +1,49 @@
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
// Created by [Dennis Andersen] [2013]
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef MISC_OYSTER_THREAD_H
|
||||||
|
#define MISC_OYSTER_THREAD_H
|
||||||
|
|
||||||
|
#include "IThreadObject.h"
|
||||||
|
|
||||||
|
namespace Oyster
|
||||||
|
{
|
||||||
|
namespace Thread
|
||||||
|
{
|
||||||
|
enum OYSTER_THREAD_ERROR
|
||||||
|
{
|
||||||
|
OYSTER_THREAD_ERROR_FAILED,
|
||||||
|
OYSTER_THREAD_ERROR_SUCCESS,
|
||||||
|
};
|
||||||
|
|
||||||
|
class OysterThread
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
struct PrivateData;
|
||||||
|
PrivateData *privateData;
|
||||||
|
|
||||||
|
OysterThread(const OysterThread& original);
|
||||||
|
const OysterThread& operator=(const OysterThread& original);
|
||||||
|
|
||||||
|
public:
|
||||||
|
OysterThread();
|
||||||
|
virtual~OysterThread();
|
||||||
|
|
||||||
|
OYSTER_THREAD_ERROR Create(IThreadObject* worker, bool start);
|
||||||
|
OYSTER_THREAD_ERROR Start();
|
||||||
|
void Stop();
|
||||||
|
void Pause();
|
||||||
|
void Pause(int mSec);
|
||||||
|
void Resume();
|
||||||
|
OYSTER_THREAD_ERROR Reset(IThreadObject* worker = 0);
|
||||||
|
void Terminate();
|
||||||
|
void Wait();
|
||||||
|
void Wait(int mSec);
|
||||||
|
OYSTER_THREAD_ERROR Swap(const OysterThread* other);
|
||||||
|
bool IsActive();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // !MISC_OYSTER_THREAD_H
|
|
@ -0,0 +1,253 @@
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
// Created by [Dennis Andersen] [2013]
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include "OysterThread.h"
|
||||||
|
#include "OysterMutex.h"
|
||||||
|
#include "..\Utilities.h"
|
||||||
|
#include <thread>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
using namespace Oyster::Thread;
|
||||||
|
using namespace Utility::DynamicMemory::SmartPointer;
|
||||||
|
|
||||||
|
|
||||||
|
#pragma region Declerations
|
||||||
|
|
||||||
|
struct ThreadData;
|
||||||
|
/** A typical Oyster thread function */
|
||||||
|
typedef void (*ThreadFunction)(StdSmartPointer<ThreadData>&);
|
||||||
|
|
||||||
|
enum OYSTER_THREAD_STATE
|
||||||
|
{
|
||||||
|
OYSTER_THREAD_STATE_RESET,
|
||||||
|
OYSTER_THREAD_STATE_RUNNING,
|
||||||
|
OYSTER_THREAD_STATE_PAUSED,
|
||||||
|
OYSTER_THREAD_STATE_STOPED,
|
||||||
|
OYSTER_THREAD_STATE_TERMINATED,
|
||||||
|
OYSTER_THREAD_STATE_DEAD,
|
||||||
|
};
|
||||||
|
|
||||||
|
//TODO: Add a threadStartPackage struct that contains all the necasary data to fire of a thread
|
||||||
|
struct ThreadData
|
||||||
|
{
|
||||||
|
OYSTER_THREAD_STATE state; //<! The current thread state.
|
||||||
|
StdSmartPointer<std::thread> workerThread; //<! The worker thread.
|
||||||
|
std::thread::id callingThread; //<! The owner thread.
|
||||||
|
IThreadObject *owner; //<! The owner of the thread as IThread.
|
||||||
|
int msec; //<! A timer in miliseconds.
|
||||||
|
OysterMutex mutexLock; //<! The lock, locking the member variabls.
|
||||||
|
|
||||||
|
ThreadData() {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
ThreadData(const ThreadData&){};
|
||||||
|
};
|
||||||
|
struct OysterThread::PrivateData
|
||||||
|
{
|
||||||
|
StdSmartPointer<ThreadData> threadData;
|
||||||
|
|
||||||
|
PrivateData()
|
||||||
|
:threadData(new ThreadData())
|
||||||
|
{
|
||||||
|
threadData->owner = 0;
|
||||||
|
threadData->workerThread = 0;
|
||||||
|
threadData->callingThread;
|
||||||
|
threadData->state = OYSTER_THREAD_STATE_STOPED;
|
||||||
|
}
|
||||||
|
~PrivateData()
|
||||||
|
{
|
||||||
|
//@todo TODO: Make detatch avalible.
|
||||||
|
//this->threadData->workerThread->detach();
|
||||||
|
|
||||||
|
this->threadData->owner = 0;
|
||||||
|
|
||||||
|
this->threadData->state = OYSTER_THREAD_STATE_DEAD;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void ThreadingFunction(StdSmartPointer<ThreadData> &origin)
|
||||||
|
{
|
||||||
|
bool shouldContinue;
|
||||||
|
StdSmartPointer<ThreadData> w = origin;
|
||||||
|
|
||||||
|
theBegining:
|
||||||
|
|
||||||
|
while(w->state == OYSTER_THREAD_STATE_STOPED);
|
||||||
|
w->mutexLock.LockMutex();
|
||||||
|
w->owner->ThreadEntry();
|
||||||
|
w->mutexLock.UnlockMutex();
|
||||||
|
|
||||||
|
while (w->state != OYSTER_THREAD_STATE_STOPED && w->state != OYSTER_THREAD_STATE_DEAD)
|
||||||
|
{
|
||||||
|
|
||||||
|
w->mutexLock.LockMutex();
|
||||||
|
{
|
||||||
|
shouldContinue = w->owner->DoWork();
|
||||||
|
}
|
||||||
|
w->mutexLock.UnlockMutex();
|
||||||
|
|
||||||
|
if(!shouldContinue)
|
||||||
|
{
|
||||||
|
goto theEnd;
|
||||||
|
}
|
||||||
|
if(w->state == OYSTER_THREAD_STATE_TERMINATED)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if(w->state == OYSTER_THREAD_STATE_RESET)
|
||||||
|
{
|
||||||
|
goto theBegining;
|
||||||
|
}
|
||||||
|
else if(w->msec > 0)
|
||||||
|
{
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(w->msec));
|
||||||
|
}
|
||||||
|
|
||||||
|
while (w->state == OYSTER_THREAD_STATE_PAUSED);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(w->state == OYSTER_THREAD_STATE_DEAD)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
theEnd:
|
||||||
|
|
||||||
|
w->mutexLock.LockMutex();
|
||||||
|
w->owner->ThreadExit();
|
||||||
|
w->mutexLock.UnlockMutex();
|
||||||
|
|
||||||
|
w->state = OYSTER_THREAD_STATE_DEAD;
|
||||||
|
}
|
||||||
|
|
||||||
|
OysterThread::OysterThread()
|
||||||
|
{
|
||||||
|
this->privateData = new PrivateData();
|
||||||
|
}
|
||||||
|
OysterThread::~OysterThread()
|
||||||
|
{
|
||||||
|
delete this->privateData;
|
||||||
|
this->privateData = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
OYSTER_THREAD_ERROR OysterThread::Create(IThreadObject* worker, bool start)
|
||||||
|
{
|
||||||
|
if(!this->privateData) return OYSTER_THREAD_ERROR_FAILED;
|
||||||
|
if(this->privateData->threadData->workerThread) return OYSTER_THREAD_ERROR_FAILED;
|
||||||
|
|
||||||
|
this->privateData->threadData->owner = worker;
|
||||||
|
|
||||||
|
ThreadFunction fnc = ThreadingFunction;
|
||||||
|
|
||||||
|
//Maby move this thread creation to a seperate Start() function because std::thread fires the thread when it is created. :(
|
||||||
|
this->privateData->threadData->workerThread = new std::thread(fnc, this->privateData->threadData);
|
||||||
|
|
||||||
|
if(!this->privateData->threadData->workerThread)
|
||||||
|
return OYSTER_THREAD_ERROR_FAILED;
|
||||||
|
|
||||||
|
if(start)
|
||||||
|
{
|
||||||
|
//@todo TODO: No need to lock since the other thread end is only reading this value. Worst case scenario is n lost cycles.
|
||||||
|
this->privateData->threadData->state = OYSTER_THREAD_STATE_RUNNING;
|
||||||
|
}
|
||||||
|
return OYSTER_THREAD_ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
OYSTER_THREAD_ERROR OysterThread::Start()
|
||||||
|
{
|
||||||
|
if(!this->privateData->threadData->workerThread)
|
||||||
|
return OYSTER_THREAD_ERROR_FAILED;
|
||||||
|
|
||||||
|
this->privateData->threadData->state = OYSTER_THREAD_STATE_RUNNING;
|
||||||
|
return OYSTER_THREAD_ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
void OysterThread::Stop()
|
||||||
|
{
|
||||||
|
this->privateData->threadData->mutexLock.LockMutex();
|
||||||
|
this->privateData->threadData->state = OYSTER_THREAD_STATE_STOPED;
|
||||||
|
this->privateData->threadData->mutexLock.UnlockMutex();
|
||||||
|
}
|
||||||
|
void OysterThread::Pause()
|
||||||
|
{
|
||||||
|
this->privateData->threadData->mutexLock.LockMutex();
|
||||||
|
this->privateData->threadData->state = OYSTER_THREAD_STATE_PAUSED;
|
||||||
|
this->privateData->threadData->mutexLock.UnlockMutex();
|
||||||
|
}
|
||||||
|
void OysterThread::Pause(int msec)
|
||||||
|
{
|
||||||
|
|
||||||
|
if(std::this_thread::get_id() == this->privateData->threadData->workerThread->get_id())
|
||||||
|
{
|
||||||
|
this->privateData->threadData->msec = msec;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this->privateData->threadData->mutexLock.LockMutex();
|
||||||
|
this->privateData->threadData->state = OYSTER_THREAD_STATE_PAUSED;
|
||||||
|
this->privateData->threadData->msec = msec;
|
||||||
|
this->privateData->threadData->mutexLock.UnlockMutex();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void OysterThread::Resume()
|
||||||
|
{
|
||||||
|
this->privateData->threadData->mutexLock.LockMutex();
|
||||||
|
this->privateData->threadData->state = OYSTER_THREAD_STATE_RUNNING;
|
||||||
|
this->privateData->threadData->mutexLock.UnlockMutex();
|
||||||
|
}
|
||||||
|
OYSTER_THREAD_ERROR OysterThread::Reset(IThreadObject* worker)
|
||||||
|
{
|
||||||
|
this->privateData->threadData->mutexLock.LockMutex();
|
||||||
|
if(worker)
|
||||||
|
{
|
||||||
|
this->privateData->threadData->owner = worker;
|
||||||
|
}
|
||||||
|
this->privateData->threadData->callingThread = std::this_thread::get_id();
|
||||||
|
this->privateData->threadData->msec = 0;
|
||||||
|
this->privateData->threadData->mutexLock.UnlockMutex();
|
||||||
|
|
||||||
|
return OYSTER_THREAD_ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
void OysterThread::Terminate()
|
||||||
|
{
|
||||||
|
delete this->privateData->threadData->workerThread;
|
||||||
|
this->privateData->threadData->mutexLock.Reset();
|
||||||
|
this->privateData->threadData->workerThread = 0;
|
||||||
|
this->privateData->threadData->callingThread = std::thread::id();
|
||||||
|
this->privateData->threadData->msec = 0;
|
||||||
|
this->privateData->threadData->state = OYSTER_THREAD_STATE_STOPED;
|
||||||
|
}
|
||||||
|
void OysterThread::Wait()
|
||||||
|
{
|
||||||
|
if(this->privateData->threadData->state == OYSTER_THREAD_STATE_DEAD)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this->privateData->threadData->workerThread->get_id() == std::this_thread::get_id()) return;
|
||||||
|
|
||||||
|
this->privateData->threadData->workerThread->join();
|
||||||
|
}
|
||||||
|
void OysterThread::Wait(int msec)
|
||||||
|
{
|
||||||
|
if(this->privateData->threadData->workerThread->get_id() == std::this_thread::get_id()) return;
|
||||||
|
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(msec));
|
||||||
|
}
|
||||||
|
OYSTER_THREAD_ERROR OysterThread::Swap(const OysterThread* other)
|
||||||
|
{
|
||||||
|
this->privateData->threadData->workerThread->swap(*other->privateData->threadData->workerThread);
|
||||||
|
return OYSTER_THREAD_ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
bool OysterThread::IsActive()
|
||||||
|
{
|
||||||
|
if (this->privateData->threadData->state == OYSTER_THREAD_STATE_RUNNING)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
// Inline and template implementations for
|
// Inline and template implementations for
|
||||||
// the Utility Collection of Miscellanious Handy Functions
|
// the Utility Collection of Miscellanious Handy Functions
|
||||||
// © Dan Andersson 2013
|
// © Dan Andersson 2013
|
||||||
|
// © Dennis Andersen 2013 TODO: Is this correct?
|
||||||
/////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#ifndef UTILITIES_INLINE_IMPL_H
|
#ifndef UTILITIES_INLINE_IMPL_H
|
||||||
|
@ -149,8 +150,7 @@ namespace Utility
|
||||||
return this->ownedArray != NULL;
|
return this->ownedArray != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Type>
|
template<typename Type>Type* UniqueArray<Type>::Release()
|
||||||
Type* UniqueArray<Type>::Release()
|
|
||||||
{
|
{
|
||||||
Type *copy = this->ownedArray;
|
Type *copy = this->ownedArray;
|
||||||
this->ownedArray = NULL;
|
this->ownedArray = NULL;
|
||||||
|
@ -162,6 +162,113 @@ namespace Utility
|
||||||
{
|
{
|
||||||
return this->operator bool();
|
return this->operator bool();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace SmartPointer
|
||||||
|
{
|
||||||
|
template<typename T>
|
||||||
|
void StdSmartPointer<T>::Destroy()
|
||||||
|
{
|
||||||
|
delete this->_rc;
|
||||||
|
this->_rc = NULL;
|
||||||
|
delete this->_ptr;
|
||||||
|
this->_ptr = NULL;
|
||||||
|
}
|
||||||
|
template<typename T> StdSmartPointer<T>::StdSmartPointer()
|
||||||
|
:_rc(0), _ptr(0)
|
||||||
|
{ }
|
||||||
|
template<typename T> StdSmartPointer<T>::StdSmartPointer(T* p)
|
||||||
|
:_ptr(p)
|
||||||
|
{
|
||||||
|
this->_rc = new ReferenceCount();
|
||||||
|
this->_rc->Incref();
|
||||||
|
}
|
||||||
|
template<typename T> StdSmartPointer<T>::StdSmartPointer(const StdSmartPointer& d)
|
||||||
|
:_ptr(d._ptr), _rc(d._rc)
|
||||||
|
{
|
||||||
|
if(this->_rc)
|
||||||
|
this->_rc->Incref();
|
||||||
|
}
|
||||||
|
template<typename T> StdSmartPointer<T>::~StdSmartPointer()
|
||||||
|
{
|
||||||
|
if (this->_rc && this->_rc->Decref() == 0)
|
||||||
|
{
|
||||||
|
Destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
template<typename T> StdSmartPointer<T>& StdSmartPointer<T>::operator= (const StdSmartPointer<T>& p)
|
||||||
|
{
|
||||||
|
if (this != &p)
|
||||||
|
{
|
||||||
|
//Last to go?
|
||||||
|
if(this->_rc && this->_rc->Release() == 0)
|
||||||
|
{
|
||||||
|
//Call child specific
|
||||||
|
Destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
this->_ptr = p._ptr;
|
||||||
|
this->_rc = p._rc;
|
||||||
|
this->_rc->Add();
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
template<typename T> StdSmartPointer<T>& StdSmartPointer<T>::operator= (T* p)
|
||||||
|
{
|
||||||
|
if (this->_ptr != p)
|
||||||
|
{
|
||||||
|
//Last to go?
|
||||||
|
if(this->_rc)
|
||||||
|
{
|
||||||
|
if(this->_rc->Decref() == 0)
|
||||||
|
{
|
||||||
|
//Call child specific
|
||||||
|
Destroy();
|
||||||
|
this->_rc = new ReferenceCount();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
this->_rc = new ReferenceCount();
|
||||||
|
|
||||||
|
this->_ptr = p;
|
||||||
|
this->_rc->Incref();
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
template<typename T> inline bool StdSmartPointer<T>::operator== (const StdSmartPointer<T>& d)
|
||||||
|
{
|
||||||
|
return d._ptr == this->_ptr;
|
||||||
|
}
|
||||||
|
template<typename T> inline bool StdSmartPointer<T>::operator== (const T& p)
|
||||||
|
{
|
||||||
|
return &p == this->_ptr;
|
||||||
|
}
|
||||||
|
template<typename T> inline T& StdSmartPointer<T>::operator* ()
|
||||||
|
{
|
||||||
|
return *this->_ptr;
|
||||||
|
}
|
||||||
|
template<typename T> inline T* StdSmartPointer<T>::operator-> ()
|
||||||
|
{
|
||||||
|
return this->_ptr;
|
||||||
|
}
|
||||||
|
template<typename T> inline StdSmartPointer<T>::operator T* ()
|
||||||
|
{
|
||||||
|
return this->_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the connected pointer */
|
||||||
|
template<typename T> inline T* StdSmartPointer<T>::Get()
|
||||||
|
{
|
||||||
|
return this->_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Checks if the pointer is valid (not NULL)
|
||||||
|
Returns true for valid, else false. */
|
||||||
|
template<typename T> inline bool StdSmartPointer<T>::IsValid()
|
||||||
|
{
|
||||||
|
return (this->_ptr != NULL) ? true : false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
//!//!//!//!//!//!//!//!//!//!//!//!//!//!//!//!//!//!//!//!//!//!//!
|
//!//!//!//!//!//!//!//!//!//!//!//!//!//!//!//!//!//!//!//!//!//!//!
|
||||||
// Utility Collection of Miscellanious Handy Functions
|
// Utility Collection of Miscellanious Handy Functions
|
||||||
// © Dan Andersson 2013
|
// © Dan Andersson 2013
|
||||||
//!//!//!//!//!//!//!//!//!//!//!//!//!//!//!//!//!//!//!//!//!//!//!
|
// © Dennis Andersen 2013
|
||||||
|
|
||||||
|
|
||||||
#ifndef UTILITIES_H
|
#ifndef UTILITIES_H
|
||||||
#define UTILITIES_H
|
#define UTILITIES_H
|
||||||
|
@ -106,20 +107,62 @@ namespace Utility
|
||||||
mutable Type *ownedArray;
|
mutable Type *ownedArray;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct RefCount
|
struct ReferenceCount
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
int count;
|
int count;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
RefCount() :count(0) { }
|
ReferenceCount() :count(0) { }
|
||||||
RefCount(const RefCount& o) { count = o.count; }
|
ReferenceCount(const ReferenceCount& o) { count = o.count; }
|
||||||
const RefCount& operator=(const RefCount& o) { count = o.count; return *this;}
|
inline const ReferenceCount& operator=(const ReferenceCount& o) { count = o.count; return *this;}
|
||||||
void Incref() { this->count++; }
|
inline void Incref() { this->count++; }
|
||||||
void Incref(int c) { this->count += c; }
|
inline void Incref(int c) { this->count += c; }
|
||||||
int Decref() { return --this->count;}
|
inline int Decref() { return --this->count;}
|
||||||
void Reset() { this->count = 0; }
|
inline void Reset() { this->count = 0; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
namespace SmartPointer
|
||||||
|
{
|
||||||
|
//! Smart pointer for a regular object.
|
||||||
|
/**
|
||||||
|
* Regular objects, objects that is deleted normaly (ie not COM objects, or array pointers)
|
||||||
|
* can use this class to easy the use of dynamic memory
|
||||||
|
*/
|
||||||
|
template<typename T>
|
||||||
|
struct StdSmartPointer
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
ReferenceCount *_rc;
|
||||||
|
T *_ptr;
|
||||||
|
|
||||||
|
/** Destroys the pointer and returns the memory allocated. */
|
||||||
|
void Destroy();
|
||||||
|
|
||||||
|
public:
|
||||||
|
StdSmartPointer();
|
||||||
|
StdSmartPointer(T* p);
|
||||||
|
StdSmartPointer(const StdSmartPointer& d);
|
||||||
|
virtual~StdSmartPointer();
|
||||||
|
StdSmartPointer<T>& operator= (const StdSmartPointer<T>& p);
|
||||||
|
StdSmartPointer<T>& operator= (T* p);
|
||||||
|
bool operator== (const StdSmartPointer<T>& d);
|
||||||
|
bool operator== (const T& p);
|
||||||
|
T& operator* ();
|
||||||
|
T* operator-> ();
|
||||||
|
operator T* ();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the connected pointer */
|
||||||
|
T* Get();
|
||||||
|
|
||||||
|
/** Checks if the pointer is valid (not NULL)
|
||||||
|
Returns true for valid, else false. */
|
||||||
|
bool IsValid();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace String
|
namespace String
|
||||||
|
|
|
@ -0,0 +1,319 @@
|
||||||
|
//!//!//!//!//!//!//!//!//!//!//!//!//!//!//!//!//!//!//!//!//!//!//!
|
||||||
|
// Utility Collection of Miscellanious Handy Functions
|
||||||
|
// © Dan Andersson 2013
|
||||||
|
<<<<<<< HEAD
|
||||||
|
//!//!//!//!//!//!//!//!//!//!//!//!//!//!//!//!//!//!//!//!//!//!//!
|
||||||
|
=======
|
||||||
|
// © Dennis Andersen 2013
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
>>>>>>> 48c812b0338b859aa6c00c8504dd2f16a4bb44f9
|
||||||
|
|
||||||
|
#ifndef UTILITIES_H
|
||||||
|
#define UTILITIES_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <istream>
|
||||||
|
#include <vector>
|
||||||
|
#include <locale>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
namespace Utility
|
||||||
|
{
|
||||||
|
namespace DynamicMemory
|
||||||
|
{
|
||||||
|
//! If dynamicInstance is not NULL, then delete
|
||||||
|
template<typename Type> void SafeDeleteInstance( Type *dynamicInstance );
|
||||||
|
|
||||||
|
//! If dynamicArray is not NULL, then delete []
|
||||||
|
template<typename Type> void SafeDeleteArray( Type dynamicArray[] );
|
||||||
|
|
||||||
|
//! Wrapper to safely transfer dynamic ownership/responsibility
|
||||||
|
template<typename Type> struct UniquePointer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//! Assigns assignedInstance ownership to this UniquePonter, old owned instance will be deleted.
|
||||||
|
//! If NULL is assigned is equavalent with clearing all responsibilities from this UniquePointer.
|
||||||
|
UniquePointer( Type *assignedInstance = NULL );
|
||||||
|
|
||||||
|
//! Will auto delete assigned dynamic instance.
|
||||||
|
~UniquePointer();
|
||||||
|
|
||||||
|
//! Assigns assignedInstance ownership to this UniquePonter, old owned instance will be deleted.
|
||||||
|
//! If NULL is assigned is equavalent with clearing all responsibilities from this UniquePointer.
|
||||||
|
UniquePointer<Type> & operator = ( Type *assignedInstance );
|
||||||
|
|
||||||
|
//! Transfers assignedInstance ownership from donor to this UniquePonter, old owned instance will be deleted.
|
||||||
|
//! If donor had nothing, is equavalent with clearing all responsibilities from this UniquePointer.
|
||||||
|
UniquePointer<Type> & operator = ( const UniquePointer<Type> &donor );
|
||||||
|
|
||||||
|
//! Access the assigned dynamic instance. Will crash if nothing there
|
||||||
|
operator Type* ();
|
||||||
|
|
||||||
|
//! Access the assigned dynamic instance. Will crash if nothing there
|
||||||
|
operator const Type* () const;
|
||||||
|
|
||||||
|
//! Access members of the assigned dynamic instance. Will crash if nothing there
|
||||||
|
Type * operator -> ();
|
||||||
|
|
||||||
|
//! Access members of the assigned dynamic instance. Will crash if nothing there
|
||||||
|
const Type * operator -> () const;
|
||||||
|
|
||||||
|
//! If true, this UniquePointer have a current ownership/responsibility of a dynamic instance.
|
||||||
|
operator bool () const;
|
||||||
|
|
||||||
|
//! This UniquePointer drops all claims of ownership/responsibility and returns the dynamic instance. Now it is your responsibility to delete.
|
||||||
|
Type* Release();
|
||||||
|
|
||||||
|
//! (inline) If true, this UniquePointer have a current ownership/responsibility of a dynamic instance.
|
||||||
|
bool HaveOwnership() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
mutable Type *ownedInstance;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename Type>
|
||||||
|
struct UniqueArray
|
||||||
|
{ //! Wrapper to safely transfer dynamic ownership/responsibility
|
||||||
|
public:
|
||||||
|
//! Assigns assignedInstance ownership to this UniquePonter, old owned array will be deleted.
|
||||||
|
//! If NULL is assigned is equavalent with clearing all responsibilities from this UniqueArray.
|
||||||
|
UniqueArray( Type assignedArray[] = NULL );
|
||||||
|
|
||||||
|
//! Will auto delete assigned dynamic array.
|
||||||
|
~UniqueArray();
|
||||||
|
|
||||||
|
//! Assigns assignedInstance ownership to this UniquePonter, old owned array will be deleted.
|
||||||
|
//! If NULL is assigned is equavalent with clearing all responsibilities from this UniqueArray.
|
||||||
|
UniqueArray<Type> & operator = ( Type assignedArray[] );
|
||||||
|
|
||||||
|
//! Transfers assignedInstance ownership from donor to this UniquePonter, old owned array will be deleted.
|
||||||
|
//! If donor had nothing, is equavalent with clearing all responsibilities from this UniqueArray.
|
||||||
|
UniqueArray<Type> & operator = ( const UniqueArray<Type> &donor );
|
||||||
|
|
||||||
|
//! Accesses the instance at index i of this UniqeArray's owned dynamic array.
|
||||||
|
//! Will crash if out-of-bound or there is no assigned array.
|
||||||
|
template<typename Index> Type & operator [] ( Index i );
|
||||||
|
|
||||||
|
//! Accesses the instance at index i of this UniqeArray's owned dynamic array.
|
||||||
|
//! Will crash if out-of-bound or there is no assigned array.
|
||||||
|
template<typename Index> const Type & operator [] ( Index i ) const;
|
||||||
|
|
||||||
|
//! If true, this UniqueArray have a current ownership/responsibility of a dynamic instance.
|
||||||
|
operator bool () const;
|
||||||
|
|
||||||
|
//! This UniqueArray drops all claims of ownership/responsibility and returns the dynamic array. Now it is your responsibility to delete.
|
||||||
|
Type* Release();
|
||||||
|
|
||||||
|
//! (inline) If true, this UniqueArray have a current ownership/responsibility of a dynamic array.
|
||||||
|
bool HaveOwnership() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
mutable Type *ownedArray;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ReferenceCount
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
int count;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ReferenceCount() :count(0) { }
|
||||||
|
ReferenceCount(const ReferenceCount& o) { count = o.count; }
|
||||||
|
inline const ReferenceCount& operator=(const ReferenceCount& o) { count = o.count; return *this;}
|
||||||
|
inline void Incref() { this->count++; }
|
||||||
|
inline void Incref(int c) { this->count += c; }
|
||||||
|
inline int Decref() { return --this->count;}
|
||||||
|
inline void Reset() { this->count = 0; }
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace SmartPointer
|
||||||
|
{
|
||||||
|
//! Smart pointer for a regular object.
|
||||||
|
/**
|
||||||
|
* Regular objects, objects that is deleted normaly (ie not COM objects, or array pointers)
|
||||||
|
* can use this class to easy the use of dynamic memory
|
||||||
|
*/
|
||||||
|
template<typename T>
|
||||||
|
struct StdSmartPointer
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
ReferenceCount *_rc;
|
||||||
|
T *_ptr;
|
||||||
|
|
||||||
|
/** Destroys the pointer and returns the memory allocated. */
|
||||||
|
void Destroy();
|
||||||
|
|
||||||
|
public:
|
||||||
|
StdSmartPointer();
|
||||||
|
StdSmartPointer(T* p);
|
||||||
|
StdSmartPointer(const StdSmartPointer& d);
|
||||||
|
virtual~StdSmartPointer();
|
||||||
|
StdSmartPointer<T>& operator= (const StdSmartPointer<T>& p);
|
||||||
|
StdSmartPointer<T>& operator= (T* p);
|
||||||
|
bool operator== (const StdSmartPointer<T>& d);
|
||||||
|
bool operator== (const T& p);
|
||||||
|
T& operator* ();
|
||||||
|
T* operator-> ();
|
||||||
|
operator T* ();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the connected pointer */
|
||||||
|
T* Get();
|
||||||
|
|
||||||
|
/** Checks if the pointer is valid (not NULL)
|
||||||
|
Returns true for valid, else false. */
|
||||||
|
bool IsValid();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace String
|
||||||
|
{
|
||||||
|
// string
|
||||||
|
|
||||||
|
::std::vector<::std::string> & Split( ::std::vector<::std::string> &output, const ::std::string &str, char delim, ::std::string::size_type offset = 0 );
|
||||||
|
::std::vector<::std::string> & Split( ::std::vector<::std::string> &output, const ::std::string &str, const ::std::string &delim, ::std::string::size_type offset = 0 );
|
||||||
|
::std::vector<::std::string> & Split( ::std::vector<::std::string> &output, const ::std::string &str, const ::std::vector<::std::string> &delim, ::std::string::size_type offset = 0 );
|
||||||
|
::std::string Trim( const ::std::string &str );
|
||||||
|
::std::string & ToLowerCase( ::std::string &output, const ::std::string &str );
|
||||||
|
::std::string & ToLowerCase( ::std::string &str );
|
||||||
|
::std::string & ToUpperCase( ::std::string &output, const ::std::string &str );
|
||||||
|
::std::string & ToUpperCase( ::std::string &str );
|
||||||
|
::std::string & ExtractDirPath( ::std::string &output, const ::std::string &file, char dirDelimeter );
|
||||||
|
::std::string & ExtractDirPath( ::std::string &output, const ::std::string &file, const ::std::string &dirDelimeter );
|
||||||
|
::std::string & ReplaceCharacters( ::std::string &str, char characterToReplace, char newCharacter, const ::std::string::size_type &offset = 0, const ::std::string::size_type &end = ::std::string::npos );
|
||||||
|
|
||||||
|
// wstring
|
||||||
|
|
||||||
|
::std::vector<::std::wstring> & Split( ::std::vector<::std::wstring> &output, const ::std::wstring &str, char delim, ::std::wstring::size_type offset = 0 );
|
||||||
|
::std::vector<::std::wstring> & Split( ::std::vector<::std::wstring> &output, const ::std::wstring &str, const ::std::wstring &delim, ::std::wstring::size_type offset = 0 );
|
||||||
|
::std::vector<::std::wstring> & Split( ::std::vector<::std::wstring> &output, const ::std::wstring &str, const ::std::vector<::std::wstring> &delim, ::std::wstring::size_type offset = 0 );
|
||||||
|
::std::wstring & wToLowerCase( ::std::wstring &output, const ::std::wstring &str );
|
||||||
|
::std::wstring & wToLowerCase( ::std::wstring &str );
|
||||||
|
|
||||||
|
//To wstring
|
||||||
|
|
||||||
|
::std::wstring & StringToWstring( const ::std::string &str, ::std::wstring &wstr );
|
||||||
|
::std::string & WStringToString( const ::std::wstring &wstr, ::std::string &str );
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Stream
|
||||||
|
{
|
||||||
|
float* ReadFloats( float *output, ::std::istream &input, unsigned int numFloats );
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace StaticArray
|
||||||
|
{
|
||||||
|
template<typename ScalarType, unsigned int num>
|
||||||
|
inline unsigned int NumElementsOf( const ScalarType(&)[num] )
|
||||||
|
{ return num; }
|
||||||
|
|
||||||
|
template<typename ScalarType, unsigned int num>
|
||||||
|
inline ScalarType & FirstElementOf( ScalarType (&arr)[num] )
|
||||||
|
{ return arr[0]; }
|
||||||
|
|
||||||
|
template<typename ScalarType, unsigned int num>
|
||||||
|
inline ScalarType & LastElementOf( ScalarType (&arr)[num] )
|
||||||
|
{ return arr[num-1]; }
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Element
|
||||||
|
{
|
||||||
|
template<typename ScalarType>
|
||||||
|
inline void Swap( ScalarType &elementA, ScalarType &elementB, ScalarType &swapSpace )
|
||||||
|
{ swapSpace = elementA; elementA = elementB; elementB = swapSpace; }
|
||||||
|
|
||||||
|
template<typename ScalarType>
|
||||||
|
inline void Swap( ScalarType &elementA, ScalarType &elementB )
|
||||||
|
{ ScalarType swapSpace; Swap( elementA, elementB, swapSpace ); }
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Value
|
||||||
|
{
|
||||||
|
using ::std::numeric_limits;
|
||||||
|
|
||||||
|
template<typename ValueType>
|
||||||
|
inline ValueType Abs( const ValueType &value )
|
||||||
|
{ return value < 0 ? value * -1 : value; }
|
||||||
|
|
||||||
|
template<typename ValueType>
|
||||||
|
inline ValueType Max( const ValueType &valueA, const ValueType &valueB )
|
||||||
|
{ return valueA > valueB ? valueA : valueB; }
|
||||||
|
|
||||||
|
template<typename ValueType>
|
||||||
|
inline ValueType Min( const ValueType &valueA, const ValueType &valueB )
|
||||||
|
{ return valueA < valueB ? valueA : valueB; }
|
||||||
|
|
||||||
|
template<typename ValueType>
|
||||||
|
inline ValueType Average( const ValueType &valueA, const ValueType &valueB )
|
||||||
|
{ return (valueA + valueB) * 0.5f; }
|
||||||
|
|
||||||
|
template<typename ValueType>
|
||||||
|
inline ValueType AverageWithDelta( const ValueType &origin, const ValueType &delta )
|
||||||
|
{ return origin + (delta * 0.5f); }
|
||||||
|
|
||||||
|
template<typename ValueType>
|
||||||
|
inline ValueType Radian( const ValueType °ree )
|
||||||
|
{ return degree * (3.1415926535897932384626433832795f / 180.0f); }
|
||||||
|
|
||||||
|
template<typename ValueType>
|
||||||
|
inline ValueType Degree( const ValueType &radian )
|
||||||
|
{ return radian * (180.0f / 3.1415926535897932384626433832795f); }
|
||||||
|
|
||||||
|
// SPECIALIZATIONS //!//!//!//!//!//!//!//!//!//!//!//!//!//!
|
||||||
|
|
||||||
|
template<> inline char Average<char>( const char &valueA, const char &valueB )
|
||||||
|
{ return (valueA + valueB) >> 1; }
|
||||||
|
|
||||||
|
template<> inline unsigned char Average<unsigned char>( const unsigned char &valueA, const unsigned char &valueB )
|
||||||
|
{ return (valueA + valueB) >> 1; }
|
||||||
|
|
||||||
|
template<> inline int Average<int>( const int &valueA, const int &valueB )
|
||||||
|
{ return (valueA + valueB) >> 1; }
|
||||||
|
|
||||||
|
template<> inline unsigned int Average<unsigned int>( const unsigned int &valueA, const unsigned int &valueB )
|
||||||
|
{ return (valueA + valueB) >> 1; }
|
||||||
|
|
||||||
|
template<> inline long Average<long>( const long &valueA, const long &valueB )
|
||||||
|
{ return (valueA + valueB) >> 1; }
|
||||||
|
|
||||||
|
template<> inline unsigned long Average<unsigned long>( const unsigned long &valueA, const unsigned long &valueB )
|
||||||
|
{ return (valueA + valueB) >> 1; }
|
||||||
|
|
||||||
|
template<> inline long long Average<long long>( const long long &valueA, const long long &valueB )
|
||||||
|
{ return (valueA + valueB) >> 1; }
|
||||||
|
|
||||||
|
template<> inline unsigned long long Average<unsigned long long>( const unsigned long long &valueA, const unsigned long long &valueB )
|
||||||
|
{ return (valueA + valueB) >> 1; }
|
||||||
|
|
||||||
|
template<> inline char AverageWithDelta<char>( const char &origin, const char &delta )
|
||||||
|
{ return origin + (delta >> 1); }
|
||||||
|
|
||||||
|
template<> inline unsigned char AverageWithDelta<unsigned char>( const unsigned char &origin, const unsigned char &delta )
|
||||||
|
{ return origin + (delta >> 1); }
|
||||||
|
|
||||||
|
template<> inline int AverageWithDelta<int>( const int &origin, const int &delta )
|
||||||
|
{ return origin + (delta >> 1); }
|
||||||
|
|
||||||
|
template<> inline unsigned int AverageWithDelta<unsigned int>( const unsigned int &origin, const unsigned int &delta )
|
||||||
|
{ return origin + (delta >> 1); }
|
||||||
|
|
||||||
|
template<> inline long AverageWithDelta<long>( const long &origin, const long &delta )
|
||||||
|
{ return origin + (delta >> 1); }
|
||||||
|
|
||||||
|
template<> inline unsigned long AverageWithDelta<unsigned long>( const unsigned long &origin, const unsigned long &delta )
|
||||||
|
{ return origin + (delta >> 1); }
|
||||||
|
|
||||||
|
template<> inline long long AverageWithDelta<long long>( const long long &origin, const long long &delta )
|
||||||
|
{ return origin + (delta >> 1); }
|
||||||
|
|
||||||
|
template<> inline unsigned long long AverageWithDelta<unsigned long long>( const unsigned long long &origin, const unsigned long long &delta )
|
||||||
|
{ return origin + (delta >> 1); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "Utilities-InlineImpl.h"
|
||||||
|
|
||||||
|
#endif
|
|
@ -159,7 +159,7 @@ namespace Oyster
|
||||||
Compute
|
Compute
|
||||||
};
|
};
|
||||||
|
|
||||||
static void SetShaderEffect(ShaderEffect);
|
static void SetShaderEffect(ShaderEffect&);
|
||||||
|
|
||||||
static void CreateInputLayout(const D3D11_INPUT_ELEMENT_DESC *desc, int ElementCount,int VertexIndex,ID3D11InputLayout *&Layout);
|
static void CreateInputLayout(const D3D11_INPUT_ELEMENT_DESC *desc, int ElementCount,int VertexIndex,ID3D11InputLayout *&Layout);
|
||||||
|
|
||||||
|
|
|
@ -328,7 +328,7 @@ namespace Oyster
|
||||||
/// \todo smart Set ie. not resetting the shader
|
/// \todo smart Set ie. not resetting the shader
|
||||||
/// \todo research states
|
/// \todo research states
|
||||||
/// \todo smart buffer set
|
/// \todo smart buffer set
|
||||||
void Core::ShaderManager::SetShaderEffect(ShaderEffect se)
|
void Core::ShaderManager::SetShaderEffect(ShaderEffect& se)
|
||||||
{
|
{
|
||||||
Set::Pixel(se.Shaders.Pixel);
|
Set::Pixel(se.Shaders.Pixel);
|
||||||
Set::Vertex(se.Shaders.Vertex);
|
Set::Vertex(se.Shaders.Vertex);
|
||||||
|
|
|
@ -118,8 +118,10 @@ Oyster::Graphics::Model::ModelInfo* OBJReader::toModel()
|
||||||
modelInfo->VertexCount = (int)desc.NumElements;
|
modelInfo->VertexCount = (int)desc.NumElements;
|
||||||
modelInfo->Vertices = b;
|
modelInfo->Vertices = b;
|
||||||
|
|
||||||
//Oyster::Resource::OysterResource::LoadResource(L"Normal.png",(Oyster::Resource::CustomLoadFunction)Oyster::Graphics::Loading::LoadTexture);
|
|
||||||
|
|
||||||
|
Oyster::Resource::OHRESOURCE diffuse = Oyster::Resource::OysterResource::LoadResource(L"bth.png",Oyster::Graphics::Loading::LoadTexture);
|
||||||
|
//Oyster::Resource::OysterResource::LoadResource(L"Normal.png",(Oyster::Resource::CustomLoadFunction)Oyster::Graphics::Loading::LoadTexture);
|
||||||
|
modelInfo->Material.push_back((ID3D11ShaderResourceView*)diffuse);
|
||||||
|
|
||||||
return modelInfo;
|
return modelInfo;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,729 @@
|
||||||
#include "TextureLoader.h"
|
#include "TextureLoader.h"
|
||||||
#include "..\Core\Dx11Includes.h"
|
#include "..\Core\Dx11Includes.h"
|
||||||
|
#include "..\Core\Core.h"
|
||||||
|
|
||||||
Oyster::Resource::CustomData* Oyster::Graphics::Loading::LoadTexture()
|
HRESULT CreateWICTextureFromFileEx( ID3D11Device* d3dDevice,
|
||||||
|
ID3D11DeviceContext* d3dContext,
|
||||||
|
const wchar_t* fileName,
|
||||||
|
size_t maxsize,
|
||||||
|
D3D11_USAGE usage,
|
||||||
|
unsigned int bindFlags,
|
||||||
|
unsigned int cpuAccessFlags,
|
||||||
|
unsigned int miscFlags,
|
||||||
|
bool forceSRGB,
|
||||||
|
ID3D11Resource** texture,
|
||||||
|
ID3D11ShaderResourceView** textureView );
|
||||||
|
|
||||||
|
const Oyster::Resource::CustomData& Oyster::Graphics::Loading::LoadTexture(const wchar_t filename[])
|
||||||
{
|
{
|
||||||
return NULL;
|
ID3D11ShaderResourceView* srv;
|
||||||
|
Oyster::Resource::CustomData Ret;
|
||||||
|
HRESULT hr = CreateWICTextureFromFileEx(Core::device,Core::deviceContext,filename,0,D3D11_USAGE_DEFAULT,D3D11_BIND_SHADER_RESOURCE,0,0,false,NULL,&srv);
|
||||||
|
if(hr!=S_OK)
|
||||||
|
{
|
||||||
|
memset(&Ret,0,sizeof(Ret));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Ret.loadedData = srv;
|
||||||
|
Ret.resourceUnloadFnc = Loading::UnloadTexture;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Oyster::Graphics::Loading::UnloadTexture(void* data)
|
||||||
|
{
|
||||||
|
ID3D11ShaderResourceView* srv = (ID3D11ShaderResourceView*)data;
|
||||||
|
SAFE_RELEASE(srv);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#include <wrl.h>
|
||||||
|
#include <memory>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) || defined(_WIN7_PLATFORM_UPDATE)
|
||||||
|
#include <d2d1.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable : 4005)
|
||||||
|
#include <wincodec.h>
|
||||||
|
#pragma warning(pop)
|
||||||
|
|
||||||
|
|
||||||
|
template<class T> class ScopedObject : public Microsoft::WRL::ComPtr<T> {};
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------------
|
||||||
|
// WIC Pixel Format Translation Data
|
||||||
|
//-------------------------------------------------------------------------------------
|
||||||
|
struct WICTranslate
|
||||||
|
{
|
||||||
|
GUID wic;
|
||||||
|
DXGI_FORMAT format;
|
||||||
|
};
|
||||||
|
|
||||||
|
static WICTranslate g_WICFormats[] =
|
||||||
|
{
|
||||||
|
{ GUID_WICPixelFormat128bppRGBAFloat, DXGI_FORMAT_R32G32B32A32_FLOAT },
|
||||||
|
|
||||||
|
{ GUID_WICPixelFormat64bppRGBAHalf, DXGI_FORMAT_R16G16B16A16_FLOAT },
|
||||||
|
{ GUID_WICPixelFormat64bppRGBA, DXGI_FORMAT_R16G16B16A16_UNORM },
|
||||||
|
|
||||||
|
{ GUID_WICPixelFormat32bppRGBA, DXGI_FORMAT_R8G8B8A8_UNORM },
|
||||||
|
{ GUID_WICPixelFormat32bppBGRA, DXGI_FORMAT_B8G8R8A8_UNORM }, // DXGI 1.1
|
||||||
|
{ GUID_WICPixelFormat32bppBGR, DXGI_FORMAT_B8G8R8X8_UNORM }, // DXGI 1.1
|
||||||
|
|
||||||
|
{ GUID_WICPixelFormat32bppRGBA1010102XR, DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM }, // DXGI 1.1
|
||||||
|
{ GUID_WICPixelFormat32bppRGBA1010102, DXGI_FORMAT_R10G10B10A2_UNORM },
|
||||||
|
|
||||||
|
#ifdef DXGI_1_2_FORMATS
|
||||||
|
|
||||||
|
{ GUID_WICPixelFormat16bppBGRA5551, DXGI_FORMAT_B5G5R5A1_UNORM },
|
||||||
|
{ GUID_WICPixelFormat16bppBGR565, DXGI_FORMAT_B5G6R5_UNORM },
|
||||||
|
|
||||||
|
#endif // DXGI_1_2_FORMATS
|
||||||
|
|
||||||
|
{ GUID_WICPixelFormat32bppGrayFloat, DXGI_FORMAT_R32_FLOAT },
|
||||||
|
{ GUID_WICPixelFormat16bppGrayHalf, DXGI_FORMAT_R16_FLOAT },
|
||||||
|
{ GUID_WICPixelFormat16bppGray, DXGI_FORMAT_R16_UNORM },
|
||||||
|
{ GUID_WICPixelFormat8bppGray, DXGI_FORMAT_R8_UNORM },
|
||||||
|
|
||||||
|
{ GUID_WICPixelFormat8bppAlpha, DXGI_FORMAT_A8_UNORM },
|
||||||
|
};
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------------
|
||||||
|
// WIC Pixel Format nearest conversion table
|
||||||
|
//-------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
struct WICConvert
|
||||||
|
{
|
||||||
|
GUID source;
|
||||||
|
GUID target;
|
||||||
|
};
|
||||||
|
|
||||||
|
static WICConvert g_WICConvert[] =
|
||||||
|
{
|
||||||
|
// Note target GUID in this conversion table must be one of those directly supported formats (above).
|
||||||
|
|
||||||
|
{ GUID_WICPixelFormatBlackWhite, GUID_WICPixelFormat8bppGray }, // DXGI_FORMAT_R8_UNORM
|
||||||
|
|
||||||
|
{ GUID_WICPixelFormat1bppIndexed, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
|
||||||
|
{ GUID_WICPixelFormat2bppIndexed, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
|
||||||
|
{ GUID_WICPixelFormat4bppIndexed, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
|
||||||
|
{ GUID_WICPixelFormat8bppIndexed, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
|
||||||
|
|
||||||
|
{ GUID_WICPixelFormat2bppGray, GUID_WICPixelFormat8bppGray }, // DXGI_FORMAT_R8_UNORM
|
||||||
|
{ GUID_WICPixelFormat4bppGray, GUID_WICPixelFormat8bppGray }, // DXGI_FORMAT_R8_UNORM
|
||||||
|
|
||||||
|
{ GUID_WICPixelFormat16bppGrayFixedPoint, GUID_WICPixelFormat16bppGrayHalf }, // DXGI_FORMAT_R16_FLOAT
|
||||||
|
{ GUID_WICPixelFormat32bppGrayFixedPoint, GUID_WICPixelFormat32bppGrayFloat }, // DXGI_FORMAT_R32_FLOAT
|
||||||
|
|
||||||
|
#ifdef DXGI_1_2_FORMATS
|
||||||
|
|
||||||
|
{ GUID_WICPixelFormat16bppBGR555, GUID_WICPixelFormat16bppBGRA5551 }, // DXGI_FORMAT_B5G5R5A1_UNORM
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
{ GUID_WICPixelFormat16bppBGR555, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
|
||||||
|
{ GUID_WICPixelFormat16bppBGRA5551, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
|
||||||
|
{ GUID_WICPixelFormat16bppBGR565, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
|
||||||
|
|
||||||
|
#endif // DXGI_1_2_FORMATS
|
||||||
|
|
||||||
|
{ GUID_WICPixelFormat32bppBGR101010, GUID_WICPixelFormat32bppRGBA1010102 }, // DXGI_FORMAT_R10G10B10A2_UNORM
|
||||||
|
|
||||||
|
{ GUID_WICPixelFormat24bppBGR, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
|
||||||
|
{ GUID_WICPixelFormat24bppRGB, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
|
||||||
|
{ GUID_WICPixelFormat32bppPBGRA, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
|
||||||
|
{ GUID_WICPixelFormat32bppPRGBA, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
|
||||||
|
|
||||||
|
{ GUID_WICPixelFormat48bppRGB, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM
|
||||||
|
{ GUID_WICPixelFormat48bppBGR, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM
|
||||||
|
{ GUID_WICPixelFormat64bppBGRA, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM
|
||||||
|
{ GUID_WICPixelFormat64bppPRGBA, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM
|
||||||
|
{ GUID_WICPixelFormat64bppPBGRA, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM
|
||||||
|
|
||||||
|
{ GUID_WICPixelFormat48bppRGBFixedPoint, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT
|
||||||
|
{ GUID_WICPixelFormat48bppBGRFixedPoint, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT
|
||||||
|
{ GUID_WICPixelFormat64bppRGBAFixedPoint, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT
|
||||||
|
{ GUID_WICPixelFormat64bppBGRAFixedPoint, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT
|
||||||
|
{ GUID_WICPixelFormat64bppRGBFixedPoint, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT
|
||||||
|
{ GUID_WICPixelFormat64bppRGBHalf, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT
|
||||||
|
{ GUID_WICPixelFormat48bppRGBHalf, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT
|
||||||
|
|
||||||
|
{ GUID_WICPixelFormat128bppPRGBAFloat, GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT
|
||||||
|
{ GUID_WICPixelFormat128bppRGBFloat, GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT
|
||||||
|
{ GUID_WICPixelFormat128bppRGBAFixedPoint, GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT
|
||||||
|
{ GUID_WICPixelFormat128bppRGBFixedPoint, GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT
|
||||||
|
{ GUID_WICPixelFormat32bppRGBE, GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT
|
||||||
|
|
||||||
|
{ GUID_WICPixelFormat32bppCMYK, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
|
||||||
|
{ GUID_WICPixelFormat64bppCMYK, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM
|
||||||
|
{ GUID_WICPixelFormat40bppCMYKAlpha, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM
|
||||||
|
{ GUID_WICPixelFormat80bppCMYKAlpha, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM
|
||||||
|
|
||||||
|
#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) || defined(_WIN7_PLATFORM_UPDATE)
|
||||||
|
{ GUID_WICPixelFormat32bppRGB, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
|
||||||
|
{ GUID_WICPixelFormat64bppRGB, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM
|
||||||
|
{ GUID_WICPixelFormat64bppPRGBAHalf, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// We don't support n-channel formats
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool g_WIC2 = false;
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
bool _IsWIC2()
|
||||||
|
{
|
||||||
|
return g_WIC2;
|
||||||
|
}
|
||||||
|
|
||||||
|
IWICImagingFactory* _GetWIC()
|
||||||
|
{
|
||||||
|
static IWICImagingFactory* s_Factory = nullptr;
|
||||||
|
|
||||||
|
if ( s_Factory )
|
||||||
|
return s_Factory;
|
||||||
|
|
||||||
|
#if(_WIN32_WINNT >= _WIN32_WINNT_WIN8) || defined(_WIN7_PLATFORM_UPDATE)
|
||||||
|
HRESULT hr = CoCreateInstance(
|
||||||
|
CLSID_WICImagingFactory2,
|
||||||
|
nullptr,
|
||||||
|
CLSCTX_INPROC_SERVER,
|
||||||
|
__uuidof(IWICImagingFactory2),
|
||||||
|
(LPVOID*)&s_Factory
|
||||||
|
);
|
||||||
|
|
||||||
|
if ( SUCCEEDED(hr) )
|
||||||
|
{
|
||||||
|
// WIC2 is available on Windows 8 and Windows 7 SP1 with KB 2670838 installed
|
||||||
|
g_WIC2 = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hr = CoCreateInstance(
|
||||||
|
CLSID_WICImagingFactory1,
|
||||||
|
nullptr,
|
||||||
|
CLSCTX_INPROC_SERVER,
|
||||||
|
__uuidof(IWICImagingFactory),
|
||||||
|
(LPVOID*)&s_Factory
|
||||||
|
);
|
||||||
|
|
||||||
|
if ( FAILED(hr) )
|
||||||
|
{
|
||||||
|
s_Factory = nullptr;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
HRESULT hr = CoCreateInstance(
|
||||||
|
CLSID_WICImagingFactory,
|
||||||
|
nullptr,
|
||||||
|
CLSCTX_INPROC_SERVER,
|
||||||
|
__uuidof(IWICImagingFactory),
|
||||||
|
(LPVOID*)&s_Factory
|
||||||
|
);
|
||||||
|
|
||||||
|
if ( FAILED(hr) )
|
||||||
|
{
|
||||||
|
s_Factory = nullptr;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return s_Factory;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------------
|
||||||
|
static DXGI_FORMAT _WICToDXGI( const GUID& guid )
|
||||||
|
{
|
||||||
|
for( size_t i=0; i < _countof(g_WICFormats); ++i )
|
||||||
|
{
|
||||||
|
if ( memcmp( &g_WICFormats[i].wic, &guid, sizeof(GUID) ) == 0 )
|
||||||
|
return g_WICFormats[i].format;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) || defined(_WIN7_PLATFORM_UPDATE)
|
||||||
|
if ( g_WIC2 )
|
||||||
|
{
|
||||||
|
if ( memcmp( &GUID_WICPixelFormat96bppRGBFloat, &guid, sizeof(GUID) ) == 0 )
|
||||||
|
return DXGI_FORMAT_R32G32B32_FLOAT;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return DXGI_FORMAT_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------------
|
||||||
|
static size_t _WICBitsPerPixel( REFGUID targetGuid )
|
||||||
|
{
|
||||||
|
IWICImagingFactory* pWIC = _GetWIC();
|
||||||
|
if ( !pWIC )
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
ScopedObject<IWICComponentInfo> cinfo;
|
||||||
|
if ( FAILED( pWIC->CreateComponentInfo( targetGuid, &cinfo ) ) )
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
WICComponentType type;
|
||||||
|
if ( FAILED( cinfo->GetComponentType( &type ) ) )
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if ( type != WICPixelFormat )
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
Microsoft::WRL::ComPtr<IWICPixelFormatInfo> pfinfo;
|
||||||
|
if ( FAILED( cinfo.As( &pfinfo ) ) )
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
UINT bpp;
|
||||||
|
if ( FAILED( pfinfo->GetBitsPerPixel( &bpp ) ) )
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return bpp;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
static DXGI_FORMAT MakeSRGB( _In_ DXGI_FORMAT format )
|
||||||
|
{
|
||||||
|
switch( format )
|
||||||
|
{
|
||||||
|
case DXGI_FORMAT_R8G8B8A8_UNORM:
|
||||||
|
return DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
|
||||||
|
|
||||||
|
case DXGI_FORMAT_BC1_UNORM:
|
||||||
|
return DXGI_FORMAT_BC1_UNORM_SRGB;
|
||||||
|
|
||||||
|
case DXGI_FORMAT_BC2_UNORM:
|
||||||
|
return DXGI_FORMAT_BC2_UNORM_SRGB;
|
||||||
|
|
||||||
|
case DXGI_FORMAT_BC3_UNORM:
|
||||||
|
return DXGI_FORMAT_BC3_UNORM_SRGB;
|
||||||
|
|
||||||
|
case DXGI_FORMAT_B8G8R8A8_UNORM:
|
||||||
|
return DXGI_FORMAT_B8G8R8A8_UNORM_SRGB;
|
||||||
|
|
||||||
|
case DXGI_FORMAT_B8G8R8X8_UNORM:
|
||||||
|
return DXGI_FORMAT_B8G8R8X8_UNORM_SRGB;
|
||||||
|
|
||||||
|
case DXGI_FORMAT_BC7_UNORM:
|
||||||
|
return DXGI_FORMAT_BC7_UNORM_SRGB;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return format;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT CreateTextureFromWIC( _In_ ID3D11Device* d3dDevice,
|
||||||
|
_In_opt_ ID3D11DeviceContext* d3dContext,
|
||||||
|
_In_ IWICBitmapFrameDecode *frame,
|
||||||
|
_In_ size_t maxsize,
|
||||||
|
_In_ D3D11_USAGE usage,
|
||||||
|
_In_ unsigned int bindFlags,
|
||||||
|
_In_ unsigned int cpuAccessFlags,
|
||||||
|
_In_ unsigned int miscFlags,
|
||||||
|
_In_ bool forceSRGB,
|
||||||
|
_Out_opt_ ID3D11Resource** texture,
|
||||||
|
_Out_opt_ ID3D11ShaderResourceView** textureView )
|
||||||
|
{
|
||||||
|
UINT width, height;
|
||||||
|
HRESULT hr = frame->GetSize( &width, &height );
|
||||||
|
if ( FAILED(hr) )
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
assert( width > 0 && height > 0 );
|
||||||
|
|
||||||
|
if ( !maxsize )
|
||||||
|
{
|
||||||
|
// This is a bit conservative because the hardware could support larger textures than
|
||||||
|
// the Feature Level defined minimums, but doing it this way is much easier and more
|
||||||
|
// performant for WIC than the 'fail and retry' model used by DDSTextureLoader
|
||||||
|
|
||||||
|
switch( d3dDevice->GetFeatureLevel() )
|
||||||
|
{
|
||||||
|
case D3D_FEATURE_LEVEL_9_1:
|
||||||
|
case D3D_FEATURE_LEVEL_9_2:
|
||||||
|
maxsize = 2048 /*D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION*/;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case D3D_FEATURE_LEVEL_9_3:
|
||||||
|
maxsize = 4096 /*D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION*/;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case D3D_FEATURE_LEVEL_10_0:
|
||||||
|
case D3D_FEATURE_LEVEL_10_1:
|
||||||
|
maxsize = 8192 /*D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION*/;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
maxsize = D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert( maxsize > 0 );
|
||||||
|
|
||||||
|
UINT twidth, theight;
|
||||||
|
if ( width > maxsize || height > maxsize )
|
||||||
|
{
|
||||||
|
float ar = static_cast<float>(height) / static_cast<float>(width);
|
||||||
|
if ( width > height )
|
||||||
|
{
|
||||||
|
twidth = static_cast<UINT>( maxsize );
|
||||||
|
theight = static_cast<UINT>( static_cast<float>(maxsize) * ar );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
theight = static_cast<UINT>( maxsize );
|
||||||
|
twidth = static_cast<UINT>( static_cast<float>(maxsize) / ar );
|
||||||
|
}
|
||||||
|
assert( twidth <= maxsize && theight <= maxsize );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
twidth = width;
|
||||||
|
theight = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine format
|
||||||
|
WICPixelFormatGUID pixelFormat;
|
||||||
|
hr = frame->GetPixelFormat( &pixelFormat );
|
||||||
|
if ( FAILED(hr) )
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
WICPixelFormatGUID convertGUID;
|
||||||
|
memcpy( &convertGUID, &pixelFormat, sizeof(WICPixelFormatGUID) );
|
||||||
|
|
||||||
|
size_t bpp = 0;
|
||||||
|
|
||||||
|
DXGI_FORMAT format = _WICToDXGI( pixelFormat );
|
||||||
|
if ( format == DXGI_FORMAT_UNKNOWN )
|
||||||
|
{
|
||||||
|
if ( memcmp( &GUID_WICPixelFormat96bppRGBFixedPoint, &pixelFormat, sizeof(WICPixelFormatGUID) ) == 0 )
|
||||||
|
{
|
||||||
|
#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) || defined(_WIN7_PLATFORM_UPDATE)
|
||||||
|
if ( g_WIC2 )
|
||||||
|
{
|
||||||
|
memcpy( &convertGUID, &GUID_WICPixelFormat96bppRGBFloat, sizeof(WICPixelFormatGUID) );
|
||||||
|
format = DXGI_FORMAT_R32G32B32_FLOAT;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
memcpy( &convertGUID, &GUID_WICPixelFormat128bppRGBAFloat, sizeof(WICPixelFormatGUID) );
|
||||||
|
format = DXGI_FORMAT_R32G32B32A32_FLOAT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for( size_t i=0; i < _countof(g_WICConvert); ++i )
|
||||||
|
{
|
||||||
|
if ( memcmp( &g_WICConvert[i].source, &pixelFormat, sizeof(WICPixelFormatGUID) ) == 0 )
|
||||||
|
{
|
||||||
|
memcpy( &convertGUID, &g_WICConvert[i].target, sizeof(WICPixelFormatGUID) );
|
||||||
|
|
||||||
|
format = _WICToDXGI( g_WICConvert[i].target );
|
||||||
|
assert( format != DXGI_FORMAT_UNKNOWN );
|
||||||
|
bpp = _WICBitsPerPixel( convertGUID );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( format == DXGI_FORMAT_UNKNOWN )
|
||||||
|
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bpp = _WICBitsPerPixel( pixelFormat );
|
||||||
|
}
|
||||||
|
|
||||||
|
#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) || defined(_WIN7_PLATFORM_UPDATE)
|
||||||
|
if ( (format == DXGI_FORMAT_R32G32B32_FLOAT) && d3dContext != 0 && textureView != 0 )
|
||||||
|
{
|
||||||
|
// Special case test for optional device support for autogen mipchains for R32G32B32_FLOAT
|
||||||
|
UINT fmtSupport = 0;
|
||||||
|
hr = d3dDevice->CheckFormatSupport( DXGI_FORMAT_R32G32B32_FLOAT, &fmtSupport );
|
||||||
|
if ( FAILED(hr) || !( fmtSupport & D3D11_FORMAT_SUPPORT_MIP_AUTOGEN ) )
|
||||||
|
{
|
||||||
|
// Use R32G32B32A32_FLOAT instead which is required for Feature Level 10.0 and up
|
||||||
|
memcpy( &convertGUID, &GUID_WICPixelFormat128bppRGBAFloat, sizeof(WICPixelFormatGUID) );
|
||||||
|
format = DXGI_FORMAT_R32G32B32A32_FLOAT;
|
||||||
|
bpp = 128;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if ( !bpp )
|
||||||
|
return E_FAIL;
|
||||||
|
|
||||||
|
// Handle sRGB formats
|
||||||
|
if ( forceSRGB )
|
||||||
|
{
|
||||||
|
format = MakeSRGB( format );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ScopedObject<IWICMetadataQueryReader> metareader;
|
||||||
|
if ( SUCCEEDED( frame->GetMetadataQueryReader( &metareader ) ) )
|
||||||
|
{
|
||||||
|
GUID containerFormat;
|
||||||
|
if ( SUCCEEDED( metareader->GetContainerFormat( &containerFormat ) ) )
|
||||||
|
{
|
||||||
|
// Check for sRGB colorspace metadata
|
||||||
|
bool sRGB = false;
|
||||||
|
|
||||||
|
PROPVARIANT value;
|
||||||
|
PropVariantInit( &value );
|
||||||
|
|
||||||
|
if ( memcmp( &containerFormat, &GUID_ContainerFormatPng, sizeof(GUID) ) == 0 )
|
||||||
|
{
|
||||||
|
// Check for sRGB chunk
|
||||||
|
if ( SUCCEEDED( metareader->GetMetadataByName( L"/sRGB/RenderingIntent", &value ) ) && value.vt == VT_UI1 )
|
||||||
|
{
|
||||||
|
sRGB = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ( SUCCEEDED( metareader->GetMetadataByName( L"System.Image.ColorSpace", &value ) ) && value.vt == VT_UI2 && value.uiVal == 1 )
|
||||||
|
{
|
||||||
|
sRGB = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
PropVariantClear( &value );
|
||||||
|
|
||||||
|
if ( sRGB )
|
||||||
|
format = MakeSRGB( format );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify our target format is supported by the current device
|
||||||
|
// (handles WDDM 1.0 or WDDM 1.1 device driver cases as well as DirectX 11.0 Runtime without 16bpp format support)
|
||||||
|
UINT support = 0;
|
||||||
|
hr = d3dDevice->CheckFormatSupport( format, &support );
|
||||||
|
if ( FAILED(hr) || !(support & D3D11_FORMAT_SUPPORT_TEXTURE2D) )
|
||||||
|
{
|
||||||
|
// Fallback to RGBA 32-bit format which is supported by all devices
|
||||||
|
memcpy( &convertGUID, &GUID_WICPixelFormat32bppRGBA, sizeof(WICPixelFormatGUID) );
|
||||||
|
format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||||
|
bpp = 32;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allocate temporary memory for image
|
||||||
|
size_t rowPitch = ( twidth * bpp + 7 ) / 8;
|
||||||
|
size_t imageSize = rowPitch * theight;
|
||||||
|
|
||||||
|
std::unique_ptr<uint8_t[]> temp( new (std::nothrow) uint8_t[ imageSize ] );
|
||||||
|
if (!temp)
|
||||||
|
return E_OUTOFMEMORY;
|
||||||
|
|
||||||
|
// Load image data
|
||||||
|
if ( memcmp( &convertGUID, &pixelFormat, sizeof(GUID) ) == 0
|
||||||
|
&& twidth == width
|
||||||
|
&& theight == height )
|
||||||
|
{
|
||||||
|
// No format conversion or resize needed
|
||||||
|
hr = frame->CopyPixels( 0, static_cast<UINT>( rowPitch ), static_cast<UINT>( imageSize ), temp.get() );
|
||||||
|
if ( FAILED(hr) )
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
else if ( twidth != width || theight != height )
|
||||||
|
{
|
||||||
|
// Resize
|
||||||
|
IWICImagingFactory* pWIC = _GetWIC();
|
||||||
|
if ( !pWIC )
|
||||||
|
return E_NOINTERFACE;
|
||||||
|
|
||||||
|
ScopedObject<IWICBitmapScaler> scaler;
|
||||||
|
hr = pWIC->CreateBitmapScaler( &scaler );
|
||||||
|
if ( FAILED(hr) )
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
hr = scaler->Initialize( frame, twidth, theight, WICBitmapInterpolationModeFant );
|
||||||
|
if ( FAILED(hr) )
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
WICPixelFormatGUID pfScaler;
|
||||||
|
hr = scaler->GetPixelFormat( &pfScaler );
|
||||||
|
if ( FAILED(hr) )
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
if ( memcmp( &convertGUID, &pfScaler, sizeof(GUID) ) == 0 )
|
||||||
|
{
|
||||||
|
// No format conversion needed
|
||||||
|
hr = scaler->CopyPixels( 0, static_cast<UINT>( rowPitch ), static_cast<UINT>( imageSize ), temp.get() );
|
||||||
|
if ( FAILED(hr) )
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ScopedObject<IWICFormatConverter> FC;
|
||||||
|
hr = pWIC->CreateFormatConverter( &FC );
|
||||||
|
if ( FAILED(hr) )
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
hr = FC->Initialize( scaler.Get(), convertGUID, WICBitmapDitherTypeErrorDiffusion, 0, 0, WICBitmapPaletteTypeCustom );
|
||||||
|
if ( FAILED(hr) )
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
hr = FC->CopyPixels( 0, static_cast<UINT>( rowPitch ), static_cast<UINT>( imageSize ), temp.get() );
|
||||||
|
if ( FAILED(hr) )
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Format conversion but no resize
|
||||||
|
IWICImagingFactory* pWIC = _GetWIC();
|
||||||
|
if ( !pWIC )
|
||||||
|
return E_NOINTERFACE;
|
||||||
|
|
||||||
|
ScopedObject<IWICFormatConverter> FC;
|
||||||
|
hr = pWIC->CreateFormatConverter( &FC );
|
||||||
|
if ( FAILED(hr) )
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
hr = FC->Initialize( frame, convertGUID, WICBitmapDitherTypeErrorDiffusion, 0, 0, WICBitmapPaletteTypeCustom );
|
||||||
|
if ( FAILED(hr) )
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
hr = FC->CopyPixels( 0, static_cast<UINT>( rowPitch ), static_cast<UINT>( imageSize ), temp.get() );
|
||||||
|
if ( FAILED(hr) )
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// See if format is supported for auto-gen mipmaps (varies by feature level)
|
||||||
|
bool autogen = false;
|
||||||
|
if ( d3dContext != 0 && textureView != 0 ) // Must have context and shader-view to auto generate mipmaps
|
||||||
|
{
|
||||||
|
UINT fmtSupport = 0;
|
||||||
|
hr = d3dDevice->CheckFormatSupport( format, &fmtSupport );
|
||||||
|
if ( SUCCEEDED(hr) && ( fmtSupport & D3D11_FORMAT_SUPPORT_MIP_AUTOGEN ) )
|
||||||
|
{
|
||||||
|
autogen = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create texture
|
||||||
|
D3D11_TEXTURE2D_DESC desc;
|
||||||
|
desc.Width = twidth;
|
||||||
|
desc.Height = theight;
|
||||||
|
desc.MipLevels = (autogen) ? 0 : 1;
|
||||||
|
desc.ArraySize = 1;
|
||||||
|
desc.Format = format;
|
||||||
|
desc.SampleDesc.Count = 1;
|
||||||
|
desc.SampleDesc.Quality = 0;
|
||||||
|
desc.Usage = usage;
|
||||||
|
desc.CPUAccessFlags = cpuAccessFlags;
|
||||||
|
|
||||||
|
if ( autogen )
|
||||||
|
{
|
||||||
|
desc.BindFlags = bindFlags | D3D11_BIND_RENDER_TARGET;
|
||||||
|
desc.MiscFlags = miscFlags | D3D11_RESOURCE_MISC_GENERATE_MIPS;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
desc.BindFlags = bindFlags;
|
||||||
|
desc.MiscFlags = miscFlags;
|
||||||
|
}
|
||||||
|
|
||||||
|
D3D11_SUBRESOURCE_DATA initData;
|
||||||
|
initData.pSysMem = temp.get();
|
||||||
|
initData.SysMemPitch = static_cast<UINT>( rowPitch );
|
||||||
|
initData.SysMemSlicePitch = static_cast<UINT>( imageSize );
|
||||||
|
|
||||||
|
ID3D11Texture2D* tex = nullptr;
|
||||||
|
//Error with miscFlags Generate Mips
|
||||||
|
hr = d3dDevice->CreateTexture2D( &desc, (autogen) ? nullptr : &initData, &tex );
|
||||||
|
/// Replace To get Texture Data
|
||||||
|
if ( SUCCEEDED(hr) && tex != 0 )
|
||||||
|
{
|
||||||
|
if (textureView != 0)
|
||||||
|
{
|
||||||
|
D3D11_SHADER_RESOURCE_VIEW_DESC SRVDesc;
|
||||||
|
memset( &SRVDesc, 0, sizeof( SRVDesc ) );
|
||||||
|
SRVDesc.Format = desc.Format;
|
||||||
|
|
||||||
|
SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
|
||||||
|
SRVDesc.Texture2D.MipLevels = (autogen) ? -1 : 1;
|
||||||
|
|
||||||
|
hr = d3dDevice->CreateShaderResourceView( tex, &SRVDesc, textureView );
|
||||||
|
if ( FAILED(hr) )
|
||||||
|
{
|
||||||
|
tex->Release();
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( autogen )
|
||||||
|
{
|
||||||
|
assert( d3dContext != 0 );
|
||||||
|
d3dContext->UpdateSubresource( tex, 0, nullptr, temp.get(), static_cast<UINT>(rowPitch), static_cast<UINT>(imageSize) );
|
||||||
|
d3dContext->GenerateMips( *textureView );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (texture != 0)
|
||||||
|
{
|
||||||
|
*texture = tex;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//SetDebugObjectName(tex, "WICTextureLoader");
|
||||||
|
tex->Release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT CreateWICTextureFromFileEx( ID3D11Device* d3dDevice,
|
||||||
|
ID3D11DeviceContext* d3dContext,
|
||||||
|
const wchar_t* fileName,
|
||||||
|
size_t maxsize,
|
||||||
|
D3D11_USAGE usage,
|
||||||
|
unsigned int bindFlags,
|
||||||
|
unsigned int cpuAccessFlags,
|
||||||
|
unsigned int miscFlags,
|
||||||
|
bool forceSRGB,
|
||||||
|
ID3D11Resource** texture,
|
||||||
|
ID3D11ShaderResourceView** textureView )
|
||||||
|
{
|
||||||
|
if ( texture )
|
||||||
|
{
|
||||||
|
*texture = nullptr;
|
||||||
|
}
|
||||||
|
if ( textureView )
|
||||||
|
{
|
||||||
|
*textureView = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!d3dDevice || !fileName || (!texture && !textureView))
|
||||||
|
return E_INVALIDARG;
|
||||||
|
|
||||||
|
IWICImagingFactory* pWIC = _GetWIC();
|
||||||
|
if ( !pWIC )
|
||||||
|
return E_NOINTERFACE;
|
||||||
|
|
||||||
|
// Initialize WIC
|
||||||
|
ScopedObject<IWICBitmapDecoder> decoder;
|
||||||
|
HRESULT hr = pWIC->CreateDecoderFromFilename( fileName, 0, GENERIC_READ, WICDecodeMetadataCacheOnDemand, &decoder );
|
||||||
|
if ( FAILED(hr) )
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
ScopedObject<IWICBitmapFrameDecode> frame;
|
||||||
|
hr = decoder->GetFrame( 0, &frame );
|
||||||
|
if ( FAILED(hr) )
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
hr = CreateTextureFromWIC( d3dDevice, d3dContext, frame.Get(), maxsize,
|
||||||
|
usage, bindFlags, cpuAccessFlags, miscFlags, forceSRGB,
|
||||||
|
texture, textureView );
|
||||||
|
|
||||||
|
return hr;
|
||||||
}
|
}
|
|
@ -6,8 +6,8 @@ namespace Oyster
|
||||||
{
|
{
|
||||||
namespace Loading
|
namespace Loading
|
||||||
{
|
{
|
||||||
void UnloadTexture();
|
void UnloadTexture(void* loadedData);
|
||||||
Oyster::Resource::CustomData* LoadTexture();
|
const Oyster::Resource::CustomData& LoadTexture(const wchar_t filename[]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -223,9 +223,16 @@
|
||||||
<AssemblerOutput Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
<AssemblerOutput Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
</AssemblerOutput>
|
</AssemblerOutput>
|
||||||
</FxCompile>
|
</FxCompile>
|
||||||
|
<FxCompile Include="Shader\HLSL\SimpleDebug\TextureDebug.hlsl">
|
||||||
|
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Pixel</ShaderType>
|
||||||
|
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Pixel</ShaderType>
|
||||||
|
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Pixel</ShaderType>
|
||||||
|
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Pixel</ShaderType>
|
||||||
|
</FxCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="Shader\HLSL\Deffered Shaders\GatherGBuffer\GBufferHeader.hlsli" />
|
<None Include="Shader\HLSL\Deffered Shaders\GatherGBuffer\GBufferHeader.hlsli" />
|
||||||
|
<None Include="Shader\HLSL\SimpleDebug\Debug.hlsli" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
<ImportGroup Label="ExtensionTargets">
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
|
|
@ -87,8 +87,10 @@
|
||||||
<FxCompile Include="Shader\HLSL\SimpleDebug\DebugCameraVertex.hlsl" />
|
<FxCompile Include="Shader\HLSL\SimpleDebug\DebugCameraVertex.hlsl" />
|
||||||
<FxCompile Include="Shader\HLSL\Deffered Shaders\GatherGBuffer\PixelGatherData.hlsl" />
|
<FxCompile Include="Shader\HLSL\Deffered Shaders\GatherGBuffer\PixelGatherData.hlsl" />
|
||||||
<FxCompile Include="Shader\HLSL\Deffered Shaders\GatherGBuffer\VertexGatherData.hlsl" />
|
<FxCompile Include="Shader\HLSL\Deffered Shaders\GatherGBuffer\VertexGatherData.hlsl" />
|
||||||
|
<FxCompile Include="Shader\HLSL\SimpleDebug\TextureDebug.hlsl" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="Shader\HLSL\Deffered Shaders\GatherGBuffer\GBufferHeader.hlsli" />
|
<None Include="Shader\HLSL\Deffered Shaders\GatherGBuffer\GBufferHeader.hlsli" />
|
||||||
|
<None Include="Shader\HLSL\SimpleDebug\Debug.hlsli" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
|
@ -7,6 +7,7 @@ const std::wstring PathFromExeToHlsl = L"..\\..\\..\\Code\\OysterGraphics\\Shade
|
||||||
const std::wstring VertexTransformDebug = L"TransformDebugVertex";
|
const std::wstring VertexTransformDebug = L"TransformDebugVertex";
|
||||||
const std::wstring VertexDebug = L"DebugVertex";
|
const std::wstring VertexDebug = L"DebugVertex";
|
||||||
const std::wstring PixelRed = L"DebugPixel";
|
const std::wstring PixelRed = L"DebugPixel";
|
||||||
|
const std::wstring PixelTexture = L"Texture";
|
||||||
|
|
||||||
typedef Oyster::Graphics::Core::ShaderManager::ShaderType ShaderType;
|
typedef Oyster::Graphics::Core::ShaderManager::ShaderType ShaderType;
|
||||||
typedef Oyster::Graphics::Core::ShaderManager::Get GetShader;
|
typedef Oyster::Graphics::Core::ShaderManager::Get GetShader;
|
||||||
|
@ -19,7 +20,7 @@ namespace Oyster
|
||||||
{
|
{
|
||||||
namespace Render
|
namespace Render
|
||||||
{
|
{
|
||||||
Shader::ShaderEffect Resources::obj;
|
Shader::ShaderEffect Resources::obj;// = Shader::ShaderEffect();;
|
||||||
Buffer Resources::ModelData = Buffer();
|
Buffer Resources::ModelData = Buffer();
|
||||||
Buffer Resources::VPData = Buffer();
|
Buffer Resources::VPData = Buffer();
|
||||||
|
|
||||||
|
@ -36,6 +37,8 @@ namespace Oyster
|
||||||
|
|
||||||
/** Load Pixel Shader for d3dcompile */
|
/** Load Pixel Shader for d3dcompile */
|
||||||
Core::ShaderManager::Init(PathFromExeToHlsl + L"SimpleDebug\\" + L"DebugPixel.hlsl", ShaderType::Pixel, PixelRed, false);
|
Core::ShaderManager::Init(PathFromExeToHlsl + L"SimpleDebug\\" + L"DebugPixel.hlsl", ShaderType::Pixel, PixelRed, false);
|
||||||
|
Core::ShaderManager::Init(PathFromExeToHlsl + L"SimpleDebug\\" + L"TextureDebug.hlsl", ShaderType::Pixel, PixelTexture, false);
|
||||||
|
|
||||||
|
|
||||||
#else
|
#else
|
||||||
/** Load Vertex Shader with Precompiled */
|
/** Load Vertex Shader with Precompiled */
|
||||||
|
@ -75,6 +78,23 @@ namespace Oyster
|
||||||
|
|
||||||
ID3D11RasterizerState* rs = NULL;
|
ID3D11RasterizerState* rs = NULL;
|
||||||
Oyster::Graphics::Core::device->CreateRasterizerState(&rdesc,&rs);
|
Oyster::Graphics::Core::device->CreateRasterizerState(&rdesc,&rs);
|
||||||
|
|
||||||
|
D3D11_SAMPLER_DESC sdesc;
|
||||||
|
sdesc.Filter = D3D11_FILTER_ANISOTROPIC;
|
||||||
|
/// @todo parata med fredrik om wraping
|
||||||
|
sdesc.AddressU = D3D11_TEXTURE_ADDRESS_MIRROR_ONCE;
|
||||||
|
sdesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
|
||||||
|
sdesc.AddressW = D3D11_TEXTURE_ADDRESS_BORDER;
|
||||||
|
sdesc.MipLODBias = 0;
|
||||||
|
sdesc.MaxAnisotropy =4;
|
||||||
|
sdesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS;
|
||||||
|
*sdesc.BorderColor = *Oyster::Math::Float4(0,0,0,1).element;
|
||||||
|
sdesc.MinLOD = 0;
|
||||||
|
sdesc.MaxLOD = D3D11_FLOAT32_MAX;
|
||||||
|
|
||||||
|
ID3D11SamplerState** ss = new ID3D11SamplerState*[1];
|
||||||
|
Oyster::Graphics::Core::device->CreateSamplerState(&sdesc,ss);
|
||||||
|
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
|
||||||
#pragma region Setup Views
|
#pragma region Setup Views
|
||||||
|
@ -84,7 +104,7 @@ namespace Oyster
|
||||||
#pragma region Create Shader Effects
|
#pragma region Create Shader Effects
|
||||||
/** @todo Create ShaderEffects */
|
/** @todo Create ShaderEffects */
|
||||||
obj.Shaders.Pixel = GetShader::Pixel(PixelRed);
|
obj.Shaders.Pixel = GetShader::Pixel(PixelRed);
|
||||||
obj.Shaders.Vertex = GetShader::Vertex(VertexTransformDebug);
|
obj.Shaders.Vertex = GetShader::Vertex(VertexDebug);
|
||||||
|
|
||||||
D3D11_INPUT_ELEMENT_DESC indesc[] =
|
D3D11_INPUT_ELEMENT_DESC indesc[] =
|
||||||
{
|
{
|
||||||
|
@ -98,6 +118,8 @@ namespace Oyster
|
||||||
obj.IAStage.Topology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
|
obj.IAStage.Topology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
|
||||||
obj.CBuffers.Vertex.push_back(&VPData);
|
obj.CBuffers.Vertex.push_back(&VPData);
|
||||||
obj.RenderStates.Rasterizer = rs;
|
obj.RenderStates.Rasterizer = rs;
|
||||||
|
obj.RenderStates.SampleCount = 1;
|
||||||
|
obj.RenderStates.SampleState = ss;
|
||||||
|
|
||||||
ModelData.Apply(1);
|
ModelData.Apply(1);
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
|
|
@ -28,6 +28,8 @@ struct PixelOut
|
||||||
Texture2D Diffuse : register(t0);
|
Texture2D Diffuse : register(t0);
|
||||||
Texture2D Specular : register(t1);
|
Texture2D Specular : register(t1);
|
||||||
|
|
||||||
|
SamplerState Sampler : register(s0);
|
||||||
|
|
||||||
cbuffer PerFrame : register(b0)
|
cbuffer PerFrame : register(b0)
|
||||||
{
|
{
|
||||||
matrix View;
|
matrix View;
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
PixelOut main(VertexOut input)
|
PixelOut main(VertexOut input)
|
||||||
{
|
{
|
||||||
PixelOut output;
|
PixelOut output;
|
||||||
output.DiffuseGlow = float4(1.0f, 0.0f, 0.0f, 1.0f);
|
output.DiffuseGlow = Diffuse.Sample(Sampler, input.UV);
|
||||||
output.NormalSpec = float4(input.normal, 1.0f);
|
output.NormalSpec = float4(input.normal, 1.0f);
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
cbuffer PerFrame : register(b0)
|
||||||
|
{
|
||||||
|
matrix View;
|
||||||
|
float4x4 Projection;
|
||||||
|
}
|
||||||
|
|
||||||
|
cbuffer PerModel : register(b1)
|
||||||
|
{
|
||||||
|
matrix World;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct VertexIn
|
||||||
|
{
|
||||||
|
float3 pos : POSITION;
|
||||||
|
float2 UV : TEXCOORD;
|
||||||
|
float3 normal : NORMAL;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct VertexOut
|
||||||
|
{
|
||||||
|
float4 Pos : SV_POSITION;
|
||||||
|
float2 UV : TEXCOORD;
|
||||||
|
float3 Normal : NORMAL;
|
||||||
|
float4 Wpos : POSITION;
|
||||||
|
};
|
|
@ -1,28 +1,13 @@
|
||||||
cbuffer PerFrame : register(b0)
|
#include "Debug.hlsli"
|
||||||
{
|
|
||||||
matrix View;
|
|
||||||
float4x4 Projection;
|
|
||||||
}
|
|
||||||
|
|
||||||
cbuffer PerModel : register(b1)
|
|
||||||
{
|
|
||||||
matrix World;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct VertexIn
|
VertexOut main( VertexIn input )
|
||||||
{
|
{
|
||||||
float3 pos : POSITION;
|
VertexOut outp;
|
||||||
float2 UV : TEXCOORD;
|
outp.Wpos = mul( World, float4(input.pos,1) );
|
||||||
float3 normal : NORMAL;
|
|
||||||
};
|
|
||||||
|
|
||||||
float4 main( VertexIn input ) : SV_POSITION
|
|
||||||
{
|
|
||||||
float4 postTransform = mul( World, float4(input.pos,1) );
|
|
||||||
//float4 postTransform = float4(input.pos,1);
|
|
||||||
//return postTransform;
|
|
||||||
//return mul(View, float4(input.pos,1));
|
|
||||||
matrix VP = mul(Projection, View);
|
matrix VP = mul(Projection, View);
|
||||||
//matrix WVP = mul(World, VP);
|
outp.Pos = mul(VP, outp.Wpos );
|
||||||
return mul(VP, postTransform );
|
outp.UV = input.UV;
|
||||||
|
outp.Normal = input.normal;
|
||||||
|
return outp;
|
||||||
}
|
}
|
|
@ -1,4 +1,6 @@
|
||||||
float4 main() : SV_TARGET0
|
#include "Debug.hlsli"
|
||||||
|
|
||||||
|
float4 main() : SV_TARGET
|
||||||
{
|
{
|
||||||
return float4(1.0f, 0.0f, 0.0f, 1.0f);
|
return float4(1.0f, 0.0f, 0.0f, 1.0f);
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
float4 main( float4 pos : POSITION ) : SV_POSITION
|
float4 main( float4 pos : POSITION ) : SV_POSITION
|
||||||
{
|
{
|
||||||
return pos;
|
return pos*0.1f;
|
||||||
}
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
#include "Debug.hlsli"
|
||||||
|
|
||||||
|
Texture2D tex : register(t0);
|
||||||
|
SamplerState S1 : register(s0);
|
||||||
|
|
||||||
|
float4 main(VertexOut inp) : SV_TARGET0
|
||||||
|
{
|
||||||
|
return tex.Sample(S1,inp.UV);
|
||||||
|
}
|
|
@ -201,6 +201,7 @@ HRESULT InitDirect3D()
|
||||||
|
|
||||||
HRESULT Update(float deltaTime)
|
HRESULT Update(float deltaTime)
|
||||||
{
|
{
|
||||||
|
m->WorldMatrix.m14 += 0.0001f;
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue