diff --git a/CMakeLists.txt b/CMakeLists.txt index 88c48e10..37e94055 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -97,6 +97,8 @@ add_library(miniwin STATIC EXCLUDE_FROM_ALL miniwin/miniwin/src/miniwin_ddsurface.cpp miniwin/miniwin/src/miniwin_ddraw.cpp miniwin/miniwin/src/miniwin_d3drm.cpp + miniwin/miniwin/src/miniwin_d3drmdevice.cpp + miniwin/miniwin/src/miniwin_d3drmviewport.cpp ) # Force reported render mods from MiniWin target_compile_definitions(miniwin PRIVATE MINIWIN_PIXELFORMAT=SDL_PIXELFORMAT_RGB565) diff --git a/miniwin/miniwin/include/bitflags.h b/miniwin/miniwin/include/bitflags.h index 4b497a1d..386f6a19 100644 --- a/miniwin/miniwin/include/bitflags.h +++ b/miniwin/miniwin/include/bitflags.h @@ -1,3 +1,5 @@ +#pragma once + #include // Enable bitwise ops only for enum classes with the ENABLE_BITMASK_OPERATORS trait diff --git a/miniwin/miniwin/include/miniwin_d3drm.h b/miniwin/miniwin/include/miniwin_d3drm.h index dfd8b66f..648edbfe 100644 --- a/miniwin/miniwin/include/miniwin_d3drm.h +++ b/miniwin/miniwin/include/miniwin_d3drm.h @@ -13,7 +13,7 @@ // --- Typedefs --- typedef float D3DVAL; typedef void* LPD3DRM_APPDATA; -typedef unsigned int D3DRMGROUPINDEX; +typedef DWORD D3DRMGROUPINDEX; typedef DWORD D3DCOLOR, *LPD3DCOLOR; typedef float D3DVALUE, *LPD3DVALUE; @@ -116,16 +116,16 @@ typedef struct D3DRMPALETTEENTRY { } D3DRMPALETTEENTRY; typedef struct D3DRMIMAGE { - unsigned int width, height, depth, bytes_per_line; - unsigned int red_mask, green_mask, blue_mask, alpha_mask; - unsigned int palette_size; + DWORD width, height, depth, bytes_per_line; + DWORD red_mask, green_mask, blue_mask, alpha_mask; + DWORD palette_size; D3DRMPALETTEENTRY* palette; void* buffer1; void* buffer2; void* data; int rgb; int aspectx, aspecty; - unsigned int format; + DWORD format; } D3DRMIMAGE; typedef struct D3DRMMATRIX4D { @@ -179,11 +179,11 @@ struct IDirect3DRMMesh : public IDirect3DRMVisual { ) = 0; virtual HRESULT GetGroup( int groupIndex, - unsigned int* vertexCount, - unsigned int* faceCount, - unsigned int* vertexPerFace, + DWORD* vertexCount, + DWORD* faceCount, + DWORD* vertexPerFace, DWORD* dataSize, - unsigned int* data + DWORD* data ) = 0; virtual HRESULT SetGroupColor(int groupIndex, D3DCOLOR color) = 0; virtual HRESULT SetGroupColorRGB(int groupIndex, float r, float g, float b) = 0; @@ -284,8 +284,8 @@ struct IDirect3DRMViewport : public IDirect3DRMObject { virtual D3DVALUE GetBack() = 0; virtual HRESULT SetField(D3DVALUE field) = 0; virtual D3DVALUE GetField() = 0; - virtual int GetWidth() = 0; - virtual int GetHeight() = 0; + virtual DWORD GetWidth() = 0; + virtual DWORD GetHeight() = 0; virtual HRESULT Transform(D3DRMVECTOR4D* screen, D3DVECTOR* world) = 0; virtual HRESULT InverseTransform(D3DVECTOR* world, D3DRMVECTOR4D* screen) = 0; virtual HRESULT Pick(float x, float y, LPDIRECT3DRMPICKEDARRAY* pickedArray) = 0; @@ -305,11 +305,11 @@ struct IDirect3DRMWinDevice : virtual public IDirect3DRMObject { }; struct IDirect3DRMDevice : virtual public IDirect3DRMObject { - virtual unsigned int GetWidth() = 0; - virtual unsigned int GetHeight() = 0; + virtual DWORD GetWidth() = 0; + virtual DWORD GetHeight() = 0; virtual HRESULT SetBufferCount(int count) = 0; virtual HRESULT GetBufferCount() = 0; - virtual HRESULT SetShades(unsigned int shadeCount) = 0; + virtual HRESULT SetShades(DWORD shadeCount) = 0; virtual HRESULT GetShades() = 0; virtual HRESULT SetQuality(D3DRMRENDERQUALITY quality) = 0; virtual D3DRMRENDERQUALITY GetQuality() = 0; @@ -353,8 +353,8 @@ struct IDirect3DRM : virtual public IUnknown { int height, IDirect3DRMViewport** outViewport ) = 0; - virtual HRESULT SetDefaultTextureShades(unsigned int count) = 0; - virtual HRESULT SetDefaultTextureColors(unsigned int count) = 0; + virtual HRESULT SetDefaultTextureShades(DWORD count) = 0; + virtual HRESULT SetDefaultTextureColors(DWORD count) = 0; }; typedef IDirect3DRM *LPDIRECT3DRM, **LPLPDIRECT3DRM; diff --git a/miniwin/miniwin/src/include/miniwin_d3drm_p.h b/miniwin/miniwin/src/include/miniwin_d3drm_p.h new file mode 100644 index 00000000..03eef0c8 --- /dev/null +++ b/miniwin/miniwin/src/include/miniwin_d3drm_p.h @@ -0,0 +1,76 @@ +#pragma once + +#include "miniwin_d3drm.h" + +#include +#include +#include + +typedef struct PositionColorVertex { + float x, y, z; + Uint8 r, g, b, a; +} PositionColorVertex; + +template +class Direct3DRMArrayBase : public ArrayInterface { +public: + ~Direct3DRMArrayBase() override + { + for (auto* item : items) { + if (item) { + item->Release(); + } + } + } + DWORD GetSize() override { return static_cast(items.size()); } + HRESULT AddElement(InterfaceType* in) override + { + if (!in) { + return DDERR_INVALIDPARAMS; + } + in->AddRef(); + items.push_back(in); + return DD_OK; + } + HRESULT GetElement(DWORD index, InterfaceType** out) override + { + if (index >= items.size()) { + return DDERR_INVALIDPARAMS; + } + *out = static_cast(items[index]); + if (*out) { + (*out)->AddRef(); + } + return DD_OK; + } + HRESULT DeleteElement(InterfaceType* element) override + { + auto it = std::find(items.begin(), items.end(), element); + if (it == items.end()) { + return DDERR_INVALIDPARAMS; + } + + (*it)->Release(); + items.erase(it); + return DD_OK; + } + +protected: + std::vector items; +}; + +struct Direct3DRMFrameArrayImpl : public Direct3DRMArrayBase { + using Direct3DRMArrayBase::Direct3DRMArrayBase; +}; + +struct Direct3DRMLightArrayImpl : public Direct3DRMArrayBase { + using Direct3DRMArrayBase::Direct3DRMArrayBase; +}; + +struct Direct3DRMViewportArrayImpl : public Direct3DRMArrayBase { + using Direct3DRMArrayBase::Direct3DRMArrayBase; +}; + +struct Direct3DRMVisualArrayImpl : public Direct3DRMArrayBase { + using Direct3DRMArrayBase::Direct3DRMArrayBase; +}; diff --git a/miniwin/miniwin/src/include/miniwin_d3drmdevice_p.h b/miniwin/miniwin/src/include/miniwin_d3drmdevice_p.h new file mode 100644 index 00000000..7cc18e31 --- /dev/null +++ b/miniwin/miniwin/src/include/miniwin_d3drmdevice_p.h @@ -0,0 +1,38 @@ +#pragma once + +#include "miniwin_d3drm.h" +#include "miniwin_d3drmobject_p.h" + +#include + +struct Direct3DRMDevice2Impl : public Direct3DRMObjectBase { + Direct3DRMDevice2Impl(DWORD width, DWORD height, SDL_GPUDevice* device); + ~Direct3DRMDevice2Impl() override; + DWORD GetWidth() override; + DWORD GetHeight() override; + HRESULT SetBufferCount(int count) override; + HRESULT GetBufferCount() override; + HRESULT SetShades(DWORD shadeCount) override; + HRESULT GetShades() override; + HRESULT SetQuality(D3DRMRENDERQUALITY quality) override; + D3DRMRENDERQUALITY GetQuality() override; + HRESULT SetDither(int dither) override; + HRESULT GetDither() override; + HRESULT SetTextureQuality(D3DRMTEXTUREQUALITY quality) override; + D3DRMTEXTUREQUALITY GetTextureQuality() override; + HRESULT SetRenderMode(D3DRMRENDERMODE mode) override; + D3DRMRENDERMODE GetRenderMode() override; + /** + * @brief Recalculating light positions, animation updates, etc. + */ + HRESULT Update() override; + HRESULT AddViewport(IDirect3DRMViewport* viewport) override; + HRESULT GetViewports(IDirect3DRMViewportArray** ppViewportArray) override; + + SDL_GPUDevice* m_device; + +private: + DWORD m_width; + DWORD m_height; + IDirect3DRMViewportArray* m_viewports; +}; diff --git a/miniwin/miniwin/src/include/miniwin_d3drmobject_p.h b/miniwin/miniwin/src/include/miniwin_d3drmobject_p.h new file mode 100644 index 00000000..a441fbf7 --- /dev/null +++ b/miniwin/miniwin/src/include/miniwin_d3drmobject_p.h @@ -0,0 +1,70 @@ +#pragma once + +#include "miniwin_d3drm.h" + +#include +#include + +template +struct Direct3DRMObjectBase : public T { + ULONG Release() override + { + if (IUnknown::m_refCount == 1) { + for (auto it = m_callbacks.cbegin(); it != m_callbacks.cend(); it++) { + it->first(this, it->second); + } + } + SDL_free(m_name); + return this->T::Release(); + } + HRESULT AddDestroyCallback(D3DRMOBJECTCALLBACK callback, void* arg) override + { + m_callbacks.push_back(std::make_pair(callback, arg)); + return D3DRM_OK; + } + HRESULT DeleteDestroyCallback(D3DRMOBJECTCALLBACK callback, void* arg) override + { + for (auto it = m_callbacks.cbegin(); it != m_callbacks.cend(); it++) { + if (it->first == callback && it->second == arg) { + m_callbacks.erase(it); + return D3DRM_OK; + } + } + return D3DRMERR_NOTFOUND; + } + HRESULT SetAppData(LPD3DRM_APPDATA appData) override + { + m_appData = appData; + return D3DRM_OK; + } + LPVOID GetAppData() override { return m_appData; } + HRESULT SetName(const char* name) override + { + SDL_free(m_name); + m_name = NULL; + if (name) { + m_name = SDL_strdup(name); + } + return D3DRM_OK; + } + HRESULT GetName(DWORD* size, char* name) override + { + if (!size) { + return DDERR_INVALIDPARAMS; + } + const char* s = m_name ? m_name : ""; + size_t l = SDL_strlen(s); + if (name) { + SDL_strlcpy(name, s, *size); + } + else { + *size = l + 1; + } + return D3DRM_OK; + } + +private: + std::vector> m_callbacks; + LPD3DRM_APPDATA m_appData = nullptr; + char* m_name = nullptr; +}; diff --git a/miniwin/miniwin/src/include/miniwin_d3drmviewport_p.h b/miniwin/miniwin/src/include/miniwin_d3drmviewport_p.h new file mode 100644 index 00000000..79ec7b38 --- /dev/null +++ b/miniwin/miniwin/src/include/miniwin_d3drmviewport_p.h @@ -0,0 +1,56 @@ +#pragma once + +#include "miniwin_d3drm.h" +#include "miniwin_d3drmdevice_p.h" +#include "miniwin_d3drmobject_p.h" + +#include + +struct Direct3DRMViewportImpl : public Direct3DRMObjectBase { + Direct3DRMViewportImpl( + DWORD width, + DWORD height, + SDL_GPUDevice* device, + SDL_GPUTexture* transferTexture, + SDL_GPUTransferBuffer* downloadTransferBuffer, + SDL_GPUGraphicsPipeline* pipeline + ); + ~Direct3DRMViewportImpl() override; + HRESULT Render(IDirect3DRMFrame* group) override; + /** + * @brief Blit the render back to our backbuffer + */ + HRESULT ForceUpdate(int x, int y, int w, int h) override; + HRESULT Clear() override; + HRESULT SetCamera(IDirect3DRMFrame* camera) override; + HRESULT GetCamera(IDirect3DRMFrame** camera) override; + HRESULT SetProjection(D3DRMPROJECTIONTYPE type) override; + D3DRMPROJECTIONTYPE GetProjection() override; + HRESULT SetFront(D3DVALUE z) override; + D3DVALUE GetFront() override; + HRESULT SetBack(D3DVALUE z) override; + D3DVALUE GetBack() override; + HRESULT SetField(D3DVALUE field) override; + D3DVALUE GetField() override; + DWORD GetWidth() override; + DWORD GetHeight() override; + HRESULT Transform(D3DRMVECTOR4D* screen, D3DVECTOR* world) override; + HRESULT InverseTransform(D3DVECTOR* world, D3DRMVECTOR4D* screen) override; + HRESULT Pick(float x, float y, LPDIRECT3DRMPICKEDARRAY* pickedArray) override; + void CloseDevice(); + void Update(); + +private: + void FreeDeviceResources(); + int m_vertexCount; + bool m_updated = false; + DWORD m_width; + DWORD m_height; + IDirect3DRMFrame* m_camera = nullptr; + SDL_GPUDevice* m_device; + SDL_GPUGraphicsPipeline* m_pipeline; + SDL_GPUTexture* m_transferTexture; + SDL_GPUTransferBuffer* m_downloadTransferBuffer; + SDL_GPUBuffer* m_vertexBuffer; + SDL_Surface* m_renderedImage = nullptr; +}; diff --git a/miniwin/miniwin/src/miniwin_d3drm.cpp b/miniwin/miniwin/src/miniwin_d3drm.cpp index d68a7e2f..b19c92ee 100644 --- a/miniwin/miniwin/src/miniwin_d3drm.cpp +++ b/miniwin/miniwin/src/miniwin_d3drm.cpp @@ -1,81 +1,12 @@ #include "miniwin_d3drm.h" -#include "miniwin_ddsurface_p.h" #include "ShaderIndex.h" +#include "miniwin_d3drm_p.h" +#include "miniwin_d3drmobject_p.h" +#include "miniwin_d3drmviewport_p.h" +#include "miniwin_ddsurface_p.h" #include -#include -#include -#include - -typedef struct PositionColorVertex { - float x, y, z; - Uint8 r, g, b, a; -} PositionColorVertex; - -template -class Direct3DRMArrayBase : public ArrayInterface { -public: - ~Direct3DRMArrayBase() override - { - for (auto* item : items) { - if (item) { - item->Release(); - } - } - } - DWORD GetSize() override { return static_cast(items.size()); } - HRESULT AddElement(InterfaceType* in) override - { - if (!in) { - return DDERR_INVALIDPARAMS; - } - in->AddRef(); - items.push_back(in); - return DD_OK; - } - HRESULT GetElement(DWORD index, InterfaceType** out) override - { - if (index >= items.size()) { - return DDERR_INVALIDPARAMS; - } - *out = static_cast(items[index]); - if (*out) { - (*out)->AddRef(); - } - return DD_OK; - } - HRESULT DeleteElement(InterfaceType* element) override - { - auto it = std::find(items.begin(), items.end(), element); - if (it == items.end()) { - return DDERR_INVALIDPARAMS; - } - - (*it)->Release(); - items.erase(it); - return DD_OK; - } - -protected: - std::vector items; -}; - -struct Direct3DRMFrameArrayImpl : public Direct3DRMArrayBase { - using Direct3DRMArrayBase::Direct3DRMArrayBase; -}; - -struct Direct3DRMLightArrayImpl : public Direct3DRMArrayBase { - using Direct3DRMArrayBase::Direct3DRMArrayBase; -}; - -struct Direct3DRMViewportArrayImpl : public Direct3DRMArrayBase { - using Direct3DRMArrayBase::Direct3DRMArrayBase; -}; - -struct Direct3DRMVisualArrayImpl : public Direct3DRMArrayBase { - using Direct3DRMArrayBase::Direct3DRMArrayBase; -}; struct PickRecord { IDirect3DRMVisual* visual; @@ -130,69 +61,6 @@ struct Direct3DRMWinDeviceImpl : public IDirect3DRMWinDevice { void HandlePaint(void* p_dc) override {} }; -template -struct Direct3DRMObjectBase : public T { - ULONG Release() override - { - if (IUnknown::m_refCount == 1) { - for (auto it = m_callbacks.cbegin(); it != m_callbacks.cend(); it++) { - it->first(this, it->second); - } - } - return this->T::Release(); - } - HRESULT AddDestroyCallback(D3DRMOBJECTCALLBACK callback, void* arg) override - { - m_callbacks.push_back(std::make_pair(callback, arg)); - return D3DRM_OK; - } - HRESULT DeleteDestroyCallback(D3DRMOBJECTCALLBACK callback, void* arg) override - { - for (auto it = m_callbacks.cbegin(); it != m_callbacks.cend(); it++) { - if (it->first == callback && it->second == arg) { - m_callbacks.erase(it); - return D3DRM_OK; - } - } - return D3DRMERR_NOTFOUND; - } - HRESULT SetAppData(LPD3DRM_APPDATA appData) override - { - m_appData = appData; - return D3DRM_OK; - } - LPVOID GetAppData() override { return m_appData; } - HRESULT SetName(const char* name) override - { - SDL_free(m_name); - m_name = NULL; - if (name) { - m_name = SDL_strdup(name); - } - return D3DRM_OK; - } - HRESULT GetName(DWORD* size, char* name) override - { - if (!size) { - return DDERR_INVALIDPARAMS; - } - const char* s = m_name ? m_name : ""; - size_t l = SDL_strlen(s); - if (name) { - SDL_strlcpy(name, s, *size); - } - else { - *size = l + 1; - } - return D3DRM_OK; - } - -private: - std::vector> m_callbacks; - LPD3DRM_APPDATA m_appData = nullptr; - char* m_name = nullptr; -}; - struct Direct3DRMMeshImpl : public Direct3DRMObjectBase { HRESULT Clone(int flags, GUID iid, void** object) override { @@ -211,11 +79,11 @@ struct Direct3DRMMeshImpl : public Direct3DRMObjectBase { } HRESULT GetGroup( int groupIndex, - unsigned int* vertexCount, - unsigned int* faceCount, - unsigned int* vertexPerFace, + DWORD* vertexCount, + DWORD* faceCount, + DWORD* vertexPerFace, DWORD* dataSize, - unsigned int* data + DWORD* data ) override { return DD_OK; @@ -263,214 +131,6 @@ struct Direct3DRMTextureImpl : public Direct3DRMObjectBase HRESULT Changed(BOOL pixels, BOOL palette) override { return DD_OK; } }; -SDL_GPUShader* CompileVertexShader(SDL_GPUDevice* device, VertexShaderId id) -{ - size_t size; - const SDL_GPUShaderCreateInfo* createInfo = GetVertexShaderCode(id, SDL_GetGPUShaderFormats(device)); - if (!createInfo) { - return NULL; - } - SDL_GPUShader* shader = SDL_CreateGPUShader(device, createInfo); - if (!shader) { - SDL_Log("Failed to create Vertex GPU shader: %s", SDL_GetError()); - } - return shader; -} - -SDL_GPUShader* CompileFragmentShader(SDL_GPUDevice* device, FragmentShaderId id) -{ - size_t size; - const SDL_GPUShaderCreateInfo* createInfo = GetFragmentShaderCode(id, SDL_GetGPUShaderFormats(device)); - if (!createInfo) { - return NULL; - } - SDL_GPUShader* shader = SDL_CreateGPUShader(device, createInfo); - if (!shader) { - SDL_Log("Failed to create Fragment GPU shader: %s", SDL_GetError()); - } - return shader; -} - -SDL_GPUDevice* m_device; -SDL_GPUGraphicsPipeline* m_pipeline; -SDL_GPUTexture* m_transferTexture; -SDL_GPUTransferBuffer* m_downloadTransferBuffer; -SDL_GPUBuffer* VertexBuffer; -int m_vertexCount = 3; - -struct Direct3DRMDevice2Impl : public Direct3DRMObjectBase { - Direct3DRMDevice2Impl() - { - m_device = SDL_CreateGPUDevice( - SDL_GPU_SHADERFORMAT_SPIRV | SDL_GPU_SHADERFORMAT_DXIL | SDL_GPU_SHADERFORMAT_MSL, - true, - NULL - ); - if (m_device == NULL) { - SDL_Log("GPUCreateDevice failed"); - return; - } - if (DDWindow == NULL) { - SDL_Log("CreateWindow failed: %s", SDL_GetError()); - return; - } - if (!SDL_ClaimWindowForGPUDevice(m_device, DDWindow)) { - SDL_Log("GPUClaimWindow failed"); - return; - } - SDL_GPUShader* vertexShader = CompileVertexShader(m_device, VertexShaderId::PositionColor); - if (vertexShader == NULL) { - SDL_Log("Failed to create vertex shader!"); - return; - } - SDL_GPUShader* fragmentShader = CompileFragmentShader(m_device, FragmentShaderId::SolidColor); - if (fragmentShader == NULL) { - SDL_Log("Failed to create fragment shader!"); - return; - } - - SDL_GPUColorTargetDescription colorTargets = {SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM_SRGB}; - SDL_GPUVertexBufferDescription vertexBufferDescs[] = { - {.slot = 0, - .pitch = sizeof(PositionColorVertex), - .input_rate = SDL_GPU_VERTEXINPUTRATE_VERTEX, - .instance_step_rate = 0} - }; - - SDL_GPUVertexAttribute vertexAttrs[] = { - {.location = 0, .buffer_slot = 0, .format = SDL_GPU_VERTEXELEMENTFORMAT_FLOAT3, .offset = 0}, - {.location = 1, - .buffer_slot = 0, - .format = SDL_GPU_VERTEXELEMENTFORMAT_UBYTE4_NORM, - .offset = sizeof(float) * 3} - }; - - SDL_GPUVertexInputState vertexInputState = { - .vertex_buffer_descriptions = vertexBufferDescs, - .num_vertex_buffers = 1, - .vertex_attributes = vertexAttrs, - .num_vertex_attributes = 2 - }; - - SDL_GPUGraphicsPipelineCreateInfo pipelineCreateInfo = - {.vertex_shader = vertexShader, - .fragment_shader = fragmentShader, - .vertex_input_state = vertexInputState, - .primitive_type = SDL_GPU_PRIMITIVETYPE_TRIANGLELIST, - .target_info = { - .color_target_descriptions = &colorTargets, - .num_color_targets = 1, - }}; - - m_pipeline = SDL_CreateGPUGraphicsPipeline(m_device, &pipelineCreateInfo); - if (m_pipeline == NULL) { - SDL_Log("Failed to create fill pipeline!"); - return; - } - - // Clean up shader resources - SDL_ReleaseGPUShader(m_device, vertexShader); - SDL_ReleaseGPUShader(m_device, fragmentShader); - // Create the vertex buffer - SDL_GPUBufferCreateInfo bufferCreateInfo = { - .usage = SDL_GPU_BUFFERUSAGE_VERTEX, - .size = (Uint32) (sizeof(PositionColorVertex) * m_vertexCount) - }; - - VertexBuffer = SDL_CreateGPUBuffer(m_device, &bufferCreateInfo); - - SDL_GPUTransferBufferCreateInfo transferCreateInfo = { - .usage = SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD, - .size = (Uint32) (sizeof(PositionColorVertex) * m_vertexCount) - }; - - SDL_GPUTransferBuffer* transferBuffer = SDL_CreateGPUTransferBuffer(m_device, &transferCreateInfo); - - PositionColorVertex* transferData = - (PositionColorVertex*) SDL_MapGPUTransferBuffer(m_device, transferBuffer, false); - - transferData[0] = (PositionColorVertex){-1, -1, 0, 255, 0, 0, 255}; - transferData[1] = (PositionColorVertex){1, -1, 0, 0, 0, 255, 255}; - transferData[2] = (PositionColorVertex){0, 1, 0, 0, 255, 0, 128}; - - SDL_UnmapGPUTransferBuffer(m_device, transferBuffer); - - // Upload the transfer data to the vertex buffer - SDL_GPUCommandBuffer* uploadCmdBuf = SDL_AcquireGPUCommandBuffer(m_device); - SDL_GPUCopyPass* copyPass = SDL_BeginGPUCopyPass(uploadCmdBuf); - - SDL_GPUTransferBufferLocation transferLocation = {.transfer_buffer = transferBuffer, .offset = 0}; - - SDL_GPUBufferRegion bufferRegion = - {.buffer = VertexBuffer, .offset = 0, .size = (Uint32) (sizeof(PositionColorVertex) * m_vertexCount)}; - - SDL_UploadToGPUBuffer(copyPass, &transferLocation, &bufferRegion, false); - - SDL_EndGPUCopyPass(copyPass); - SDL_SubmitGPUCommandBuffer(uploadCmdBuf); - SDL_ReleaseGPUTransferBuffer(m_device, transferBuffer); - - SDL_GPUTextureCreateInfo textureInfo = {}; - textureInfo.type = SDL_GPU_TEXTURETYPE_2D; - textureInfo.format = SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM_SRGB; - textureInfo.width = 640; - textureInfo.height = 480; - textureInfo.layer_count_or_depth = 1; - textureInfo.num_levels = 1; - textureInfo.usage = SDL_GPU_TEXTUREUSAGE_COLOR_TARGET; - m_transferTexture = SDL_CreateGPUTexture(m_device, &textureInfo); - if (m_transferTexture == NULL) { - SDL_Log("Failed to create fill pipeline!"); - return; - } - SDL_GPUTransferBufferCreateInfo downloadTransferInfo = { - .usage = SDL_GPU_TRANSFERBUFFERUSAGE_DOWNLOAD, - .size = 640 * 480 * 4 - }; - m_downloadTransferBuffer = SDL_CreateGPUTransferBuffer(m_device, &downloadTransferInfo); - if (!m_downloadTransferBuffer) { - return; - } - - m_viewports = new Direct3DRMViewportArrayImpl; - m_viewports->AddRef(); - } - ~Direct3DRMDevice2Impl() override - { - m_viewports->Release(); - - SDL_ReleaseGPUGraphicsPipeline(m_device, m_pipeline); - SDL_ReleaseWindowFromGPUDevice(m_device, DDWindow); - SDL_ReleaseGPUBuffer(m_device, VertexBuffer); - SDL_DestroyWindow(DDWindow); - SDL_DestroyGPUDevice(m_device); - } - unsigned int GetWidth() override { return 640; } - unsigned int GetHeight() override { return 480; } - HRESULT SetBufferCount(int count) override { return DD_OK; } - HRESULT GetBufferCount() override { return DD_OK; } - HRESULT SetShades(unsigned int shadeCount) override { return DD_OK; } - HRESULT GetShades() override { return DD_OK; } - HRESULT SetQuality(D3DRMRENDERQUALITY quality) override { return DD_OK; } - D3DRMRENDERQUALITY GetQuality() override { return D3DRMRENDERQUALITY::GOURAUD; } - HRESULT SetDither(int dither) override { return DD_OK; } - HRESULT GetDither() override { return DD_OK; } - HRESULT SetTextureQuality(D3DRMTEXTUREQUALITY quality) override { return DD_OK; } - D3DRMTEXTUREQUALITY GetTextureQuality() override { return D3DRMTEXTUREQUALITY::LINEAR; } - HRESULT SetRenderMode(D3DRMRENDERMODE mode) override { return DD_OK; } - D3DRMRENDERMODE GetRenderMode() override { return D3DRMRENDERMODE::BLENDEDTRANSPARENCY; } - HRESULT Update() override { return DD_OK; } - HRESULT AddViewport(IDirect3DRMViewport* viewport) override { return m_viewports->AddElement(viewport); } - HRESULT GetViewports(IDirect3DRMViewportArray** ppViewportArray) override - { - *ppViewportArray = m_viewports; - return DD_OK; - } - -private: - IDirect3DRMViewportArray* m_viewports; -}; - struct Direct3DRMFrameImpl : public Direct3DRMObjectBase { Direct3DRMFrameImpl() { @@ -550,130 +210,76 @@ struct Direct3DRMFrameImpl : public Direct3DRMObjectBase { IDirect3DRMTexture* m_texture = nullptr; }; -struct Direct3DRMViewportImpl : public Direct3DRMObjectBase { - HRESULT Render(IDirect3DRMFrame* group) override - { - if (!m_transferTexture || !DDBackBuffer) { - return DDERR_GENERIC; - } - SDL_GPUCommandBuffer* cmdbuf = SDL_AcquireGPUCommandBuffer(m_device); - if (cmdbuf == NULL) { - return DDERR_GENERIC; - } - - // Render the graphics - SDL_GPUColorTargetInfo colorTargetInfo = {}; - colorTargetInfo.texture = m_transferTexture; - // Make the render target transparent so we can combine it with the back buffer - colorTargetInfo.clear_color = {0, 0, 0, 0}; - colorTargetInfo.load_op = SDL_GPU_LOADOP_CLEAR; - - SDL_GPURenderPass* renderPass = SDL_BeginGPURenderPass(cmdbuf, &colorTargetInfo, 1, NULL); - SDL_BindGPUGraphicsPipeline(renderPass, m_pipeline); - SDL_GPUBufferBinding vertexBufferBinding = {.buffer = VertexBuffer, .offset = 0}; - SDL_BindGPUVertexBuffers(renderPass, 0, &vertexBufferBinding, 1); - SDL_DrawGPUPrimitives(renderPass, m_vertexCount, 1, 0, 0); - SDL_EndGPURenderPass(renderPass); - - // Download rendered image - SDL_GPUCopyPass* copyPass = SDL_BeginGPUCopyPass(cmdbuf); - SDL_GPUTextureRegion region = {}; - region.texture = m_transferTexture; - region.w = DDBackBuffer->w; - region.h = DDBackBuffer->h; - region.d = 1; - SDL_GPUTextureTransferInfo transferInfo = {}; - transferInfo.transfer_buffer = m_downloadTransferBuffer; - transferInfo.offset = 0; - SDL_DownloadFromGPUTexture(copyPass, ®ion, &transferInfo); - SDL_EndGPUCopyPass(copyPass); - SDL_GPUFence* fence = SDL_SubmitGPUCommandBufferAndAcquireFence(cmdbuf); - if (!cmdbuf || !SDL_WaitForGPUFences(m_device, true, &fence, 1)) { - return DDERR_GENERIC; - } - SDL_ReleaseGPUFence(m_device, fence); - void* downloadedData = SDL_MapGPUTransferBuffer(m_device, m_downloadTransferBuffer, false); - if (!downloadedData) { - return DDERR_GENERIC; - } - SDL_Surface* renderedImage = SDL_CreateSurfaceFrom( - DDBackBuffer->w, - DDBackBuffer->h, - SDL_PIXELFORMAT_ABGR8888, - downloadedData, - DDBackBuffer->w * 4 - ); - if (!renderedImage) { - return DDERR_GENERIC; - } - - // Blit the render back to our backbuffer - SDL_Rect srcRect{0, 0, DDBackBuffer->w, DDBackBuffer->h}; - - if (renderedImage->format == DDBackBuffer->format) { - // No conversion needed - SDL_BlitSurface(renderedImage, &srcRect, DDBackBuffer, &srcRect); - SDL_DestroySurface(renderedImage); - return DD_OK; - } - - const SDL_PixelFormatDetails* details = SDL_GetPixelFormatDetails(DDBackBuffer->format); - if (details->Amask != 0) { - // Backbuffer supports transparnacy - SDL_Surface* convertedRender = SDL_ConvertSurface(renderedImage, DDBackBuffer->format); - SDL_DestroySurface(renderedImage); - SDL_BlitSurface(convertedRender, &srcRect, DDBackBuffer, &srcRect); - SDL_DestroySurface(convertedRender); - return DD_OK; - } - - // Convert backbuffer to a format that supports transparancy - SDL_Surface* tempBackbuffer = SDL_ConvertSurface(DDBackBuffer, renderedImage->format); - SDL_BlitSurface(renderedImage, &srcRect, tempBackbuffer, &srcRect); - SDL_DestroySurface(renderedImage); - // Then convert the result back to the backbuffer format and write it back - SDL_Surface* newBackBuffer = SDL_ConvertSurface(tempBackbuffer, DDBackBuffer->format); - SDL_DestroySurface(tempBackbuffer); - SDL_BlitSurface(newBackBuffer, &srcRect, DDBackBuffer, &srcRect); - SDL_DestroySurface(newBackBuffer); - return DD_OK; - } - HRESULT ForceUpdate(int x, int y, int w, int h) override { return DD_OK; } - HRESULT Clear() override { return DD_OK; } - HRESULT SetCamera(IDirect3DRMFrame* camera) override - { - m_camera = camera; - return DD_OK; - } - HRESULT GetCamera(IDirect3DRMFrame** camera) override - { - *camera = m_camera; - return DD_OK; - } - HRESULT SetProjection(D3DRMPROJECTIONTYPE type) override { return DD_OK; } - D3DRMPROJECTIONTYPE GetProjection() override { return D3DRMPROJECTIONTYPE::PERSPECTIVE; } - HRESULT SetFront(D3DVALUE z) override { return DD_OK; } - D3DVALUE GetFront() override { return 0; } - HRESULT SetBack(D3DVALUE z) override { return DD_OK; } - D3DVALUE GetBack() override { return 0; } - HRESULT SetField(D3DVALUE field) override { return DD_OK; } - D3DVALUE GetField() override { return 0; } - int GetWidth() override { return 640; } - int GetHeight() override { return 480; } - HRESULT Transform(D3DRMVECTOR4D* screen, D3DVECTOR* world) override { return DD_OK; } - HRESULT InverseTransform(D3DVECTOR* world, D3DRMVECTOR4D* screen) override { return DD_OK; } - HRESULT Pick(float x, float y, LPDIRECT3DRMPICKEDARRAY* pickedArray) override { return DD_OK; } - -private: - IDirect3DRMFrame* m_camera = nullptr; -}; - struct Direct3DRMLightImpl : public Direct3DRMObjectBase { HRESULT SetColorRGB(float r, float g, float b) override { return DD_OK; } }; struct Direct3DRMMaterialImpl : public Direct3DRMObjectBase {}; +SDL_GPUGraphicsPipeline* InitializeGraphicsPipeline(SDL_GPUDevice* device) +{ + const SDL_GPUShaderCreateInfo* vertexCreateInfo = + GetVertexShaderCode(VertexShaderId::PositionColor, SDL_GetGPUShaderFormats(device)); + if (!vertexCreateInfo) { + return nullptr; + } + SDL_GPUShader* vertexShader = SDL_CreateGPUShader(device, vertexCreateInfo); + if (!vertexShader) { + return nullptr; + } + + const SDL_GPUShaderCreateInfo* fragmentCreateInfo = + GetFragmentShaderCode(FragmentShaderId::SolidColor, SDL_GetGPUShaderFormats(device)); + if (!fragmentCreateInfo) { + return nullptr; + } + SDL_GPUShader* fragmentShader = SDL_CreateGPUShader(device, fragmentCreateInfo); + if (!fragmentShader) { + return nullptr; + } + + SDL_GPUVertexBufferDescription vertexBufferDescs[1] = {}; + vertexBufferDescs[0].slot = 0; + vertexBufferDescs[0].pitch = sizeof(PositionColorVertex); + vertexBufferDescs[0].input_rate = SDL_GPU_VERTEXINPUTRATE_VERTEX; + vertexBufferDescs[0].instance_step_rate = 0; + + SDL_GPUVertexAttribute vertexAttrs[2] = {}; + vertexAttrs[0].location = 0; + vertexAttrs[0].buffer_slot = 0; + vertexAttrs[0].format = SDL_GPU_VERTEXELEMENTFORMAT_FLOAT3; + vertexAttrs[0].offset = 0; + + vertexAttrs[1].location = 1; + vertexAttrs[1].buffer_slot = 0; + vertexAttrs[1].format = SDL_GPU_VERTEXELEMENTFORMAT_UBYTE4_NORM; + vertexAttrs[1].offset = sizeof(float) * 3; + + SDL_GPUVertexInputState vertexInputState = {}; + vertexInputState.vertex_buffer_descriptions = vertexBufferDescs; + vertexInputState.num_vertex_buffers = 1; + vertexInputState.vertex_attributes = vertexAttrs; + vertexInputState.num_vertex_attributes = 2; + + SDL_GPUColorTargetDescription colorTargets = {}; + colorTargets.format = SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM_SRGB; + + SDL_GPUGraphicsPipelineCreateInfo pipelineCreateInfo = {}; + pipelineCreateInfo.vertex_shader = vertexShader; + pipelineCreateInfo.fragment_shader = fragmentShader; + pipelineCreateInfo.vertex_input_state = vertexInputState; + pipelineCreateInfo.primitive_type = SDL_GPU_PRIMITIVETYPE_TRIANGLELIST; + pipelineCreateInfo.target_info.color_target_descriptions = &colorTargets; + pipelineCreateInfo.target_info.num_color_targets = 1; + + SDL_GPUGraphicsPipeline* pipeline = SDL_CreateGPUGraphicsPipeline(device, &pipelineCreateInfo); + // Clean up shader resources + SDL_ReleaseGPUShader(device, vertexShader); + SDL_ReleaseGPUShader(device, fragmentShader); + + return pipeline; +} + struct Direct3DRMImpl : virtual public IDirect3DRM2 { // IUnknown interface HRESULT QueryInterface(const GUID& riid, void** ppvObject) override @@ -683,15 +289,34 @@ struct Direct3DRMImpl : virtual public IDirect3DRM2 { *ppvObject = static_cast(this); return DD_OK; } - SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "DirectDrawImpl does not implement guid"); + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Direct3DRMImpl does not implement guid"); return E_NOINTERFACE; } // IDirect3DRM interface + HRESULT CreateDevice(IDirect3DRMDevice2** outDevice, DWORD width, DWORD height) + { + SDL_GPUDevice* device = SDL_CreateGPUDevice( + SDL_GPU_SHADERFORMAT_SPIRV | SDL_GPU_SHADERFORMAT_DXIL | SDL_GPU_SHADERFORMAT_MSL, + true, + NULL + ); + if (device == NULL) { + return DDERR_GENERIC; + } + if (DDWindow == NULL) { + return DDERR_GENERIC; + } + if (!SDL_ClaimWindowForGPUDevice(device, DDWindow)) { + return DDERR_GENERIC; + } + + *outDevice = static_cast(new Direct3DRMDevice2Impl(width, height, device)); + return DD_OK; + } HRESULT CreateDeviceFromD3D(const IDirect3D2* d3d, IDirect3DDevice2* d3dDevice, IDirect3DRMDevice2** outDevice) override { - *outDevice = static_cast(new Direct3DRMDevice2Impl); - return DD_OK; + return CreateDevice(outDevice, 640, 480); } HRESULT CreateDeviceFromSurface( const GUID* guid, @@ -700,8 +325,10 @@ struct Direct3DRMImpl : virtual public IDirect3DRM2 { IDirect3DRMDevice2** outDevice ) override { - *outDevice = static_cast(new Direct3DRMDevice2Impl); - return DD_OK; + DDSURFACEDESC DDSDesc; + DDSDesc.dwSize = sizeof(DDSURFACEDESC); + surface->GetSurfaceDesc(&DDSDesc); + return CreateDevice(outDevice, DDSDesc.dwWidth, DDSDesc.dwHeight); } HRESULT CreateTexture(D3DRMIMAGE* image, IDirect3DRMTexture2** outTexture) override { @@ -734,7 +361,7 @@ struct Direct3DRMImpl : virtual public IDirect3DRM2 { return DD_OK; } HRESULT CreateViewport( - IDirect3DRMDevice2* device, + IDirect3DRMDevice2* iDevice, IDirect3DRMFrame* camera, int x, int y, @@ -743,12 +370,49 @@ struct Direct3DRMImpl : virtual public IDirect3DRM2 { IDirect3DRMViewport** outViewport ) override { - *outViewport = static_cast(new Direct3DRMViewportImpl); + auto device = static_cast(iDevice); + + SDL_GPUGraphicsPipeline* pipeline = InitializeGraphicsPipeline(device->m_device); + if (!pipeline) { + return DDERR_GENERIC; + } + + SDL_GPUTextureCreateInfo textureInfo = {}; + textureInfo.type = SDL_GPU_TEXTURETYPE_2D; + textureInfo.format = SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM_SRGB; + textureInfo.width = width; + textureInfo.height = height; + textureInfo.layer_count_or_depth = 1; + textureInfo.num_levels = 1; + textureInfo.usage = SDL_GPU_TEXTUREUSAGE_COLOR_TARGET; + SDL_GPUTexture* transferTexture = SDL_CreateGPUTexture(device->m_device, &textureInfo); + if (transferTexture == NULL) { + return DDERR_GENERIC; + } + + // Setup texture GPU-to-CPU transfer + SDL_GPUTransferBufferCreateInfo downloadTransferInfo = {}; + downloadTransferInfo.usage = SDL_GPU_TRANSFERBUFFERUSAGE_DOWNLOAD; + downloadTransferInfo.size = static_cast(width * height * 4); + SDL_GPUTransferBuffer* downloadTransferBuffer = + SDL_CreateGPUTransferBuffer(device->m_device, &downloadTransferInfo); + if (!downloadTransferBuffer) { + return DDERR_GENERIC; + } + + *outViewport = static_cast(new Direct3DRMViewportImpl( + width, + height, + device->m_device, + transferTexture, + downloadTransferBuffer, + pipeline + )); device->AddViewport(*outViewport); return DD_OK; } - HRESULT SetDefaultTextureShades(unsigned int count) override { return DD_OK; } - HRESULT SetDefaultTextureColors(unsigned int count) override { return DD_OK; } + HRESULT SetDefaultTextureShades(DWORD count) override { return DD_OK; } + HRESULT SetDefaultTextureColors(DWORD count) override { return DD_OK; } }; HRESULT WINAPI Direct3DRMCreate(IDirect3DRM** direct3DRM) diff --git a/miniwin/miniwin/src/miniwin_d3drmdevice.cpp b/miniwin/miniwin/src/miniwin_d3drmdevice.cpp new file mode 100644 index 00000000..f45cec28 --- /dev/null +++ b/miniwin/miniwin/src/miniwin_d3drmdevice.cpp @@ -0,0 +1,117 @@ +#include "miniwin_d3drm.h" +#include "miniwin_d3drm_p.h" +#include "miniwin_d3drmobject_p.h" +#include "miniwin_d3drmviewport_p.h" + +#include + +Direct3DRMDevice2Impl::Direct3DRMDevice2Impl(DWORD width, DWORD height, SDL_GPUDevice* device) + : m_width(width), m_height(height), m_device(device), m_viewports(new Direct3DRMViewportArrayImpl) +{ +} + +Direct3DRMDevice2Impl::~Direct3DRMDevice2Impl() +{ + for (int i = 0; i < m_viewports->GetSize(); i++) { + IDirect3DRMViewport* viewport; + m_viewports->GetElement(i, &viewport); + static_cast(viewport)->CloseDevice(); + viewport->Release(); + } + m_viewports->Release(); + + SDL_ReleaseWindowFromGPUDevice(m_device, DDWindow); + SDL_DestroyGPUDevice(m_device); +} + +DWORD Direct3DRMDevice2Impl::GetWidth() +{ + return m_width; +} + +DWORD Direct3DRMDevice2Impl::GetHeight() +{ + return m_height; +} + +HRESULT Direct3DRMDevice2Impl::SetBufferCount(int count) +{ + return DD_OK; +} + +HRESULT Direct3DRMDevice2Impl::GetBufferCount() +{ + return DD_OK; +} + +HRESULT Direct3DRMDevice2Impl::SetShades(DWORD shadeCount) +{ + return DD_OK; +} + +HRESULT Direct3DRMDevice2Impl::GetShades() +{ + return DD_OK; +} + +HRESULT Direct3DRMDevice2Impl::SetQuality(D3DRMRENDERQUALITY quality) +{ + return DD_OK; +} + +D3DRMRENDERQUALITY Direct3DRMDevice2Impl::GetQuality() +{ + return D3DRMRENDERQUALITY::GOURAUD; +} + +HRESULT Direct3DRMDevice2Impl::SetDither(int dither) +{ + return DD_OK; +} + +HRESULT Direct3DRMDevice2Impl::GetDither() +{ + return DD_OK; +} + +HRESULT Direct3DRMDevice2Impl::SetTextureQuality(D3DRMTEXTUREQUALITY quality) +{ + return DD_OK; +} + +D3DRMTEXTUREQUALITY Direct3DRMDevice2Impl::GetTextureQuality() +{ + return D3DRMTEXTUREQUALITY::LINEAR; +} + +HRESULT Direct3DRMDevice2Impl::SetRenderMode(D3DRMRENDERMODE mode) +{ + return DD_OK; +} + +D3DRMRENDERMODE Direct3DRMDevice2Impl::GetRenderMode() +{ + return D3DRMRENDERMODE::BLENDEDTRANSPARENCY; +} + +HRESULT Direct3DRMDevice2Impl::Update() +{ + for (int i = 0; i < m_viewports->GetSize(); i++) { + IDirect3DRMViewport* viewport; + m_viewports->GetElement(i, &viewport); + static_cast(viewport)->Update(); + } + + return DD_OK; +} + +HRESULT Direct3DRMDevice2Impl::AddViewport(IDirect3DRMViewport* viewport) +{ + return m_viewports->AddElement(viewport); +} + +HRESULT Direct3DRMDevice2Impl::GetViewports(IDirect3DRMViewportArray** ppViewportArray) +{ + *ppViewportArray = m_viewports; + return DD_OK; +} diff --git a/miniwin/miniwin/src/miniwin_d3drmviewport.cpp b/miniwin/miniwin/src/miniwin_d3drmviewport.cpp new file mode 100644 index 00000000..a8b3bbeb --- /dev/null +++ b/miniwin/miniwin/src/miniwin_d3drmviewport.cpp @@ -0,0 +1,267 @@ +#include "miniwin_d3drm_p.h" +#include "miniwin_d3drmviewport_p.h" + +#include + +Direct3DRMViewportImpl::Direct3DRMViewportImpl( + DWORD width, + DWORD height, + SDL_GPUDevice* device, + SDL_GPUTexture* transferTexture, + SDL_GPUTransferBuffer* downloadTransferBuffer, + SDL_GPUGraphicsPipeline* pipeline +) + : m_width(width), m_height(height), m_device(device), m_transferTexture(transferTexture), + m_downloadTransferBuffer(downloadTransferBuffer), m_pipeline(pipeline) +{ +} + +void Direct3DRMViewportImpl::FreeDeviceResources() +{ + SDL_ReleaseGPUBuffer(m_device, m_vertexBuffer); + SDL_ReleaseGPUGraphicsPipeline(m_device, m_pipeline); +} + +Direct3DRMViewportImpl::~Direct3DRMViewportImpl() +{ + FreeDeviceResources(); +} + +void Direct3DRMViewportImpl::Update() +{ + m_vertexCount = 3; + + SDL_GPUBufferCreateInfo bufferCreateInfo = {}; + bufferCreateInfo.usage = SDL_GPU_BUFFERUSAGE_VERTEX; + bufferCreateInfo.size = static_cast(sizeof(PositionColorVertex) * m_vertexCount); + + m_vertexBuffer = SDL_CreateGPUBuffer(m_device, &bufferCreateInfo); + + SDL_GPUTransferBufferCreateInfo transferCreateInfo = {}; + transferCreateInfo.usage = SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD; + transferCreateInfo.size = static_cast(sizeof(PositionColorVertex) * m_vertexCount); + + SDL_GPUTransferBuffer* transferBuffer = SDL_CreateGPUTransferBuffer(m_device, &transferCreateInfo); + + PositionColorVertex* transferData = + (PositionColorVertex*) SDL_MapGPUTransferBuffer(m_device, transferBuffer, false); + + transferData[0] = {-1, -1, 0, 255, 0, 0, 255}; + transferData[1] = {1, -1, 0, 0, 0, 255, 255}; + transferData[2] = {0, 1, 0, 0, 255, 0, 128}; + + SDL_UnmapGPUTransferBuffer(m_device, transferBuffer); + + // Upload the transfer data to the vertex buffer + SDL_GPUCommandBuffer* uploadCmdBuf = SDL_AcquireGPUCommandBuffer(m_device); + SDL_GPUCopyPass* copyPass = SDL_BeginGPUCopyPass(uploadCmdBuf); + SDL_GPUTransferBufferLocation transferLocation = {}; + transferLocation.transfer_buffer = transferBuffer; + transferLocation.offset = 0; + + SDL_GPUBufferRegion bufferRegion = {}; + bufferRegion.buffer = m_vertexBuffer; + bufferRegion.offset = 0; + bufferRegion.size = static_cast(sizeof(PositionColorVertex) * m_vertexCount); + + SDL_UploadToGPUBuffer(copyPass, &transferLocation, &bufferRegion, false); + + SDL_EndGPUCopyPass(copyPass); + SDL_SubmitGPUCommandBuffer(uploadCmdBuf); + SDL_ReleaseGPUTransferBuffer(m_device, transferBuffer); + + m_updated = true; +} + +HRESULT Direct3DRMViewportImpl::Render(IDirect3DRMFrame* group) +{ + if (!m_updated) { + return DDERR_GENERIC; + } + + if (!m_device) { + return DDERR_GENERIC; + } + + SDL_GPUCommandBuffer* cmdbuf = SDL_AcquireGPUCommandBuffer(m_device); + if (cmdbuf == NULL) { + return DDERR_GENERIC; + } + + // Render the graphics + SDL_GPUColorTargetInfo colorTargetInfo = {}; + colorTargetInfo.texture = m_transferTexture; + // Make the render target transparent so we can combine it with the back buffer + colorTargetInfo.clear_color = {0, 0, 0, 0}; + colorTargetInfo.load_op = SDL_GPU_LOADOP_CLEAR; + SDL_GPURenderPass* renderPass = SDL_BeginGPURenderPass(cmdbuf, &colorTargetInfo, 1, NULL); + SDL_BindGPUGraphicsPipeline(renderPass, m_pipeline); + SDL_GPUBufferBinding vertexBufferBinding = {}; + vertexBufferBinding.buffer = m_vertexBuffer; + vertexBufferBinding.offset = 0; + SDL_BindGPUVertexBuffers(renderPass, 0, &vertexBufferBinding, 1); + SDL_DrawGPUPrimitives(renderPass, m_vertexCount, 1, 0, 0); + SDL_EndGPURenderPass(renderPass); + + // Download rendered image + SDL_GPUCopyPass* copyPass = SDL_BeginGPUCopyPass(cmdbuf); + SDL_GPUTextureRegion region = {}; + region.texture = m_transferTexture; + region.w = DDBackBuffer->w; + region.h = DDBackBuffer->h; + region.d = 1; + SDL_GPUTextureTransferInfo transferInfo = {}; + transferInfo.transfer_buffer = m_downloadTransferBuffer; + transferInfo.offset = 0; + SDL_DownloadFromGPUTexture(copyPass, ®ion, &transferInfo); + SDL_EndGPUCopyPass(copyPass); + SDL_GPUFence* fence = SDL_SubmitGPUCommandBufferAndAcquireFence(cmdbuf); + if (!cmdbuf || !SDL_WaitForGPUFences(m_device, true, &fence, 1)) { + return DDERR_GENERIC; + } + SDL_ReleaseGPUFence(m_device, fence); + void* downloadedData = SDL_MapGPUTransferBuffer(m_device, m_downloadTransferBuffer, false); + if (!downloadedData) { + return DDERR_GENERIC; + } + + m_updated = false; + + SDL_DestroySurface(m_renderedImage); + m_renderedImage = SDL_CreateSurfaceFrom( + DDBackBuffer->w, + DDBackBuffer->h, + SDL_PIXELFORMAT_ABGR8888, + downloadedData, + DDBackBuffer->w * 4 + ); + + SDL_Surface* convertedRender = SDL_ConvertSurface(m_renderedImage, SDL_PIXELFORMAT_RGBA8888); + SDL_DestroySurface(m_renderedImage); + SDL_UnmapGPUTransferBuffer(m_device, m_downloadTransferBuffer); + m_renderedImage = convertedRender; + + return ForceUpdate(0, 0, DDBackBuffer->w, DDBackBuffer->h); +} + +HRESULT Direct3DRMViewportImpl::ForceUpdate(int x, int y, int w, int h) +{ + if (!m_renderedImage) { + return DDERR_GENERIC; + } + // Blit the render back to our backbuffer + SDL_Rect srcRect{0, 0, DDBackBuffer->w, DDBackBuffer->h}; + + const SDL_PixelFormatDetails* details = SDL_GetPixelFormatDetails(DDBackBuffer->format); + if (details->Amask != 0) { + // Backbuffer supports transparnacy + SDL_Surface* convertedRender = SDL_ConvertSurface(m_renderedImage, DDBackBuffer->format); + SDL_DestroySurface(m_renderedImage); + m_renderedImage = convertedRender; + return DD_OK; + } + + if (m_renderedImage->format == DDBackBuffer->format) { + // No conversion needed + SDL_BlitSurface(m_renderedImage, &srcRect, DDBackBuffer, &srcRect); + return DD_OK; + } + + // Convert backbuffer to a format that supports transparancy + SDL_Surface* tempBackbuffer = SDL_ConvertSurface(DDBackBuffer, m_renderedImage->format); + SDL_BlitSurface(m_renderedImage, &srcRect, tempBackbuffer, &srcRect); + // Then convert the result back to the backbuffer format and write it back + SDL_Surface* newBackBuffer = SDL_ConvertSurface(tempBackbuffer, DDBackBuffer->format); + SDL_DestroySurface(tempBackbuffer); + SDL_BlitSurface(newBackBuffer, &srcRect, DDBackBuffer, &srcRect); + SDL_DestroySurface(newBackBuffer); + return DD_OK; +} + +HRESULT Direct3DRMViewportImpl::Clear() +{ + return DD_OK; +} + +HRESULT Direct3DRMViewportImpl::SetCamera(IDirect3DRMFrame* camera) +{ + m_camera = camera; + return DD_OK; +} + +HRESULT Direct3DRMViewportImpl::GetCamera(IDirect3DRMFrame** camera) +{ + *camera = m_camera; + return DD_OK; +} + +HRESULT Direct3DRMViewportImpl::SetProjection(D3DRMPROJECTIONTYPE type) +{ + return DD_OK; +} + +D3DRMPROJECTIONTYPE Direct3DRMViewportImpl::GetProjection() +{ + return D3DRMPROJECTIONTYPE::PERSPECTIVE; +} + +HRESULT Direct3DRMViewportImpl::SetFront(D3DVALUE z) +{ + return DD_OK; +} + +D3DVALUE Direct3DRMViewportImpl::GetFront() +{ + return 0; +} + +HRESULT Direct3DRMViewportImpl::SetBack(D3DVALUE z) +{ + return DD_OK; +} + +D3DVALUE Direct3DRMViewportImpl::GetBack() +{ + return 0; +} + +HRESULT Direct3DRMViewportImpl::SetField(D3DVALUE field) +{ + return DD_OK; +} + +D3DVALUE Direct3DRMViewportImpl::GetField() +{ + return 0; +} + +DWORD Direct3DRMViewportImpl::GetWidth() +{ + return m_width; +} + +DWORD Direct3DRMViewportImpl::GetHeight() +{ + return m_height; +} + +HRESULT Direct3DRMViewportImpl::Transform(D3DRMVECTOR4D* screen, D3DVECTOR* world) +{ + return DD_OK; +} + +HRESULT Direct3DRMViewportImpl::InverseTransform(D3DVECTOR* world, D3DRMVECTOR4D* screen) +{ + return DD_OK; +} + +HRESULT Direct3DRMViewportImpl::Pick(float x, float y, LPDIRECT3DRMPICKEDARRAY* pickedArray) +{ + return DD_OK; +} + +void Direct3DRMViewportImpl::CloseDevice() +{ + FreeDeviceResources(); + m_device = nullptr; +} diff --git a/miniwin/miniwin/src/miniwin_ddsurface.cpp b/miniwin/miniwin/src/miniwin_ddsurface.cpp index b04c2e77..1c8f5a78 100644 --- a/miniwin/miniwin/src/miniwin_ddsurface.cpp +++ b/miniwin/miniwin/src/miniwin_ddsurface.cpp @@ -35,7 +35,7 @@ HRESULT DirectDrawSurfaceImpl::QueryInterface(const GUID& riid, void** ppvObject *ppvObject = static_cast(this); return S_OK; } - SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "DirectDrawImpl does not implement guid"); + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "DirectDrawSurfaceImpl does not implement guid"); return E_NOINTERFACE; }