diff --git a/src/client/Console.cpp b/src/client/Console.cpp index 580bba3..c2d7adc 100644 --- a/src/client/Console.cpp +++ b/src/client/Console.cpp @@ -185,7 +185,15 @@ void ConsoleDeviceInitialize(const char* title) { CGxFormat format; memcpy(&format, &s_requestedFormat, sizeof(s_requestedFormat)); - CGxDevice* device = GxDevCreate(GxApi_GLL, nullptr, format); + // TODO proper api selection + EGxApi api = GxApi_OpenGl; +#if defined(WHOA_SYSTEM_WIN) + api = GxApi_D3d9; +#elif defined(WHOA_SYSTEM_MAC) + api = GxApi_GLL; +#endif + + CGxDevice* device = GxDevCreate(api, nullptr, format); // TODO } diff --git a/src/gx/CGxDevice.cpp b/src/gx/CGxDevice.cpp index 0c9c11c..a2c5cb2 100644 --- a/src/gx/CGxDevice.cpp +++ b/src/gx/CGxDevice.cpp @@ -10,6 +10,10 @@ #include #include +#if defined(WHOA_SYSTEM_WIN) + #include "gx/d3d/CGxDeviceD3d.hpp" +#endif + #if defined(WHOA_SYSTEM_MAC) #include "gx/gll/CGxDeviceGLL.hpp" #endif @@ -70,15 +74,21 @@ uint32_t CGxDevice::s_texFormatBytesPerBlock[] = { 4 // GxTex_D24X8 }; -CGxDevice* CGxDevice::NewD3d() { +void CGxDevice::Log(const char* format, ...) { // TODO - return nullptr; +} + +#if defined(WHOA_SYSTEM_WIN) +CGxDevice* CGxDevice::NewD3d() { + auto m = SMemAlloc(sizeof(CGxDeviceD3d), __FILE__, __LINE__, 0x0); + return new (m) CGxDeviceD3d(); } CGxDevice* CGxDevice::NewD3d9Ex() { // TODO return nullptr; } +#endif #if defined(WHOA_SYSTEM_MAC) CGxDevice* CGxDevice::NewGLL() { diff --git a/src/gx/CGxDevice.hpp b/src/gx/CGxDevice.hpp index ba2fa63..e810c64 100644 --- a/src/gx/CGxDevice.hpp +++ b/src/gx/CGxDevice.hpp @@ -46,8 +46,11 @@ class CGxDevice { static uint32_t s_texFormatBytesPerBlock[]; // Static functions + static void Log(const char* format, ...); +#if defined(WHOA_SYSTEM_WIN) static CGxDevice* NewD3d(); static CGxDevice* NewD3d9Ex(); +#endif #if defined(WHOA_SYSTEM_MAC) static CGxDevice* NewGLL(); #endif diff --git a/src/gx/CMakeLists.txt b/src/gx/CMakeLists.txt index 67b530a..33338b0 100644 --- a/src/gx/CMakeLists.txt +++ b/src/gx/CMakeLists.txt @@ -6,6 +6,11 @@ file(GLOB GX_SOURCES "texture/*.cpp" ) +if(WHOA_SYSTEM_WIN) + file(GLOB D3D_SOURCES "d3d/*.cpp") + list(APPEND GX_SOURCES ${D3D_SOURCES}) +endif() + if(WHOA_SYSTEM_MAC) file(GLOB GLL_SOURCES "gll/*.cpp" "gll/*.mm") set_source_files_properties(${GLL_SOURCES} @@ -35,6 +40,13 @@ target_link_libraries(gx tempest ) +if(WHOA_SYSTEM_WIN) + target_link_libraries(gx + PRIVATE + d3d9.lib + ) +endif() + if(WHOA_SYSTEM_MAC) target_link_libraries(gx PRIVATE diff --git a/src/gx/d3d/CGxDeviceD3d.cpp b/src/gx/d3d/CGxDeviceD3d.cpp new file mode 100644 index 0000000..a5ebd5b --- /dev/null +++ b/src/gx/d3d/CGxDeviceD3d.cpp @@ -0,0 +1,149 @@ +#include "gx/d3d/CGxDeviceD3d.hpp" + +ATOM WindowClassCreate() { + auto instance = GetModuleHandle(nullptr); + + WNDCLASSEX wc = { 0 }; + + wc.cbSize = sizeof(wc); + wc.style = CS_OWNDC; + wc.lpfnWndProc = CGxDeviceD3d::WindowProcD3d; + wc.hInstance = instance; + wc.lpszClassName = "GxWindowClassD3d"; + + wc.hIcon = static_cast(LoadImage(instance, TEXT("BlizzardIcon.ico"), 1u, 0, 0, 0x40)); + wc.hCursor = LoadCursor(instance, TEXT("BlizzardCursor.cur")); + + if (!wc.hCursor) { + wc.hCursor = LoadCursor(instance, IDC_ARROW); + } + + return RegisterClassEx(&wc); +} + +int32_t CGxDeviceD3d::ILoadD3dLib(HINSTANCE& d3dLib, LPDIRECT3D9& d3d) { + d3dLib = nullptr; + d3d = nullptr; + + d3dLib = LoadLibrary(TEXT("d3d9.dll")); + + if (d3dLib) { + auto d3dCreateProc = GetProcAddress(d3dLib, "Direct3DCreate9"); + + if (d3dCreateProc) { + d3d = reinterpret_cast(d3dCreateProc()); + + if (d3d) { + return 1; + } + + CGxDevice::Log("CGxDeviceD3d::ILoadD3dLib(): unable to d3dCreateProc()"); + } else { + CGxDevice::Log("CGxDeviceD3d::ILoadD3dLib(): unable to GetProcAddress()"); + } + } else { + CGxDevice::Log("CGxDeviceD3d::ILoadD3dLib(): unable to LoadLibrary()"); + } + + CGxDeviceD3d::IUnloadD3dLib(d3dLib, d3d); + + return 0; +} + +void CGxDeviceD3d::IUnloadD3dLib(HINSTANCE& d3dLib, LPDIRECT3D9& d3d) { + if (d3d) { + d3d->Release(); + } + + if (d3dLib) { + FreeLibrary(d3dLib); + } +} + +LRESULT CGxDeviceD3d::WindowProcD3d(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { + // TODO + return 0; +} + +void CGxDeviceD3d::CapsWindowSize(CRect& dst) { + // TODO +} + +void CGxDeviceD3d::CapsWindowSizeInScreenCoords(CRect& dst) { + // TODO +} + +int32_t CGxDeviceD3d::DeviceCreate(long (*windowProc)(void*, uint32_t, uint32_t, long), const CGxFormat& format) { + this->m_ownhwnd = 1; + + // TODO gamma ramp + + this->m_hwndClass = WindowClassCreate(); + + if (this->m_hwndClass) { + if (this->ICreateD3d() && this->CGxDevice::DeviceCreate(windowProc, format)) { + return 1; + } else { + // TODO + // this->DeviceDestroy(); + return 0; + } + } + + // TODO CGxDevice::Log("CGxDeviceD3d::DeviceCreate(): WindowClassCreate() failed: %s", OsGetLastErrorStr()); + // TODO this->DeviceDestroy(); + + return 0; +} + +int32_t CGxDeviceD3d::ICreateD3d() { + if (CGxDeviceD3d::ILoadD3dLib(this->m_d3dLib, this->m_d3d) && this->m_d3d->GetDeviceCaps(0, D3DDEVTYPE_HAL, &this->m_d3dCaps) >= S_OK) { + if (this->m_desktopDisplayMode.Format != D3DFMT_UNKNOWN) { + return 1; + } + + D3DDISPLAYMODE displayMode; + if (this->m_d3d->GetAdapterDisplayMode(0, &displayMode) >= S_OK) { + this->m_desktopDisplayMode.Width = displayMode.Width; + this->m_desktopDisplayMode.Height = displayMode.Height; + this->m_desktopDisplayMode.RefreshRate = displayMode.RefreshRate; + this->m_desktopDisplayMode.Format = displayMode.Format; + + return 1; + } + } + + this->IDestroyD3d(); + + return 0; +} + +void CGxDeviceD3d::IDestroyD3d() { + this->IDestroyD3dDevice(); + CGxDeviceD3d::IUnloadD3dLib(this->m_d3dLib, this->m_d3d); +} + +void CGxDeviceD3d::IDestroyD3dDevice() { + // TODO +} + +void CGxDeviceD3d::IRsSendToHw(EGxRenderState rs) { + // TODO +} + +void CGxDeviceD3d::IShaderCreate(CGxShader* shader) { + // TODO +} + +void CGxDeviceD3d::ITexMarkAsUpdated(CGxTex* texId) { + // TODO +} + +void CGxDeviceD3d::PoolSizeSet(CGxPool* pool, uint32_t size) { + // TODO +} + +int32_t CGxDeviceD3d::StereoEnabled() { + // TODO + return 0; +} diff --git a/src/gx/d3d/CGxDeviceD3d.hpp b/src/gx/d3d/CGxDeviceD3d.hpp new file mode 100644 index 0000000..c234990 --- /dev/null +++ b/src/gx/d3d/CGxDeviceD3d.hpp @@ -0,0 +1,41 @@ +#ifndef GX_D3D_C_GX_DEVICE_D3D_HPP +#define GX_D3D_C_GX_DEVICE_D3D_HPP + +#include "gx/CGxDevice.hpp" +#include +#include +#include + +class CGxDeviceD3d : public CGxDevice { + public: + // Static functions + static int32_t ILoadD3dLib(HINSTANCE& d3dLib, LPDIRECT3D9& d3d); + static void IUnloadD3dLib(HINSTANCE& d3dLib, LPDIRECT3D9& d3d); + static LRESULT WindowProcD3d(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + + // Member variables + ATOM m_hwndClass; + int32_t m_ownhwnd; + HINSTANCE m_d3dLib; + LPDIRECT3D9 m_d3d; + LPDIRECT3DDEVICE9 m_d3dDevice; + D3DCAPS9 m_d3dCaps; + D3DDISPLAYMODE m_desktopDisplayMode; + + // Virtual member functions + virtual void ITexMarkAsUpdated(CGxTex* texId); + virtual void IRsSendToHw(EGxRenderState rs); + virtual int32_t DeviceCreate(long (*windowProc)(void*, uint32_t, uint32_t, long), const CGxFormat& format); + virtual void CapsWindowSize(CRect& dst); + virtual void CapsWindowSizeInScreenCoords(CRect& dst); + virtual void PoolSizeSet(CGxPool* pool, uint32_t size); + virtual void IShaderCreate(CGxShader* shader); + virtual int32_t StereoEnabled(); + + // Member functions + int32_t ICreateD3d(); + void IDestroyD3d(); + void IDestroyD3dDevice(); +}; + +#endif