Move 2D rendering to GPU: part 1

This commit is contained in:
Anders Jenbo 2025-06-15 18:47:19 +02:00
parent e6a005fd33
commit 2ed68c8c26
20 changed files with 746 additions and 365 deletions

View File

@ -61,11 +61,6 @@ void MxDisplaySurface::ClearScreen()
backBuffers = m_videoParam.GetBackBuffers() + 1; backBuffers = m_videoParam.GetBackBuffers() + 1;
} }
MxS32 width = m_videoParam.GetRect().GetWidth();
MxS32 height = m_videoParam.GetRect().GetHeight();
RECT rc = {0, 0, width, height};
memset(&desc, 0, sizeof(desc)); memset(&desc, 0, sizeof(desc));
desc.dwSize = sizeof(desc); desc.dwSize = sizeof(desc);
if (m_ddSurface2->GetSurfaceDesc(&desc) != DD_OK) { if (m_ddSurface2->GetSurfaceDesc(&desc) != DD_OK) {
@ -77,9 +72,9 @@ void MxDisplaySurface::ClearScreen()
ddBltFx.dwFillColor = 0; ddBltFx.dwFillColor = 0;
for (MxS32 i = 0; i < backBuffers; i++) { for (MxS32 i = 0; i < backBuffers; i++) {
if (m_ddSurface2->Blt(&rc, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddBltFx) == DDERR_SURFACELOST) { if (m_ddSurface2->Blt(NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddBltFx) == DDERR_SURFACELOST) {
m_ddSurface2->Restore(); m_ddSurface2->Restore();
m_ddSurface2->Blt(&rc, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddBltFx); m_ddSurface2->Blt(NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddBltFx);
} }
if (m_videoParam.Flags().GetFlipSurfaces()) { if (m_videoParam.Flags().GetFlipSurfaces()) {

View File

@ -6,9 +6,10 @@ add_library(miniwin STATIC EXCLUDE_FROM_ALL
src/windows/windows.cpp src/windows/windows.cpp
# DDraw # DDraw
src/ddraw/ddraw.cpp
src/ddraw/ddpalette.cpp src/ddraw/ddpalette.cpp
src/ddraw/ddraw.cpp
src/ddraw/ddsurface.cpp src/ddraw/ddsurface.cpp
src/ddraw/framebuffer.cpp
# D3DRM # D3DRM
src/d3drm/d3drm.cpp src/d3drm/d3drm.cpp
@ -21,9 +22,9 @@ add_library(miniwin STATIC EXCLUDE_FROM_ALL
src/internal/meshutils.cpp src/internal/meshutils.cpp
# D3DRM backends # D3DRM backends
src/d3drm/backends/software/renderer.cpp
src/d3drm/backends/sdl3gpu/renderer.cpp src/d3drm/backends/sdl3gpu/renderer.cpp
src/d3drm/backends/sdl3gpu/shaders/generated/ShaderIndex.cpp src/d3drm/backends/sdl3gpu/shaders/generated/ShaderIndex.cpp
src/d3drm/backends/software/renderer.cpp
) )
find_package(OpenGL) find_package(OpenGL)

View File

@ -347,7 +347,7 @@ struct IDirect3DRM : virtual public IUnknown {
IDirect3DRMDevice2** outDevice IDirect3DRMDevice2** outDevice
) = 0; ) = 0;
virtual HRESULT CreateTexture(D3DRMIMAGE* image, IDirect3DRMTexture2** outTexture) = 0; virtual HRESULT CreateTexture(D3DRMIMAGE* image, IDirect3DRMTexture2** outTexture) = 0;
virtual HRESULT CreateTextureFromSurface(LPDIRECTDRAWSURFACE surface, IDirect3DRMTexture2** outTexture) = 0; virtual HRESULT CreateTextureFromSurface(IDirectDrawSurface* surface, IDirect3DRMTexture2** outTexture) = 0;
virtual HRESULT CreateMesh(IDirect3DRMMesh** outMesh) = 0; virtual HRESULT CreateMesh(IDirect3DRMMesh** outMesh) = 0;
virtual HRESULT CreateMaterial(D3DVAL power, IDirect3DRMMaterial** outMaterial) = 0; virtual HRESULT CreateMaterial(D3DVAL power, IDirect3DRMMaterial** outMaterial) = 0;
virtual HRESULT CreateLightRGB(D3DRMLIGHTTYPE type, D3DVAL r, D3DVAL g, D3DVAL b, IDirect3DRMLight** outLight) = 0; virtual HRESULT CreateLightRGB(D3DRMLIGHTTYPE type, D3DVAL r, D3DVAL g, D3DVAL b, IDirect3DRMLight** outLight) = 0;

View File

@ -311,10 +311,10 @@ typedef IDirectDrawClipper* LPDIRECTDRAWCLIPPER;
typedef struct IDirectDrawSurface* LPDIRECTDRAWSURFACE; typedef struct IDirectDrawSurface* LPDIRECTDRAWSURFACE;
struct IDirectDrawSurface : virtual public IUnknown { struct IDirectDrawSurface : virtual public IUnknown {
virtual HRESULT AddAttachedSurface(LPDIRECTDRAWSURFACE lpDDSAttachedSurface) = 0; virtual HRESULT AddAttachedSurface(IDirectDrawSurface* lpDDSAttachedSurface) = 0;
virtual HRESULT Blt( virtual HRESULT Blt(
LPRECT lpDestRect, LPRECT lpDestRect,
LPDIRECTDRAWSURFACE lpDDSrcSurface, IDirectDrawSurface* lpDDSrcSurface,
LPRECT lpSrcRect, LPRECT lpSrcRect,
DDBltFlags dwFlags, DDBltFlags dwFlags,
LPDDBLTFX lpDDBltFx LPDDBLTFX lpDDBltFx
@ -322,21 +322,21 @@ struct IDirectDrawSurface : virtual public IUnknown {
virtual HRESULT BltFast( virtual HRESULT BltFast(
DWORD dwX, DWORD dwX,
DWORD dwY, DWORD dwY,
LPDIRECTDRAWSURFACE lpDDSrcSurface, IDirectDrawSurface* lpDDSrcSurface,
LPRECT lpSrcRect, LPRECT lpSrcRect,
DDBltFastFlags dwTrans DDBltFastFlags dwTrans
) = 0; ) = 0;
virtual HRESULT Flip(LPDIRECTDRAWSURFACE lpDDSurfaceTargetOverride, DDFlipFlags dwFlags) = 0; virtual HRESULT Flip(IDirectDrawSurface* lpDDSurfaceTargetOverride, DDFlipFlags dwFlags) = 0;
virtual HRESULT GetAttachedSurface(LPDDSCAPS lpDDSCaps, LPDIRECTDRAWSURFACE* lplpDDAttachedSurface) = 0; virtual HRESULT GetAttachedSurface(LPDDSCAPS lpDDSCaps, IDirectDrawSurface** lplpDDAttachedSurface) = 0;
virtual HRESULT GetDC(HDC* lphDC) = 0; virtual HRESULT GetDC(HDC* lphDC) = 0;
virtual HRESULT GetPalette(LPDIRECTDRAWPALETTE* lplpDDPalette) = 0; virtual HRESULT GetPalette(LPDIRECTDRAWPALETTE* lplpDDPalette) = 0;
virtual HRESULT GetPixelFormat(LPDDPIXELFORMAT lpDDPixelFormat) = 0; virtual HRESULT GetPixelFormat(LPDDPIXELFORMAT lpDDPixelFormat) = 0;
virtual HRESULT GetSurfaceDesc(LPDDSURFACEDESC lpDDSurfaceDesc) = 0; virtual HRESULT GetSurfaceDesc(DDSURFACEDESC* lpDDSurfaceDesc) = 0;
virtual HRESULT IsLost() = 0; virtual HRESULT IsLost() = 0;
virtual HRESULT Lock(LPRECT lpDestRect, LPDDSURFACEDESC lpDDSurfaceDesc, DDLockFlags dwFlags, HANDLE hEvent) = 0; virtual HRESULT Lock(LPRECT lpDestRect, DDSURFACEDESC* lpDDSurfaceDesc, DDLockFlags dwFlags, HANDLE hEvent) = 0;
virtual HRESULT ReleaseDC(HDC hDC) = 0; virtual HRESULT ReleaseDC(HDC hDC) = 0;
virtual HRESULT Restore() = 0; virtual HRESULT Restore() = 0;
virtual HRESULT SetClipper(LPDIRECTDRAWCLIPPER lpDDClipper) = 0; virtual HRESULT SetClipper(IDirectDrawClipper* lpDDClipper) = 0;
virtual HRESULT SetColorKey(DDColorKeyFlags dwFlags, LPDDCOLORKEY lpDDColorKey) = 0; virtual HRESULT SetColorKey(DDColorKeyFlags dwFlags, LPDDCOLORKEY lpDDColorKey) = 0;
virtual HRESULT SetPalette(LPDIRECTDRAWPALETTE lpDDPalette) = 0; virtual HRESULT SetPalette(LPDIRECTDRAWPALETTE lpDDPalette) = 0;
virtual HRESULT Unlock(LPVOID lpSurfaceData) = 0; virtual HRESULT Unlock(LPVOID lpSurfaceData) = 0;
@ -345,9 +345,9 @@ struct IDirectDrawSurface : virtual public IUnknown {
struct IDirectDrawSurface3 : public IDirectDrawSurface {}; struct IDirectDrawSurface3 : public IDirectDrawSurface {};
typedef IDirectDrawSurface3* LPDIRECTDRAWSURFACE3; typedef IDirectDrawSurface3* LPDIRECTDRAWSURFACE3;
typedef HRESULT (*LPDDENUMMODESCALLBACK)(LPDDSURFACEDESC, LPVOID); typedef HRESULT (*LPDDENUMMODESCALLBACK)(DDSURFACEDESC*, LPVOID);
struct IDirectDraw : virtual public IUnknown { struct IDirectDraw : virtual public IUnknown {
virtual HRESULT CreateClipper(DWORD dwFlags, LPDIRECTDRAWCLIPPER* lplpDDClipper, IUnknown* pUnkOuter) = 0; virtual HRESULT CreateClipper(DWORD dwFlags, IDirectDrawClipper** lplpDDClipper, IUnknown* pUnkOuter) = 0;
virtual HRESULT CreatePalette( virtual HRESULT CreatePalette(
DDPixelCaps dwFlags, DDPixelCaps dwFlags,
LPPALETTEENTRY lpColorTable, LPPALETTEENTRY lpColorTable,
@ -355,19 +355,19 @@ struct IDirectDraw : virtual public IUnknown {
IUnknown* pUnkOuter IUnknown* pUnkOuter
) = 0; ) = 0;
virtual HRESULT CreateSurface( virtual HRESULT CreateSurface(
LPDDSURFACEDESC lpDDSurfaceDesc, DDSURFACEDESC* lpDDSurfaceDesc,
LPDIRECTDRAWSURFACE* lplpDDSurface, IDirectDrawSurface** lplpDDSurface,
IUnknown* pUnkOuter IUnknown* pUnkOuter
) = 0; ) = 0;
virtual HRESULT EnumDisplayModes( virtual HRESULT EnumDisplayModes(
DWORD dwFlags, DWORD dwFlags,
LPDDSURFACEDESC lpDDSurfaceDesc, DDSURFACEDESC* lpDDSurfaceDesc,
LPVOID lpContext, LPVOID lpContext,
LPDDENUMMODESCALLBACK lpEnumModesCallback LPDDENUMMODESCALLBACK lpEnumModesCallback
) = 0; ) = 0;
virtual HRESULT FlipToGDISurface() = 0; virtual HRESULT FlipToGDISurface() = 0;
virtual HRESULT GetCaps(LPDDCAPS lpDDDriverCaps, LPDDCAPS lpDDHELCaps) = 0; virtual HRESULT GetCaps(LPDDCAPS lpDDDriverCaps, LPDDCAPS lpDDHELCaps) = 0;
virtual HRESULT GetDisplayMode(LPDDSURFACEDESC lpDDSurfaceDesc) = 0; virtual HRESULT GetDisplayMode(DDSURFACEDESC* lpDDSurfaceDesc) = 0;
virtual HRESULT RestoreDisplayMode() = 0; virtual HRESULT RestoreDisplayMode() = 0;
virtual HRESULT SetCooperativeLevel(HWND hWnd, DDSCLFlags dwFlags) = 0; virtual HRESULT SetCooperativeLevel(HWND hWnd, DDSCLFlags dwFlags) = 0;
virtual HRESULT SetDisplayMode(DWORD dwWidth, DWORD dwHeight, DWORD dwBPP) = 0; virtual HRESULT SetDisplayMode(DWORD dwWidth, DWORD dwHeight, DWORD dwBPP) = 0;

View File

@ -141,7 +141,6 @@ void OpenGL1Renderer::AddTextureDestroyCallback(Uint32 id, IDirect3DRMTexture* t
Uint32 OpenGL1Renderer::GetTextureId(IDirect3DRMTexture* iTexture) Uint32 OpenGL1Renderer::GetTextureId(IDirect3DRMTexture* iTexture)
{ {
auto texture = static_cast<Direct3DRMTextureImpl*>(iTexture); auto texture = static_cast<Direct3DRMTextureImpl*>(iTexture);
auto surface = static_cast<DirectDrawSurfaceImpl*>(texture->m_surface);
for (Uint32 i = 0; i < m_textures.size(); ++i) { for (Uint32 i = 0; i < m_textures.size(); ++i) {
auto& tex = m_textures[i]; auto& tex = m_textures[i];
@ -151,8 +150,7 @@ Uint32 OpenGL1Renderer::GetTextureId(IDirect3DRMTexture* iTexture)
glGenTextures(1, &tex.glTextureId); glGenTextures(1, &tex.glTextureId);
glBindTexture(GL_TEXTURE_2D, tex.glTextureId); glBindTexture(GL_TEXTURE_2D, tex.glTextureId);
SDL_Surface* surf = SDL_Surface* surf = SDL_ConvertSurface(texture->m_surface, SDL_PIXELFORMAT_ABGR8888);
SDL_ConvertSurface(surface->m_surface, SDL_PIXELFORMAT_ABGR8888); // Why are the colors backwarsd?
if (!surf) { if (!surf) {
return NO_TEXTURE_ID; return NO_TEXTURE_ID;
} }
@ -171,8 +169,7 @@ Uint32 OpenGL1Renderer::GetTextureId(IDirect3DRMTexture* iTexture)
glGenTextures(1, &texId); glGenTextures(1, &texId);
glBindTexture(GL_TEXTURE_2D, texId); glBindTexture(GL_TEXTURE_2D, texId);
SDL_Surface* surf = SDL_Surface* surf = SDL_ConvertSurface(texture->m_surface, SDL_PIXELFORMAT_ABGR8888);
SDL_ConvertSurface(surface->m_surface, SDL_PIXELFORMAT_ABGR8888); // Why are the colors backwarsd?
if (!surf) { if (!surf) {
return NO_TEXTURE_ID; return NO_TEXTURE_ID;
} }
@ -356,7 +353,7 @@ const char* OpenGL1Renderer::GetName()
HRESULT OpenGL1Renderer::BeginFrame(const D3DRMMATRIX4D& viewMatrix) HRESULT OpenGL1Renderer::BeginFrame(const D3DRMMATRIX4D& viewMatrix)
{ {
if (!DDBackBuffer) { if (!DDFrameBuffer) {
return DDERR_GENERIC; return DDERR_GENERIC;
} }
@ -538,11 +535,10 @@ void OpenGL1Renderer::SubmitDraw(
HRESULT OpenGL1Renderer::FinalizeFrame() HRESULT OpenGL1Renderer::FinalizeFrame()
{ {
glDepthMask(GL_TRUE); glDepthMask(GL_TRUE);
glReadPixels(0, 0, m_width, m_height, GL_RGBA, GL_UNSIGNED_BYTE, m_renderedImage->pixels); glReadPixels(0, 0, m_width, m_height, GL_BGRA, GL_UNSIGNED_BYTE, m_renderedImage->pixels);
glBindFramebuffer(GL_FRAMEBUFFER, 0); glBindFramebuffer(GL_FRAMEBUFFER, 0);
// Composite onto SDL backbuffer DDFrameBuffer->Upload(m_renderedImage->pixels, m_renderedImage->pitch);
SDL_BlitSurface(m_renderedImage, nullptr, DDBackBuffer, nullptr);
return DD_OK; return DD_OK;
} }

View File

@ -141,7 +141,7 @@ static SDL_GPUGraphicsPipeline* InitializeGraphicsPipeline(SDL_GPUDevice* device
vertexInputState.num_vertex_attributes = SDL_arraysize(vertexAttrs); vertexInputState.num_vertex_attributes = SDL_arraysize(vertexAttrs);
SDL_GPUColorTargetDescription colorTargets = {}; SDL_GPUColorTargetDescription colorTargets = {};
colorTargets.format = SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM; colorTargets.format = SDL_GPU_TEXTUREFORMAT_B8G8R8A8_UNORM;
if (depthWrite) { if (depthWrite) {
colorTargets.blend_state.enable_blend = false; colorTargets.blend_state.enable_blend = false;
} }
@ -209,7 +209,7 @@ Direct3DRMRenderer* Direct3DRMSDL3GPURenderer::Create(DWORD width, DWORD height)
SDL_GPUTextureCreateInfo textureInfo = {}; SDL_GPUTextureCreateInfo textureInfo = {};
textureInfo.type = SDL_GPU_TEXTURETYPE_2D; textureInfo.type = SDL_GPU_TEXTURETYPE_2D;
textureInfo.format = SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM; textureInfo.format = SDL_GPU_TEXTUREFORMAT_B8G8R8A8_UNORM;
textureInfo.usage = SDL_GPU_TEXTUREUSAGE_COLOR_TARGET; textureInfo.usage = SDL_GPU_TEXTUREUSAGE_COLOR_TARGET;
textureInfo.width = width; textureInfo.width = width;
textureInfo.height = height; textureInfo.height = height;
@ -310,7 +310,7 @@ Direct3DRMSDL3GPURenderer::Direct3DRMSDL3GPURenderer(
m_transparentPipeline(transparentPipeline), m_transferTexture(transferTexture), m_depthTexture(depthTexture), m_transparentPipeline(transparentPipeline), m_transferTexture(transferTexture), m_depthTexture(depthTexture),
m_sampler(sampler), m_uploadBuffer(uploadBuffer), m_downloadBuffer(downloadBuffer) m_sampler(sampler), m_uploadBuffer(uploadBuffer), m_downloadBuffer(downloadBuffer)
{ {
SDL_Surface* dummySurface = SDL_CreateSurface(1, 1, SDL_PIXELFORMAT_ABGR8888); SDL_Surface* dummySurface = SDL_CreateSurface(1, 1, SDL_PIXELFORMAT_ARGB8888);
if (!dummySurface) { if (!dummySurface) {
SDL_LogError(LOG_CATEGORY_MINIWIN, "Failed to create surface: %s", SDL_GetError()); SDL_LogError(LOG_CATEGORY_MINIWIN, "Failed to create surface: %s", SDL_GetError());
return; return;
@ -400,7 +400,7 @@ void Direct3DRMSDL3GPURenderer::AddTextureDestroyCallback(Uint32 id, IDirect3DRM
SDL_GPUTexture* Direct3DRMSDL3GPURenderer::CreateTextureFromSurface(SDL_Surface* surface) SDL_GPUTexture* Direct3DRMSDL3GPURenderer::CreateTextureFromSurface(SDL_Surface* surface)
{ {
ScopedSurface surf{SDL_ConvertSurface(surface, SDL_PIXELFORMAT_ABGR8888)}; ScopedSurface surf{SDL_ConvertSurface(surface, SDL_PIXELFORMAT_ARGB8888)};
if (!surf.ptr) { if (!surf.ptr) {
SDL_LogError(LOG_CATEGORY_MINIWIN, "SDL_ConvertSurface (%s)", SDL_GetError()); SDL_LogError(LOG_CATEGORY_MINIWIN, "SDL_ConvertSurface (%s)", SDL_GetError());
return nullptr; return nullptr;
@ -410,7 +410,7 @@ SDL_GPUTexture* Direct3DRMSDL3GPURenderer::CreateTextureFromSurface(SDL_Surface*
SDL_GPUTextureCreateInfo textureInfo = {}; SDL_GPUTextureCreateInfo textureInfo = {};
textureInfo.type = SDL_GPU_TEXTURETYPE_2D; textureInfo.type = SDL_GPU_TEXTURETYPE_2D;
textureInfo.format = SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM; textureInfo.format = SDL_GPU_TEXTUREFORMAT_B8G8R8A8_UNORM;
textureInfo.usage = SDL_GPU_TEXTUREUSAGE_SAMPLER; textureInfo.usage = SDL_GPU_TEXTUREUSAGE_SAMPLER;
textureInfo.width = surf.ptr->w; textureInfo.width = surf.ptr->w;
textureInfo.height = surf.ptr->h; textureInfo.height = surf.ptr->h;
@ -464,15 +464,13 @@ SDL_GPUTexture* Direct3DRMSDL3GPURenderer::CreateTextureFromSurface(SDL_Surface*
Uint32 Direct3DRMSDL3GPURenderer::GetTextureId(IDirect3DRMTexture* iTexture) Uint32 Direct3DRMSDL3GPURenderer::GetTextureId(IDirect3DRMTexture* iTexture)
{ {
auto texture = static_cast<Direct3DRMTextureImpl*>(iTexture); auto texture = static_cast<Direct3DRMTextureImpl*>(iTexture);
auto surface = static_cast<DirectDrawSurfaceImpl*>(texture->m_surface);
SDL_Surface* surf = surface->m_surface;
for (Uint32 i = 0; i < m_textures.size(); ++i) { for (Uint32 i = 0; i < m_textures.size(); ++i) {
auto& tex = m_textures[i]; auto& tex = m_textures[i];
if (tex.texture == texture) { if (tex.texture == texture) {
if (tex.version != texture->m_version) { if (tex.version != texture->m_version) {
SDL_ReleaseGPUTexture(m_device, tex.gpuTexture); SDL_ReleaseGPUTexture(m_device, tex.gpuTexture);
tex.gpuTexture = CreateTextureFromSurface(surf); tex.gpuTexture = CreateTextureFromSurface(texture->m_surface);
if (!tex.gpuTexture) { if (!tex.gpuTexture) {
return NO_TEXTURE_ID; return NO_TEXTURE_ID;
} }
@ -482,7 +480,7 @@ Uint32 Direct3DRMSDL3GPURenderer::GetTextureId(IDirect3DRMTexture* iTexture)
} }
} }
SDL_GPUTexture* newTex = CreateTextureFromSurface(surf); SDL_GPUTexture* newTex = CreateTextureFromSurface(texture->m_surface);
if (!newTex) { if (!newTex) {
return NO_TEXTURE_ID; return NO_TEXTURE_ID;
} }
@ -705,7 +703,7 @@ SDL_GPUTransferBuffer* Direct3DRMSDL3GPURenderer::GetUploadBuffer(size_t size)
HRESULT Direct3DRMSDL3GPURenderer::BeginFrame(const D3DRMMATRIX4D& viewMatrix) HRESULT Direct3DRMSDL3GPURenderer::BeginFrame(const D3DRMMATRIX4D& viewMatrix)
{ {
if (!DDBackBuffer) { if (!DDFrameBuffer) {
return DDERR_GENERIC; return DDERR_GENERIC;
} }
@ -807,10 +805,7 @@ HRESULT Direct3DRMSDL3GPURenderer::FinalizeFrame()
return DDERR_GENERIC; return DDERR_GENERIC;
} }
SDL_Surface* renderedImage = DDFrameBuffer->Upload(downloadedData, m_width * 4);
SDL_CreateSurfaceFrom(m_width, m_height, SDL_PIXELFORMAT_ABGR8888, downloadedData, m_width * 4);
SDL_BlitSurface(renderedImage, nullptr, DDBackBuffer, nullptr);
SDL_DestroySurface(renderedImage);
SDL_UnmapGPUTransferBuffer(m_device, m_downloadBuffer); SDL_UnmapGPUTransferBuffer(m_device, m_downloadBuffer);
return DD_OK; return DD_OK;

View File

@ -25,6 +25,7 @@
Direct3DRMSoftwareRenderer::Direct3DRMSoftwareRenderer(DWORD width, DWORD height) : m_width(width), m_height(height) Direct3DRMSoftwareRenderer::Direct3DRMSoftwareRenderer(DWORD width, DWORD height) : m_width(width), m_height(height)
{ {
m_renderedImage = SDL_CreateSurface(m_width, m_height, SDL_PIXELFORMAT_ABGR8888);
m_zBuffer.resize(m_width * m_height); m_zBuffer.resize(m_width * m_height);
} }
@ -174,21 +175,8 @@ void Direct3DRMSoftwareRenderer::DrawTriangleClipped(const D3DRMVERTEX (&v)[3],
Uint32 Direct3DRMSoftwareRenderer::BlendPixel(Uint8* pixelAddr, Uint8 r, Uint8 g, Uint8 b, Uint8 a) Uint32 Direct3DRMSoftwareRenderer::BlendPixel(Uint8* pixelAddr, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
{ {
Uint32 dstPixel;
switch (m_bytesPerPixel) {
case 1:
dstPixel = *pixelAddr;
break;
case 2:
dstPixel = *(Uint16*) pixelAddr;
break;
case 4:
dstPixel = *(Uint32*) pixelAddr;
break;
}
Uint8 dstR, dstG, dstB, dstA; Uint8 dstR, dstG, dstB, dstA;
SDL_GetRGBA(dstPixel, m_format, m_palette, &dstR, &dstG, &dstB, &dstA); SDL_GetRGBA(*(Uint32*) pixelAddr, m_format, m_palette, &dstR, &dstG, &dstB, &dstA);
float alpha = a / 255.0f; float alpha = a / 255.0f;
float invAlpha = 1.0f - alpha; float invAlpha = 1.0f - alpha;
@ -342,8 +330,8 @@ void Direct3DRMSoftwareRenderer::DrawTriangleProjected(
} }
} }
Uint8* pixels = (Uint8*) DDBackBuffer->pixels; Uint8* pixels = (Uint8*) m_renderedImage->pixels;
int pitch = DDBackBuffer->pitch; int pitch = m_renderedImage->pitch;
VertexXY verts[3] = { VertexXY verts[3] = {
{p0.x, p0.y, p0.z, p0.w, c0, v0.texCoord.u, v0.texCoord.v}, {p0.x, p0.y, p0.z, p0.w, c0, v0.texCoord.u, v0.texCoord.v},
@ -446,22 +434,8 @@ void Direct3DRMSoftwareRenderer::DrawTriangleProjected(
int texY = static_cast<int>(v * texHeightScale); int texY = static_cast<int>(v * texHeightScale);
Uint8* texelAddr = texels + texY * texturePitch + texX * m_bytesPerPixel; Uint8* texelAddr = texels + texY * texturePitch + texX * m_bytesPerPixel;
Uint32 texelColor;
switch (m_bytesPerPixel) {
case 1:
texelColor = *texelAddr;
break;
case 2:
texelColor = *(Uint16*) texelAddr;
break;
case 4:
texelColor = *(Uint32*) texelAddr;
break;
}
Uint8 tr, tg, tb, ta; Uint8 tr, tg, tb, ta;
SDL_GetRGBA(texelColor, m_format, m_palette, &tr, &tg, &tb, &ta); SDL_GetRGBA(*(Uint32*) texelAddr, m_format, m_palette, &tr, &tg, &tb, &ta);
// Multiply vertex color by texel color // Multiply vertex color by texel color
r = (r * tr + 127) / 255; r = (r * tr + 127) / 255;
@ -475,17 +449,7 @@ void Direct3DRMSoftwareRenderer::DrawTriangleProjected(
finalColor = BlendPixel(pixelAddr, r, g, b, appearance.color.a); finalColor = BlendPixel(pixelAddr, r, g, b, appearance.color.a);
} }
switch (m_bytesPerPixel) {
case 1:
*pixelAddr = static_cast<Uint8>(finalColor);
break;
case 2:
*reinterpret_cast<Uint16*>(pixelAddr) = static_cast<Uint16>(finalColor);
break;
case 4:
*reinterpret_cast<Uint32*>(pixelAddr) = finalColor; *reinterpret_cast<Uint32*>(pixelAddr) = finalColor;
break;
}
} }
} }
} }
@ -517,7 +481,6 @@ void Direct3DRMSoftwareRenderer::AddTextureDestroyCallback(Uint32 id, IDirect3DR
Uint32 Direct3DRMSoftwareRenderer::GetTextureId(IDirect3DRMTexture* iTexture) Uint32 Direct3DRMSoftwareRenderer::GetTextureId(IDirect3DRMTexture* iTexture)
{ {
auto texture = static_cast<Direct3DRMTextureImpl*>(iTexture); auto texture = static_cast<Direct3DRMTextureImpl*>(iTexture);
auto surface = static_cast<DirectDrawSurfaceImpl*>(texture->m_surface);
// Check if already mapped // Check if already mapped
for (Uint32 i = 0; i < m_textures.size(); ++i) { for (Uint32 i = 0; i < m_textures.size(); ++i) {
@ -526,7 +489,7 @@ Uint32 Direct3DRMSoftwareRenderer::GetTextureId(IDirect3DRMTexture* iTexture)
if (texRef.version != texture->m_version) { if (texRef.version != texture->m_version) {
// Update animated textures // Update animated textures
SDL_DestroySurface(texRef.cached); SDL_DestroySurface(texRef.cached);
texRef.cached = SDL_ConvertSurface(surface->m_surface, DDBackBuffer->format); texRef.cached = SDL_ConvertSurface(texture->m_surface, HWBackBufferFormat);
SDL_LockSurface(texRef.cached); SDL_LockSurface(texRef.cached);
texRef.version = texture->m_version; texRef.version = texture->m_version;
} }
@ -534,7 +497,7 @@ Uint32 Direct3DRMSoftwareRenderer::GetTextureId(IDirect3DRMTexture* iTexture)
} }
} }
SDL_Surface* convertedRender = SDL_ConvertSurface(surface->m_surface, DDBackBuffer->format); SDL_Surface* convertedRender = SDL_ConvertSurface(texture->m_surface, HWBackBufferFormat);
SDL_LockSurface(convertedRender); SDL_LockSurface(convertedRender);
// Reuse freed slot // Reuse freed slot
@ -655,14 +618,12 @@ const char* Direct3DRMSoftwareRenderer::GetName()
HRESULT Direct3DRMSoftwareRenderer::BeginFrame(const D3DRMMATRIX4D& viewMatrix) HRESULT Direct3DRMSoftwareRenderer::BeginFrame(const D3DRMMATRIX4D& viewMatrix)
{ {
if (!DDBackBuffer || !SDL_LockSurface(DDBackBuffer)) {
return DDERR_GENERIC;
}
ClearZBuffer(); ClearZBuffer();
Uint32 color = SDL_MapRGBA(SDL_GetPixelFormatDetails(m_renderedImage->format), nullptr, 0, 0, 0, 0);
SDL_FillSurfaceRect(m_renderedImage, nullptr, color);
memcpy(m_viewMatrix, viewMatrix, sizeof(D3DRMMATRIX4D)); memcpy(m_viewMatrix, viewMatrix, sizeof(D3DRMMATRIX4D));
m_format = SDL_GetPixelFormatDetails(DDBackBuffer->format); m_format = SDL_GetPixelFormatDetails(HWBackBufferFormat);
m_palette = SDL_GetSurfacePalette(DDBackBuffer);
m_bytesPerPixel = m_format->bits_per_pixel / 8; m_bytesPerPixel = m_format->bits_per_pixel / 8;
return DD_OK; return DD_OK;
@ -708,7 +669,7 @@ void Direct3DRMSoftwareRenderer::SubmitDraw(
HRESULT Direct3DRMSoftwareRenderer::FinalizeFrame() HRESULT Direct3DRMSoftwareRenderer::FinalizeFrame()
{ {
SDL_UnlockSurface(DDBackBuffer); DDFrameBuffer->Upload(m_renderedImage->pixels, m_renderedImage->pitch);
return DD_OK; return DD_OK;
} }

View File

@ -160,14 +160,18 @@ HRESULT Direct3DRMImpl::CreateDeviceFromSurface(
HRESULT Direct3DRMImpl::CreateTexture(D3DRMIMAGE* image, IDirect3DRMTexture2** outTexture) HRESULT Direct3DRMImpl::CreateTexture(D3DRMIMAGE* image, IDirect3DRMTexture2** outTexture)
{ {
*outTexture = static_cast<IDirect3DRMTexture2*>(new Direct3DRMTextureImpl(image)); MINIWIN_NOT_IMPLEMENTED();
return DD_OK; return DD_OK;
} }
HRESULT Direct3DRMImpl::CreateTextureFromSurface(LPDIRECTDRAWSURFACE surface, IDirect3DRMTexture2** outTexture) HRESULT Direct3DRMImpl::CreateTextureFromSurface(IDirectDrawSurface* surface, IDirect3DRMTexture2** outTexture)
{ {
*outTexture = static_cast<IDirect3DRMTexture2*>(new Direct3DRMTextureImpl(surface)); *outTexture = dynamic_cast<IDirect3DRMTexture2*>(surface);
if (!*outTexture) {
return DDERR_GENERIC;
}
surface->AddRef();
return DD_OK; return DD_OK;
} }

View File

@ -1,13 +1,18 @@
#include "d3drmtexture_impl.h" #include "d3drmtexture_impl.h"
#include "ddpalette_impl.h"
#include "miniwin.h" #include "miniwin.h"
Direct3DRMTextureImpl::Direct3DRMTextureImpl(D3DRMIMAGE* image) Direct3DRMTextureImpl::Direct3DRMTextureImpl(int width, int height, SDL_PixelFormat format)
{ {
MINIWIN_NOT_IMPLEMENTED(); m_surface = SDL_CreateSurface(width, height, format);
if (!m_surface) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to create surface: %s", SDL_GetError());
}
} }
Direct3DRMTextureImpl::Direct3DRMTextureImpl(IDirectDrawSurface* surface) : m_surface(surface) Direct3DRMTextureImpl::~Direct3DRMTextureImpl()
{ {
SDL_DestroySurface(m_surface);
} }
HRESULT Direct3DRMTextureImpl::QueryInterface(const GUID& riid, void** ppvObject) HRESULT Direct3DRMTextureImpl::QueryInterface(const GUID& riid, void** ppvObject)
@ -23,9 +28,169 @@ HRESULT Direct3DRMTextureImpl::QueryInterface(const GUID& riid, void** ppvObject
HRESULT Direct3DRMTextureImpl::Changed(BOOL pixels, BOOL palette) HRESULT Direct3DRMTextureImpl::Changed(BOOL pixels, BOOL palette)
{ {
if (!m_surface) {
return DDERR_GENERIC;
}
m_version++; m_version++;
return DD_OK; return DD_OK;
} }
// IDirectDrawSurface interface
HRESULT Direct3DRMTextureImpl::AddAttachedSurface(IDirectDrawSurface* lpDDSAttachedSurface)
{
MINIWIN_NOT_IMPLEMENTED();
return DDERR_GENERIC;
}
HRESULT Direct3DRMTextureImpl::Blt(
LPRECT lpDestRect,
IDirectDrawSurface* lpDDSrcSurface,
LPRECT lpSrcRect,
DDBltFlags dwFlags,
LPDDBLTFX lpDDBltFx
)
{
MINIWIN_NOT_IMPLEMENTED();
return DDERR_GENERIC;
}
HRESULT Direct3DRMTextureImpl::BltFast(
DWORD dwX,
DWORD dwY,
IDirectDrawSurface* lpDDSrcSurface,
LPRECT lpSrcRect,
DDBltFastFlags dwTrans
)
{
if (dwX != 0 || dwY != 0) {
MINIWIN_NOT_IMPLEMENTED();
return DDERR_GENERIC;
}
auto* other = dynamic_cast<Direct3DRMTextureImpl*>(lpDDSrcSurface);
if (!other) {
MINIWIN_NOT_IMPLEMENTED();
return DDERR_GENERIC;
}
if (other->m_surface->format != m_surface->format) {
MINIWIN_NOT_IMPLEMENTED();
return DDERR_GENERIC;
}
SDL_BlitSurface(other->m_surface, nullptr, m_surface, nullptr);
return DD_OK;
}
HRESULT Direct3DRMTextureImpl::Flip(IDirectDrawSurface* lpDDSurfaceTarget, DDFlipFlags dwFlags)
{
MINIWIN_NOT_IMPLEMENTED();
return DDERR_GENERIC;
}
HRESULT Direct3DRMTextureImpl::GetAttachedSurface(LPDDSCAPS lpDDSCaps, IDirectDrawSurface** lplpDDAttachedSurface)
{
MINIWIN_NOT_IMPLEMENTED();
return DDERR_GENERIC;
}
HRESULT Direct3DRMTextureImpl::GetDC(HDC* lphDC)
{
MINIWIN_NOT_IMPLEMENTED();
return DDERR_GENERIC;
}
HRESULT Direct3DRMTextureImpl::GetPalette(LPDIRECTDRAWPALETTE* lplpDDPalette)
{
MINIWIN_NOT_IMPLEMENTED();
return DDERR_GENERIC;
}
HRESULT Direct3DRMTextureImpl::GetPixelFormat(LPDDPIXELFORMAT lpDDPixelFormat)
{
lpDDPixelFormat->dwFlags = DDPF_RGB;
const SDL_PixelFormatDetails* details = SDL_GetPixelFormatDetails(m_surface->format);
if (details->bits_per_pixel == 8) {
lpDDPixelFormat->dwFlags |= DDPF_PALETTEINDEXED8;
}
lpDDPixelFormat->dwRGBBitCount = details->bits_per_pixel;
lpDDPixelFormat->dwRBitMask = details->Rmask;
lpDDPixelFormat->dwGBitMask = details->Gmask;
lpDDPixelFormat->dwBBitMask = details->Bmask;
lpDDPixelFormat->dwRGBAlphaBitMask = details->Amask;
return DD_OK;
}
HRESULT Direct3DRMTextureImpl::GetSurfaceDesc(DDSURFACEDESC* lpDDSurfaceDesc)
{
lpDDSurfaceDesc->dwFlags = DDSD_PIXELFORMAT;
GetPixelFormat(&lpDDSurfaceDesc->ddpfPixelFormat);
lpDDSurfaceDesc->dwFlags |= DDSD_WIDTH | DDSD_HEIGHT;
lpDDSurfaceDesc->dwWidth = m_surface->w;
lpDDSurfaceDesc->dwHeight = m_surface->h;
return DD_OK;
}
HRESULT Direct3DRMTextureImpl::IsLost()
{
MINIWIN_NOT_IMPLEMENTED();
return DDERR_GENERIC;
}
HRESULT Direct3DRMTextureImpl::Lock(
LPRECT lpDestRect,
DDSURFACEDESC* lpDDSurfaceDesc,
DDLockFlags dwFlags,
HANDLE hEvent
)
{
if (!SDL_LockSurface(m_surface)) {
return DDERR_GENERIC;
}
GetSurfaceDesc(lpDDSurfaceDesc);
lpDDSurfaceDesc->lpSurface = m_surface->pixels;
lpDDSurfaceDesc->lPitch = m_surface->pitch;
return DD_OK;
}
HRESULT Direct3DRMTextureImpl::ReleaseDC(HDC hDC)
{
MINIWIN_NOT_IMPLEMENTED();
return DDERR_GENERIC;
}
HRESULT Direct3DRMTextureImpl::Restore()
{
MINIWIN_NOT_IMPLEMENTED();
return DDERR_GENERIC;
}
HRESULT Direct3DRMTextureImpl::SetClipper(IDirectDrawClipper* lpDDClipper)
{
MINIWIN_NOT_IMPLEMENTED();
return DDERR_GENERIC;
}
HRESULT Direct3DRMTextureImpl::SetColorKey(DDColorKeyFlags dwFlags, LPDDCOLORKEY lpDDColorKey)
{
MINIWIN_NOT_IMPLEMENTED();
return DDERR_GENERIC;
}
HRESULT Direct3DRMTextureImpl::SetPalette(LPDIRECTDRAWPALETTE lpDDPalette)
{
if (m_surface->format != SDL_PIXELFORMAT_INDEX8) {
MINIWIN_NOT_IMPLEMENTED();
}
if (m_palette) {
m_palette->Release();
}
m_palette = lpDDPalette;
SDL_SetSurfacePalette(m_surface, ((DirectDrawPaletteImpl*) m_palette)->m_palette);
m_palette->AddRef();
return DD_OK;
}
HRESULT Direct3DRMTextureImpl::Unlock(LPVOID lpSurfaceData)
{
SDL_UnlockSurface(m_surface);
return DD_OK;
}

View File

@ -358,16 +358,15 @@ HRESULT Direct3DRMViewportImpl::ForceUpdate(int x, int y, int w, int h)
HRESULT Direct3DRMViewportImpl::Clear() HRESULT Direct3DRMViewportImpl::Clear()
{ {
if (!DDBackBuffer) { if (!DDRenderer) {
return DDERR_GENERIC; return DDERR_GENERIC;
} }
uint8_t r = (m_backgroundColor >> 16) & 0xFF; uint8_t r = (m_backgroundColor >> 16) & 0xFF;
uint8_t g = (m_backgroundColor >> 8) & 0xFF; uint8_t g = (m_backgroundColor >> 8) & 0xFF;
uint8_t b = m_backgroundColor & 0xFF; uint8_t b = m_backgroundColor & 0xFF;
SDL_SetRenderDrawColor(DDRenderer, r, g, b, 255);
Uint32 color = SDL_MapRGB(SDL_GetPixelFormatDetails(DDBackBuffer->format), nullptr, r, g, b); SDL_RenderClear(DDRenderer);
SDL_FillSurfaceRect(DDBackBuffer, nullptr, color);
return DD_OK; return DD_OK;
} }

View File

@ -6,6 +6,7 @@
#include "ddpalette_impl.h" #include "ddpalette_impl.h"
#include "ddraw_impl.h" #include "ddraw_impl.h"
#include "ddsurface_impl.h" #include "ddsurface_impl.h"
#include "dummysurface_impl.h"
#include "miniwin.h" #include "miniwin.h"
#include "miniwin/d3d.h" #include "miniwin/d3d.h"
@ -16,8 +17,7 @@
#include <cstring> #include <cstring>
SDL_Window* DDWindow; SDL_Window* DDWindow;
SDL_Surface* DDBackBuffer; FrameBufferImpl* DDFrameBuffer;
SDL_Texture* HWBackBuffer;
SDL_PixelFormat HWBackBufferFormat; SDL_PixelFormat HWBackBufferFormat;
SDL_Renderer* DDRenderer; SDL_Renderer* DDRenderer;
@ -38,7 +38,7 @@ HRESULT DirectDrawImpl::QueryInterface(const GUID& riid, void** ppvObject)
} }
// IDirectDraw interface // IDirectDraw interface
HRESULT DirectDrawImpl::CreateClipper(DWORD dwFlags, LPDIRECTDRAWCLIPPER* lplpDDClipper, IUnknown* pUnkOuter) HRESULT DirectDrawImpl::CreateClipper(DWORD dwFlags, IDirectDrawClipper** lplpDDClipper, IUnknown* pUnkOuter)
{ {
*lplpDDClipper = new IDirectDrawClipper; *lplpDDClipper = new IDirectDrawClipper;
@ -61,17 +61,37 @@ HRESULT DirectDrawImpl::CreatePalette(
} }
HRESULT DirectDrawImpl::CreateSurface( HRESULT DirectDrawImpl::CreateSurface(
LPDDSURFACEDESC lpDDSurfaceDesc, DDSURFACEDESC* lpDDSurfaceDesc,
LPDIRECTDRAWSURFACE* lplpDDSurface, IDirectDrawSurface** lplpDDSurface,
IUnknown* pUnkOuter IUnknown* pUnkOuter
) )
{ {
SDL_PixelFormat format; bool isTexture = false;
#ifdef MINIWIN_PIXELFORMAT if ((lpDDSurfaceDesc->dwFlags & DDSD_CAPS) == DDSD_CAPS) {
format = MINIWIN_PIXELFORMAT; if ((lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_ZBUFFER) == DDSCAPS_ZBUFFER) {
#else if ((lpDDSurfaceDesc->dwFlags & DDSD_ZBUFFERBITDEPTH) != DDSD_ZBUFFERBITDEPTH) {
format = SDL_PIXELFORMAT_RGBA8888; return DDERR_INVALIDPARAMS;
#endif }
SDL_Log("Todo: Set %dbit Z-Buffer", lpDDSurfaceDesc->dwZBufferBitDepth);
*lplpDDSurface = static_cast<IDirectDrawSurface*>(new DummySurfaceImpl);
return DD_OK;
}
if ((lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) == DDSCAPS_PRIMARYSURFACE) {
DDFrameBuffer = new FrameBufferImpl();
*lplpDDSurface = static_cast<IDirectDrawSurface*>(DDFrameBuffer);
return DD_OK;
}
if ((lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_3DDEVICE) == DDSCAPS_3DDEVICE) {
DDFrameBuffer->AddRef();
*lplpDDSurface = static_cast<IDirectDrawSurface*>(DDFrameBuffer);
return DD_OK;
}
if ((lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_TEXTURE) == DDSCAPS_TEXTURE) {
isTexture = true;
}
}
SDL_PixelFormat format = HWBackBufferFormat;
if ((lpDDSurfaceDesc->dwFlags & DDSD_PIXELFORMAT) == DDSD_PIXELFORMAT) { if ((lpDDSurfaceDesc->dwFlags & DDSD_PIXELFORMAT) == DDSD_PIXELFORMAT) {
if ((lpDDSurfaceDesc->ddpfPixelFormat.dwFlags & DDPF_RGB) == DDPF_RGB) { if ((lpDDSurfaceDesc->ddpfPixelFormat.dwFlags & DDPF_RGB) == DDPF_RGB) {
switch (lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount) { switch (lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount) {
@ -84,44 +104,6 @@ HRESULT DirectDrawImpl::CreateSurface(
} }
} }
} }
if ((lpDDSurfaceDesc->dwFlags & DDSD_CAPS) == DDSD_CAPS) {
if ((lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_ZBUFFER) == DDSCAPS_ZBUFFER) {
if ((lpDDSurfaceDesc->dwFlags & DDSD_ZBUFFERBITDEPTH) != DDSD_ZBUFFERBITDEPTH) {
return DDERR_INVALIDPARAMS;
}
SDL_Log("Todo: Set %dbit Z-Buffer", lpDDSurfaceDesc->dwZBufferBitDepth);
*lplpDDSurface = static_cast<IDirectDrawSurface*>(new DirectDrawSurfaceImpl);
return DD_OK;
}
if ((lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) == DDSCAPS_PRIMARYSURFACE) {
SDL_Surface* windowSurface = SDL_GetWindowSurface(DDWindow);
if (!windowSurface) {
return DDERR_GENERIC;
}
int width, height;
SDL_GetWindowSize(DDWindow, &width, &height);
bool implicitFlip = (lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_FLIP) != DDSCAPS_FLIP;
auto frontBuffer = new DirectDrawSurfaceImpl(width, height, windowSurface->format);
frontBuffer->SetAutoFlip(implicitFlip);
*lplpDDSurface = static_cast<IDirectDrawSurface*>(frontBuffer);
return DD_OK;
}
if ((lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_OFFSCREENPLAIN) == DDSCAPS_OFFSCREENPLAIN) {
MINIWIN_TRACE("DDSCAPS_OFFSCREENPLAIN"); // 2D surfaces?
}
if ((lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) == DDSCAPS_SYSTEMMEMORY) {
MINIWIN_TRACE("DDSCAPS_SYSTEMMEMORY"); // Software rendering?
}
if ((lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_TEXTURE) == DDSCAPS_TEXTURE) {
MINIWIN_TRACE("DDSCAPS_TEXTURE"); // Texture for use in 3D
}
if ((lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_3DDEVICE) == DDSCAPS_3DDEVICE) {
MINIWIN_TRACE("DDSCAPS_3DDEVICE"); // back buffer
}
if ((lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY) == DDSCAPS_VIDEOMEMORY) {
MINIWIN_TRACE("DDSCAPS_VIDEOMEMORY"); // front / back buffer
}
}
if ((lpDDSurfaceDesc->dwFlags & (DDSD_WIDTH | DDSD_HEIGHT)) != (DDSD_WIDTH | DDSD_HEIGHT)) { if ((lpDDSurfaceDesc->dwFlags & (DDSD_WIDTH | DDSD_HEIGHT)) != (DDSD_WIDTH | DDSD_HEIGHT)) {
return DDERR_INVALIDPARAMS; return DDERR_INVALIDPARAMS;
@ -132,13 +114,20 @@ HRESULT DirectDrawImpl::CreateSurface(
if (width == 0 || height == 0) { if (width == 0 || height == 0) {
return DDERR_INVALIDPARAMS; return DDERR_INVALIDPARAMS;
} }
if (isTexture) {
*lplpDDSurface = static_cast<IDirectDrawSurface*>(new Direct3DRMTextureImpl(width, height, format));
}
else {
*lplpDDSurface = static_cast<IDirectDrawSurface*>(new DirectDrawSurfaceImpl(width, height, format)); *lplpDDSurface = static_cast<IDirectDrawSurface*>(new DirectDrawSurfaceImpl(width, height, format));
}
return DD_OK; return DD_OK;
} }
HRESULT DirectDrawImpl::EnumDisplayModes( HRESULT DirectDrawImpl::EnumDisplayModes(
DWORD dwFlags, DWORD dwFlags,
LPDDSURFACEDESC lpDDSurfaceDesc, DDSURFACEDESC* lpDDSurfaceDesc,
LPVOID lpContext, LPVOID lpContext,
LPDDENUMMODESCALLBACK lpEnumModesCallback LPDDENUMMODESCALLBACK lpEnumModesCallback
) )
@ -158,11 +147,7 @@ HRESULT DirectDrawImpl::EnumDisplayModes(
HRESULT status = S_OK; HRESULT status = S_OK;
for (int i = 0; i < count_modes; i++) { for (int i = 0; i < count_modes; i++) {
#ifdef MINIWIN_PIXELFORMAT
format = MINIWIN_PIXELFORMAT;
#else
format = modes[i]->format; format = modes[i]->format;
#endif
const SDL_PixelFormatDetails* details = SDL_GetPixelFormatDetails(format); const SDL_PixelFormatDetails* details = SDL_GetPixelFormatDetails(format);
if (!details) { if (!details) {
@ -239,7 +224,7 @@ HRESULT DirectDrawImpl::EnumDevices(LPD3DENUMDEVICESCALLBACK cb, void* ctx)
return S_OK; return S_OK;
} }
HRESULT DirectDrawImpl::GetDisplayMode(LPDDSURFACEDESC lpDDSurfaceDesc) HRESULT DirectDrawImpl::GetDisplayMode(DDSURFACEDESC* lpDDSurfaceDesc)
{ {
SDL_DisplayID displayID = SDL_GetPrimaryDisplay(); SDL_DisplayID displayID = SDL_GetPrimaryDisplay();
if (!displayID) { if (!displayID) {
@ -251,14 +236,7 @@ HRESULT DirectDrawImpl::GetDisplayMode(LPDDSURFACEDESC lpDDSurfaceDesc)
return DDERR_GENERIC; return DDERR_GENERIC;
} }
SDL_PixelFormat format; const SDL_PixelFormatDetails* details = SDL_GetPixelFormatDetails(mode->format);
#ifdef MINIWIN_PIXELFORMAT
format = MINIWIN_PIXELFORMAT;
#else
format = mode->format;
#endif
const SDL_PixelFormatDetails* details = SDL_GetPixelFormatDetails(format);
lpDDSurfaceDesc->dwFlags = DDSD_WIDTH | DDSD_HEIGHT; lpDDSurfaceDesc->dwFlags = DDSD_WIDTH | DDSD_HEIGHT;
lpDDSurfaceDesc->dwWidth = mode->w; lpDDSurfaceDesc->dwWidth = mode->w;
@ -305,6 +283,10 @@ HRESULT DirectDrawImpl::SetCooperativeLevel(HWND hWnd, DDSCLFlags dwFlags)
} }
DDWindow = sdlWindow; DDWindow = sdlWindow;
DDRenderer = SDL_CreateRenderer(DDWindow, NULL); DDRenderer = SDL_CreateRenderer(DDWindow, NULL);
SDL_PropertiesID prop = SDL_GetRendererProperties(DDRenderer);
const SDL_PixelFormat* formats =
(SDL_PixelFormat*) SDL_GetPointerProperty(prop, SDL_PROP_RENDERER_TEXTURE_FORMATS_POINTER, NULL);
HWBackBufferFormat = formats[0];
SDL_SetRenderLogicalPresentation(DDRenderer, 640, 480, SDL_LOGICAL_PRESENTATION_LETTERBOX); SDL_SetRenderLogicalPresentation(DDRenderer, 640, 480, SDL_LOGICAL_PRESENTATION_LETTERBOX);
} }
return DD_OK; return DD_OK;

View File

@ -5,26 +5,17 @@
#include <assert.h> #include <assert.h>
DirectDrawSurfaceImpl::DirectDrawSurfaceImpl()
{
}
DirectDrawSurfaceImpl::DirectDrawSurfaceImpl(int width, int height, SDL_PixelFormat format) DirectDrawSurfaceImpl::DirectDrawSurfaceImpl(int width, int height, SDL_PixelFormat format)
{ {
m_surface = SDL_CreateSurface(width, height, format); m_texture = SDL_CreateTexture(DDRenderer, format, SDL_TEXTUREACCESS_STREAMING, width, height);
if (!m_surface) { if (!m_texture) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to create surface: %s", SDL_GetError()); SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to create texture: %s", SDL_GetError());
} }
} }
DirectDrawSurfaceImpl::~DirectDrawSurfaceImpl() DirectDrawSurfaceImpl::~DirectDrawSurfaceImpl()
{ {
if (m_surface) { SDL_DestroyTexture(m_texture);
SDL_DestroySurface(m_surface);
}
if (m_palette) {
m_palette->Release();
}
} }
// IUnknown interface // IUnknown interface
@ -40,120 +31,62 @@ HRESULT DirectDrawSurfaceImpl::QueryInterface(const GUID& riid, void** ppvObject
} }
// IDirectDrawSurface interface // IDirectDrawSurface interface
HRESULT DirectDrawSurfaceImpl::AddAttachedSurface(LPDIRECTDRAWSURFACE lpDDSAttachedSurface) HRESULT DirectDrawSurfaceImpl::AddAttachedSurface(IDirectDrawSurface* lpDDSAttachedSurface)
{ {
MINIWIN_NOT_IMPLEMENTED();
return DD_OK; return DD_OK;
} }
void DirectDrawSurfaceImpl::SetAutoFlip(bool enabled)
{
m_autoFlip = enabled;
}
static SDL_Rect ConvertRect(const RECT* r) static SDL_Rect ConvertRect(const RECT* r)
{ {
return {r->left, r->top, r->right - r->left, r->bottom - r->top}; return {r->left, r->top, (r->right - r->left), (r->bottom - r->top)};
}
bool SetupHWBackBuffer()
{
HWBackBuffer = SDL_CreateTextureFromSurface(DDRenderer, DDBackBuffer);
if (!HWBackBuffer) {
return false;
}
SDL_PropertiesID props = SDL_GetTextureProperties(HWBackBuffer);
if (!props) {
SDL_DestroyTexture(HWBackBuffer);
HWBackBuffer = nullptr;
return false;
}
HWBackBufferFormat =
(SDL_PixelFormat) SDL_GetNumberProperty(props, SDL_PROP_TEXTURE_FORMAT_NUMBER, SDL_PIXELFORMAT_UNKNOWN);
if (HWBackBufferFormat == SDL_PIXELFORMAT_UNKNOWN) {
SDL_DestroyTexture(HWBackBuffer);
HWBackBuffer = nullptr;
return false;
}
return true;
} }
HRESULT DirectDrawSurfaceImpl::Blt( HRESULT DirectDrawSurfaceImpl::Blt(
LPRECT lpDestRect, LPRECT lpDestRect,
LPDIRECTDRAWSURFACE lpDDSrcSurface, IDirectDrawSurface* lpDDSrcSurface,
LPRECT lpSrcRect, LPRECT lpSrcRect,
DDBltFlags dwFlags, DDBltFlags dwFlags,
LPDDBLTFX lpDDBltFx LPDDBLTFX lpDDBltFx
) )
{ {
if ((dwFlags & DDBLT_COLORFILL) == DDBLT_COLORFILL) { auto* other = dynamic_cast<DirectDrawSurfaceImpl*>(lpDDSrcSurface);
SDL_Rect rect = {0, 0, m_surface->w, m_surface->h}; if (!other) {
const SDL_PixelFormatDetails* details = SDL_GetPixelFormatDetails(m_surface->format); MINIWIN_NOT_IMPLEMENTED();
Uint8 r = (lpDDBltFx->dwFillColor >> 16) & 0xFF;
Uint8 g = (lpDDBltFx->dwFillColor >> 8) & 0xFF;
Uint8 b = lpDDBltFx->dwFillColor & 0xFF;
DirectDrawPaletteImpl* ddPal = static_cast<DirectDrawPaletteImpl*>(m_palette);
SDL_Palette* sdlPalette = ddPal ? ddPal->m_palette : nullptr;
Uint32 color = SDL_MapRGB(details, sdlPalette, r, g, b);
SDL_FillSurfaceRect(m_surface, &rect, color);
if (m_autoFlip) {
return Flip(nullptr, DDFLIP_WAIT);
}
return DD_OK;
}
auto srcSurface = static_cast<DirectDrawSurfaceImpl*>(lpDDSrcSurface);
if (!srcSurface || !srcSurface->m_surface) {
return DDERR_GENERIC; return DDERR_GENERIC;
} }
if (m_autoFlip) {
DDBackBuffer = srcSurface->m_surface;
if (!HWBackBuffer && !SetupHWBackBuffer()) {
return DDERR_GENERIC;
}
return Flip(nullptr, DDFLIP_WAIT);
}
SDL_Rect srcRect; SDL_Rect srcRect, dstRect;
if (lpSrcRect) { if (lpSrcRect) {
srcRect = ConvertRect(lpSrcRect); srcRect = ConvertRect(lpSrcRect);
} }
else {
srcRect = {0, 0, srcSurface->m_surface->w, srcSurface->m_surface->h};
}
SDL_Rect dstRect;
if (lpDestRect) { if (lpDestRect) {
dstRect = ConvertRect(lpDestRect); dstRect = ConvertRect(lpDestRect);
} }
else {
dstRect = {0, 0, m_surface->w, m_surface->h};
}
SDL_Surface* blitSource = srcSurface->m_surface; void* otherPixels;
int otherPitch;
if (srcSurface->m_surface->format != m_surface->format) { if (!SDL_LockTexture(other->m_texture, lpSrcRect ? &srcRect : nullptr, &otherPixels, &otherPitch)) {
blitSource = SDL_ConvertSurface(srcSurface->m_surface, m_surface->format); SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to lock other texture: %s", SDL_GetError());
if (!blitSource) {
return DDERR_GENERIC; return DDERR_GENERIC;
} }
} void* pixels;
int pitch;
if (!SDL_BlitSurfaceScaled(blitSource, &srcRect, m_surface, &dstRect, SDL_SCALEMODE_NEAREST)) { if (!SDL_LockTexture(m_texture, lpDestRect ? &dstRect : nullptr, &pixels, &pitch)) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to lock destination texture: %s", SDL_GetError());
return DDERR_GENERIC; return DDERR_GENERIC;
} }
memcpy(pixels, otherPixels, (lpDestRect ? dstRect.h : m_texture->h) * pitch);
SDL_UnlockTexture(other->m_texture);
SDL_UnlockTexture(m_texture);
if (blitSource != srcSurface->m_surface) {
SDL_DestroySurface(blitSource);
}
return DD_OK; return DD_OK;
} }
HRESULT DirectDrawSurfaceImpl::BltFast( HRESULT DirectDrawSurfaceImpl::BltFast(
DWORD dwX, DWORD dwX,
DWORD dwY, DWORD dwY,
LPDIRECTDRAWSURFACE lpDDSrcSurface, IDirectDrawSurface* lpDDSrcSurface,
LPRECT lpSrcRect, LPRECT lpSrcRect,
DDBltFastFlags dwTrans DDBltFastFlags dwTrans
) )
@ -167,30 +100,15 @@ HRESULT DirectDrawSurfaceImpl::BltFast(
return Blt(&destRect, lpDDSrcSurface, lpSrcRect, DDBLT_NONE, nullptr); return Blt(&destRect, lpDDSrcSurface, lpSrcRect, DDBLT_NONE, nullptr);
} }
HRESULT DirectDrawSurfaceImpl::Flip(LPDIRECTDRAWSURFACE lpDDSurfaceTargetOverride, DDFlipFlags dwFlags) HRESULT DirectDrawSurfaceImpl::Flip(IDirectDrawSurface* lpDDSurfaceTargetOverride, DDFlipFlags dwFlags)
{ {
if (!DDBackBuffer || !DDRenderer) { MINIWIN_NOT_IMPLEMENTED();
return DDERR_GENERIC;
}
SDL_Surface* copy = SDL_ConvertSurface(DDBackBuffer, HWBackBufferFormat);
SDL_UpdateTexture(HWBackBuffer, nullptr, copy->pixels, copy->pitch);
SDL_DestroySurface(copy);
SDL_RenderTexture(DDRenderer, HWBackBuffer, nullptr, nullptr);
SDL_RenderPresent(DDRenderer);
return DD_OK; return DD_OK;
} }
HRESULT DirectDrawSurfaceImpl::GetAttachedSurface(LPDDSCAPS lpDDSCaps, LPDIRECTDRAWSURFACE* lplpDDAttachedSurface) HRESULT DirectDrawSurfaceImpl::GetAttachedSurface(LPDDSCAPS lpDDSCaps, IDirectDrawSurface** lplpDDAttachedSurface)
{ {
if ((lpDDSCaps->dwCaps & DDSCAPS_BACKBUFFER) != DDSCAPS_BACKBUFFER) { MINIWIN_NOT_IMPLEMENTED();
return DDERR_INVALIDPARAMS;
}
DDBackBuffer = m_surface;
if (!SetupHWBackBuffer()) {
return DDERR_GENERIC;
}
*lplpDDAttachedSurface = static_cast<IDirectDrawSurface*>(this);
return DD_OK; return DD_OK;
} }
@ -202,22 +120,14 @@ HRESULT DirectDrawSurfaceImpl::GetDC(HDC* lphDC)
HRESULT DirectDrawSurfaceImpl::GetPalette(LPDIRECTDRAWPALETTE* lplpDDPalette) HRESULT DirectDrawSurfaceImpl::GetPalette(LPDIRECTDRAWPALETTE* lplpDDPalette)
{ {
if (!m_palette) { MINIWIN_NOT_IMPLEMENTED();
return DDERR_GENERIC;
}
m_palette->AddRef();
*lplpDDPalette = m_palette;
return DD_OK; return DD_OK;
} }
HRESULT DirectDrawSurfaceImpl::GetPixelFormat(LPDDPIXELFORMAT lpDDPixelFormat) HRESULT DirectDrawSurfaceImpl::GetPixelFormat(LPDDPIXELFORMAT lpDDPixelFormat)
{ {
if (!m_surface) {
return DDERR_GENERIC;
}
memset(lpDDPixelFormat, 0, sizeof(*lpDDPixelFormat));
lpDDPixelFormat->dwFlags = DDPF_RGB; lpDDPixelFormat->dwFlags = DDPF_RGB;
const SDL_PixelFormatDetails* details = SDL_GetPixelFormatDetails(m_surface->format); const SDL_PixelFormatDetails* details = SDL_GetPixelFormatDetails(HWBackBufferFormat);
if (details->bits_per_pixel == 8) { if (details->bits_per_pixel == 8) {
lpDDPixelFormat->dwFlags |= DDPF_PALETTEINDEXED8; lpDDPixelFormat->dwFlags |= DDPF_PALETTEINDEXED8;
} }
@ -229,18 +139,13 @@ HRESULT DirectDrawSurfaceImpl::GetPixelFormat(LPDDPIXELFORMAT lpDDPixelFormat)
return DD_OK; return DD_OK;
} }
HRESULT DirectDrawSurfaceImpl::GetSurfaceDesc(LPDDSURFACEDESC lpDDSurfaceDesc) HRESULT DirectDrawSurfaceImpl::GetSurfaceDesc(DDSURFACEDESC* lpDDSurfaceDesc)
{ {
if (!m_surface) {
return DDERR_GENERIC;
}
lpDDSurfaceDesc->dwFlags = DDSD_PIXELFORMAT; lpDDSurfaceDesc->dwFlags = DDSD_PIXELFORMAT;
GetPixelFormat(&lpDDSurfaceDesc->ddpfPixelFormat); GetPixelFormat(&lpDDSurfaceDesc->ddpfPixelFormat);
if (m_surface) {
lpDDSurfaceDesc->dwFlags |= DDSD_WIDTH | DDSD_HEIGHT; lpDDSurfaceDesc->dwFlags |= DDSD_WIDTH | DDSD_HEIGHT;
lpDDSurfaceDesc->dwWidth = m_surface->w; lpDDSurfaceDesc->dwWidth = m_texture->w;
lpDDSurfaceDesc->dwHeight = m_surface->h; lpDDSurfaceDesc->dwHeight = m_texture->h;
}
return DD_OK; return DD_OK;
} }
@ -251,23 +156,16 @@ HRESULT DirectDrawSurfaceImpl::IsLost()
HRESULT DirectDrawSurfaceImpl::Lock( HRESULT DirectDrawSurfaceImpl::Lock(
LPRECT lpDestRect, LPRECT lpDestRect,
LPDDSURFACEDESC lpDDSurfaceDesc, DDSURFACEDESC* lpDDSurfaceDesc,
DDLockFlags dwFlags, DDLockFlags dwFlags,
HANDLE hEvent HANDLE hEvent
) )
{ {
if (!m_surface) { if (!SDL_LockTexture(m_texture, nullptr, &lpDDSurfaceDesc->lpSurface, &lpDDSurfaceDesc->lPitch)) {
return DDERR_GENERIC;
}
if (!SDL_LockSurface(m_surface)) {
return DDERR_GENERIC; return DDERR_GENERIC;
} }
GetSurfaceDesc(lpDDSurfaceDesc); GetSurfaceDesc(lpDDSurfaceDesc);
lpDDSurfaceDesc->lpSurface = m_surface->pixels;
lpDDSurfaceDesc->lPitch = m_surface->pitch;
return DD_OK; return DD_OK;
} }
@ -279,48 +177,30 @@ HRESULT DirectDrawSurfaceImpl::ReleaseDC(HDC hDC)
HRESULT DirectDrawSurfaceImpl::Restore() HRESULT DirectDrawSurfaceImpl::Restore()
{ {
MINIWIN_NOT_IMPLEMENTED();
return DD_OK; return DD_OK;
} }
HRESULT DirectDrawSurfaceImpl::SetClipper(LPDIRECTDRAWCLIPPER lpDDClipper) HRESULT DirectDrawSurfaceImpl::SetClipper(IDirectDrawClipper* lpDDClipper)
{ {
MINIWIN_NOT_IMPLEMENTED();
return DD_OK; return DD_OK;
} }
HRESULT DirectDrawSurfaceImpl::SetColorKey(DDColorKeyFlags dwFlags, LPDDCOLORKEY lpDDColorKey) HRESULT DirectDrawSurfaceImpl::SetColorKey(DDColorKeyFlags dwFlags, LPDDCOLORKEY lpDDColorKey)
{ {
if (lpDDColorKey->dwColorSpaceLowValue != lpDDColorKey->dwColorSpaceHighValue) {
MINIWIN_NOT_IMPLEMENTED(); MINIWIN_NOT_IMPLEMENTED();
}
if (SDL_SetSurfaceColorKey(m_surface, true, lpDDColorKey->dwColorSpaceLowValue) != 0) {
return DDERR_GENERIC;
}
return DD_OK; return DD_OK;
} }
HRESULT DirectDrawSurfaceImpl::SetPalette(LPDIRECTDRAWPALETTE lpDDPalette) HRESULT DirectDrawSurfaceImpl::SetPalette(LPDIRECTDRAWPALETTE lpDDPalette)
{ {
if (m_surface->format != SDL_PIXELFORMAT_INDEX8) {
MINIWIN_NOT_IMPLEMENTED(); MINIWIN_NOT_IMPLEMENTED();
}
if (m_palette) {
m_palette->Release();
}
m_palette = lpDDPalette;
SDL_SetSurfacePalette(m_surface, ((DirectDrawPaletteImpl*) m_palette)->m_palette);
m_palette->AddRef();
return DD_OK; return DD_OK;
} }
HRESULT DirectDrawSurfaceImpl::Unlock(LPVOID lpSurfaceData) HRESULT DirectDrawSurfaceImpl::Unlock(LPVOID lpSurfaceData)
{ {
if (!m_surface) { SDL_UnlockTexture(m_texture);
return DDERR_GENERIC;
}
SDL_UnlockSurface(m_surface);
return DD_OK; return DD_OK;
} }

View File

@ -0,0 +1,226 @@
#include "ddpalette_impl.h"
#include "ddraw_impl.h"
#include "dummysurface_impl.h"
#include "framebuffer_impl.h"
#include "miniwin.h"
#include <assert.h>
FrameBufferImpl::FrameBufferImpl()
{
int width, height;
SDL_GetRenderOutputSize(DDRenderer, &width, &height);
m_backBuffer = SDL_CreateTexture(DDRenderer, HWBackBufferFormat, SDL_TEXTUREACCESS_TARGET, width, height);
m_uploadBuffer = SDL_CreateTexture(DDRenderer, HWBackBufferFormat, SDL_TEXTUREACCESS_STREAMING, width, height);
SDL_SetRenderTarget(DDRenderer, m_backBuffer);
if (!m_backBuffer) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to create surface: %s", SDL_GetError());
}
}
FrameBufferImpl::~FrameBufferImpl()
{
SDL_DestroyTexture(m_backBuffer);
}
// IUnknown interface
HRESULT FrameBufferImpl::QueryInterface(const GUID& riid, void** ppvObject)
{
MINIWIN_NOT_IMPLEMENTED();
return E_NOINTERFACE;
}
// IDirectDrawSurface interface
HRESULT FrameBufferImpl::AddAttachedSurface(IDirectDrawSurface* lpDDSAttachedSurface)
{
if (dynamic_cast<DummySurfaceImpl*>(lpDDSAttachedSurface)) {
return DD_OK;
}
MINIWIN_NOT_IMPLEMENTED();
return DDERR_GENERIC;
}
static SDL_FRect ConvertRect(const RECT* r)
{
return {(float) r->left, (float) r->top, (float) (r->right - r->left), (float) (r->bottom - r->top)};
}
HRESULT FrameBufferImpl::Blt(
LPRECT lpDestRect,
IDirectDrawSurface* lpDDSrcSurface,
LPRECT lpSrcRect,
DDBltFlags dwFlags,
LPDDBLTFX lpDDBltFx
)
{
if (dynamic_cast<FrameBufferImpl*>(lpDDSrcSurface) == this) {
return Flip(nullptr, DDFLIP_WAIT);
}
if ((dwFlags & DDBLT_COLORFILL) == DDBLT_COLORFILL) {
if (lpDestRect != nullptr) {
MINIWIN_NOT_IMPLEMENTED();
}
Uint8 r = (lpDDBltFx->dwFillColor >> 16) & 0xFF;
Uint8 g = (lpDDBltFx->dwFillColor >> 8) & 0xFF;
Uint8 b = lpDDBltFx->dwFillColor & 0xFF;
SDL_SetRenderDrawColor(DDRenderer, r, g, b, 0xFF);
SDL_RenderClear(DDRenderer);
}
else {
auto srcSurface = dynamic_cast<DirectDrawSurfaceImpl*>(lpDDSrcSurface);
if (!srcSurface) {
return DDERR_GENERIC;
}
SDL_FRect srcRect, dstRect;
if (lpSrcRect) {
srcRect = ConvertRect(lpSrcRect);
}
if (lpDestRect) {
dstRect = ConvertRect(lpDestRect);
}
if (!SDL_RenderTexture(
DDRenderer,
srcSurface->m_texture,
lpSrcRect ? &srcRect : nullptr,
lpDestRect ? &dstRect : nullptr
)) {
return DDERR_GENERIC;
}
}
return DD_OK;
}
HRESULT FrameBufferImpl::BltFast(
DWORD dwX,
DWORD dwY,
IDirectDrawSurface* lpDDSrcSurface,
LPRECT lpSrcRect,
DDBltFastFlags dwTrans
)
{
RECT destRect = {
(int) dwX,
(int) dwY,
(int) (lpSrcRect->right - lpSrcRect->left + dwX),
(int) (lpSrcRect->bottom - lpSrcRect->top + dwY)
};
return Blt(&destRect, lpDDSrcSurface, lpSrcRect, DDBLT_NONE, nullptr);
}
HRESULT FrameBufferImpl::Flip(IDirectDrawSurface* lpDDSurfaceTargetOverride, DDFlipFlags dwFlags)
{
SDL_SetRenderTarget(DDRenderer, nullptr);
SDL_RenderTexture(DDRenderer, m_backBuffer, nullptr, nullptr);
SDL_RenderPresent(DDRenderer);
SDL_SetRenderTarget(DDRenderer, m_backBuffer);
return DD_OK;
}
HRESULT FrameBufferImpl::GetAttachedSurface(LPDDSCAPS lpDDSCaps, IDirectDrawSurface** lplpDDAttachedSurface)
{
if ((lpDDSCaps->dwCaps & DDSCAPS_BACKBUFFER) != DDSCAPS_BACKBUFFER) {
return DDERR_INVALIDPARAMS;
}
this->AddRef();
*lplpDDAttachedSurface = static_cast<IDirectDrawSurface*>(this);
return DD_OK;
}
HRESULT FrameBufferImpl::GetDC(HDC* lphDC)
{
MINIWIN_NOT_IMPLEMENTED();
return DD_OK;
}
HRESULT FrameBufferImpl::GetPalette(LPDIRECTDRAWPALETTE* lplpDDPalette)
{
MINIWIN_NOT_IMPLEMENTED();
return DD_OK;
}
HRESULT FrameBufferImpl::GetPixelFormat(LPDDPIXELFORMAT lpDDPixelFormat)
{
lpDDPixelFormat->dwFlags = DDPF_RGB;
const SDL_PixelFormatDetails* details = SDL_GetPixelFormatDetails(HWBackBufferFormat);
if (details->bits_per_pixel == 8) {
lpDDPixelFormat->dwFlags |= DDPF_PALETTEINDEXED8;
}
lpDDPixelFormat->dwRGBBitCount = details->bits_per_pixel;
lpDDPixelFormat->dwRBitMask = details->Rmask;
lpDDPixelFormat->dwGBitMask = details->Gmask;
lpDDPixelFormat->dwBBitMask = details->Bmask;
lpDDPixelFormat->dwRGBAlphaBitMask = details->Amask;
return DD_OK;
}
HRESULT FrameBufferImpl::GetSurfaceDesc(DDSURFACEDESC* lpDDSurfaceDesc)
{
lpDDSurfaceDesc->dwFlags = DDSD_PIXELFORMAT;
GetPixelFormat(&lpDDSurfaceDesc->ddpfPixelFormat);
lpDDSurfaceDesc->dwFlags |= DDSD_WIDTH | DDSD_HEIGHT;
lpDDSurfaceDesc->dwWidth = m_backBuffer->w;
lpDDSurfaceDesc->dwHeight = m_backBuffer->h;
return DD_OK;
}
HRESULT FrameBufferImpl::IsLost()
{
return DD_OK;
}
HRESULT FrameBufferImpl::Lock(LPRECT lpDestRect, DDSURFACEDESC* lpDDSurfaceDesc, DDLockFlags dwFlags, HANDLE hEvent)
{
m_readBackBuffer = SDL_RenderReadPixels(DDRenderer, nullptr);
if (!SDL_LockSurface(m_readBackBuffer)) {
return DDERR_GENERIC;
}
GetSurfaceDesc(lpDDSurfaceDesc);
lpDDSurfaceDesc->lpSurface = m_readBackBuffer->pixels;
lpDDSurfaceDesc->lPitch = m_readBackBuffer->pitch;
return DD_OK;
}
HRESULT FrameBufferImpl::ReleaseDC(HDC hDC)
{
MINIWIN_NOT_IMPLEMENTED();
return DD_OK;
}
HRESULT FrameBufferImpl::Restore()
{
MINIWIN_NOT_IMPLEMENTED();
return DD_OK;
}
HRESULT FrameBufferImpl::SetClipper(IDirectDrawClipper* lpDDClipper)
{
return DD_OK;
}
HRESULT FrameBufferImpl::SetColorKey(DDColorKeyFlags dwFlags, LPDDCOLORKEY lpDDColorKey)
{
MINIWIN_NOT_IMPLEMENTED();
return DD_OK;
}
HRESULT FrameBufferImpl::SetPalette(LPDIRECTDRAWPALETTE lpDDPalette)
{
MINIWIN_NOT_IMPLEMENTED();
return DD_OK;
}
HRESULT FrameBufferImpl::Unlock(LPVOID lpSurfaceData)
{
SDL_UpdateTexture(m_uploadBuffer, nullptr, m_readBackBuffer->pixels, m_readBackBuffer->pitch);
SDL_DestroySurface(m_readBackBuffer);
SDL_RenderTexture(DDRenderer, m_uploadBuffer, nullptr, nullptr);
return DD_OK;
}
void FrameBufferImpl::Upload(void* pixels, int pitch)
{
SDL_UpdateTexture(m_uploadBuffer, nullptr, pixels, pitch);
SDL_RenderTexture(DDRenderer, m_uploadBuffer, nullptr, nullptr);
}

View File

@ -24,7 +24,7 @@ struct Direct3DRMImpl : virtual public IDirect3DRM2 {
IDirect3DRMDevice2** outDevice IDirect3DRMDevice2** outDevice
) override; ) override;
HRESULT CreateTexture(D3DRMIMAGE* image, IDirect3DRMTexture2** outTexture) override; HRESULT CreateTexture(D3DRMIMAGE* image, IDirect3DRMTexture2** outTexture) override;
HRESULT CreateTextureFromSurface(LPDIRECTDRAWSURFACE surface, IDirect3DRMTexture2** outTexture) override; HRESULT CreateTextureFromSurface(IDirectDrawSurface* surface, IDirect3DRMTexture2** outTexture) override;
HRESULT CreateMesh(IDirect3DRMMesh** outMesh) override; HRESULT CreateMesh(IDirect3DRMMesh** outMesh) override;
HRESULT CreateMaterial(D3DVAL power, IDirect3DRMMaterial** outMaterial) override; HRESULT CreateMaterial(D3DVAL power, IDirect3DRMMaterial** outMaterial) override;
HRESULT CreateLightRGB(D3DRMLIGHTTYPE type, D3DVAL r, D3DVAL g, D3DVAL b, IDirect3DRMLight** outLight) override; HRESULT CreateLightRGB(D3DRMLIGHTTYPE type, D3DVAL r, D3DVAL g, D3DVAL b, IDirect3DRMLight** outLight) override;

View File

@ -62,6 +62,7 @@ class Direct3DRMSoftwareRenderer : public Direct3DRMRenderer {
DWORD m_width; DWORD m_width;
DWORD m_height; DWORD m_height;
SDL_Surface* m_renderedImage;
SDL_Palette* m_palette; SDL_Palette* m_palette;
const SDL_PixelFormatDetails* m_format; const SDL_PixelFormatDetails* m_format;
int m_bytesPerPixel; int m_bytesPerPixel;

View File

@ -1,13 +1,47 @@
#pragma once #pragma once
#include "d3drmobject_impl.h" #include "d3drmobject_impl.h"
#include "miniwin/ddraw.h"
struct Direct3DRMTextureImpl : public Direct3DRMObjectBaseImpl<IDirect3DRMTexture2> { #include <SDL3/SDL.h>
Direct3DRMTextureImpl(D3DRMIMAGE* image);
Direct3DRMTextureImpl(IDirectDrawSurface* surface); struct Direct3DRMTextureImpl : public Direct3DRMObjectBaseImpl<IDirect3DRMTexture2>, public IDirectDrawSurface3 {
Direct3DRMTextureImpl(int width, int height, SDL_PixelFormat format);
~Direct3DRMTextureImpl() override;
// IUnknown interface
HRESULT QueryInterface(const GUID& riid, void** ppvObject) override; HRESULT QueryInterface(const GUID& riid, void** ppvObject) override;
// IDirect3DRMTexture2 interface
HRESULT Changed(BOOL pixels, BOOL palette) override; HRESULT Changed(BOOL pixels, BOOL palette) override;
// IDirectDrawSurface interface
HRESULT AddAttachedSurface(IDirectDrawSurface* lpDDSAttachedSurface) override;
HRESULT Blt(
LPRECT lpDestRect,
IDirectDrawSurface* lpDDSrcSurface,
LPRECT lpSrcRect,
DDBltFlags dwFlags,
LPDDBLTFX lpDDBltFx
) override;
HRESULT BltFast(DWORD dwX, DWORD dwY, IDirectDrawSurface* lpDDSrcSurface, LPRECT lpSrcRect, DDBltFastFlags dwTrans)
override;
HRESULT Flip(IDirectDrawSurface* lpDDSurfaceTargetOverride, DDFlipFlags dwFlags) override;
HRESULT GetAttachedSurface(LPDDSCAPS lpDDSCaps, IDirectDrawSurface** lplpDDAttachedSurface) override;
HRESULT GetDC(HDC* lphDC) override;
HRESULT GetPalette(LPDIRECTDRAWPALETTE* lplpDDPalette) override;
HRESULT GetPixelFormat(LPDDPIXELFORMAT lpDDPixelFormat) override;
HRESULT GetSurfaceDesc(DDSURFACEDESC* lpDDSurfaceDesc) override;
HRESULT IsLost() override;
HRESULT Lock(LPRECT lpDestRect, DDSURFACEDESC* lpDDSurfaceDesc, DDLockFlags dwFlags, HANDLE hEvent) override;
HRESULT ReleaseDC(HDC hDC) override;
HRESULT Restore() override;
HRESULT SetClipper(IDirectDrawClipper* lpDDClipper) override;
HRESULT SetColorKey(DDColorKeyFlags dwFlags, LPDDCOLORKEY lpDDColorKey) override;
HRESULT SetPalette(LPDIRECTDRAWPALETTE lpDDPalette) override;
HRESULT Unlock(LPVOID lpSurfaceData) override;
IDirectDrawSurface* m_surface = nullptr; SDL_Surface* m_surface = nullptr;
Uint8 m_version = 0; Uint8 m_version = 0;
private:
IDirectDrawPalette* m_palette = nullptr;
}; };

View File

@ -1,14 +1,14 @@
#pragma once #pragma once
#include "d3drmrenderer.h" #include "d3drmrenderer.h"
#include "framebuffer_impl.h"
#include "miniwin/d3d.h" #include "miniwin/d3d.h"
#include "miniwin/ddraw.h" #include "miniwin/ddraw.h"
#include <SDL3/SDL.h> #include <SDL3/SDL.h>
extern SDL_Window* DDWindow; extern SDL_Window* DDWindow;
extern SDL_Surface* DDBackBuffer; extern FrameBufferImpl* DDFrameBuffer;
extern SDL_Texture* HWBackBuffer;
extern SDL_PixelFormat HWBackBufferFormat; extern SDL_PixelFormat HWBackBufferFormat;
extern SDL_Renderer* DDRenderer; extern SDL_Renderer* DDRenderer;
@ -16,7 +16,7 @@ struct DirectDrawImpl : public IDirectDraw2, public IDirect3D2 {
// IUnknown interface // IUnknown interface
HRESULT QueryInterface(const GUID& riid, void** ppvObject) override; HRESULT QueryInterface(const GUID& riid, void** ppvObject) override;
// IDirectDraw interface // IDirectDraw interface
HRESULT CreateClipper(DWORD dwFlags, LPDIRECTDRAWCLIPPER* lplpDDClipper, IUnknown* pUnkOuter) override; HRESULT CreateClipper(DWORD dwFlags, IDirectDrawClipper** lplpDDClipper, IUnknown* pUnkOuter) override;
HRESULT HRESULT
CreatePalette( CreatePalette(
DDPixelCaps dwFlags, DDPixelCaps dwFlags,
@ -24,17 +24,17 @@ struct DirectDrawImpl : public IDirectDraw2, public IDirect3D2 {
LPDIRECTDRAWPALETTE* lplpDDPalette, LPDIRECTDRAWPALETTE* lplpDDPalette,
IUnknown* pUnkOuter IUnknown* pUnkOuter
) override; ) override;
HRESULT CreateSurface(LPDDSURFACEDESC lpDDSurfaceDesc, LPDIRECTDRAWSURFACE* lplpDDSurface, IUnknown* pUnkOuter) HRESULT CreateSurface(DDSURFACEDESC* lpDDSurfaceDesc, IDirectDrawSurface** lplpDDSurface, IUnknown* pUnkOuter)
override; override;
HRESULT EnumDisplayModes( HRESULT EnumDisplayModes(
DWORD dwFlags, DWORD dwFlags,
LPDDSURFACEDESC lpDDSurfaceDesc, DDSURFACEDESC* lpDDSurfaceDesc,
LPVOID lpContext, LPVOID lpContext,
LPDDENUMMODESCALLBACK lpEnumModesCallback LPDDENUMMODESCALLBACK lpEnumModesCallback
) override; ) override;
HRESULT FlipToGDISurface() override; HRESULT FlipToGDISurface() override;
HRESULT GetCaps(LPDDCAPS lpDDDriverCaps, LPDDCAPS lpDDHELCaps) override; HRESULT GetCaps(LPDDCAPS lpDDDriverCaps, LPDDCAPS lpDDHELCaps) override;
HRESULT GetDisplayMode(LPDDSURFACEDESC lpDDSurfaceDesc) override; HRESULT GetDisplayMode(DDSURFACEDESC* lpDDSurfaceDesc) override;
HRESULT RestoreDisplayMode() override; HRESULT RestoreDisplayMode() override;
HRESULT SetCooperativeLevel(HWND hWnd, DDSCLFlags dwFlags) override; HRESULT SetCooperativeLevel(HWND hWnd, DDSCLFlags dwFlags) override;
HRESULT SetDisplayMode(DWORD dwWidth, DWORD dwHeight, DWORD dwBPP) override; HRESULT SetDisplayMode(DWORD dwWidth, DWORD dwHeight, DWORD dwBPP) override;

View File

@ -4,42 +4,36 @@
#include <miniwin/ddraw.h> #include <miniwin/ddraw.h>
struct DirectDrawSurfaceImpl : public IDirectDrawSurface3 { struct DirectDrawSurfaceImpl : public IDirectDrawSurface3 {
DirectDrawSurfaceImpl();
DirectDrawSurfaceImpl(int width, int height, SDL_PixelFormat format); DirectDrawSurfaceImpl(int width, int height, SDL_PixelFormat format);
~DirectDrawSurfaceImpl() override; ~DirectDrawSurfaceImpl() override;
// IUnknown interface // IUnknown interface
HRESULT QueryInterface(const GUID& riid, void** ppvObject) override; HRESULT QueryInterface(const GUID& riid, void** ppvObject) override;
// IDirectDrawSurface interface // IDirectDrawSurface interface
HRESULT AddAttachedSurface(LPDIRECTDRAWSURFACE lpDDSAttachedSurface) override; HRESULT AddAttachedSurface(IDirectDrawSurface* lpDDSAttachedSurface) override;
HRESULT Blt( HRESULT Blt(
LPRECT lpDestRect, LPRECT lpDestRect,
LPDIRECTDRAWSURFACE lpDDSrcSurface, IDirectDrawSurface* lpDDSrcSurface,
LPRECT lpSrcRect, LPRECT lpSrcRect,
DDBltFlags dwFlags, DDBltFlags dwFlags,
LPDDBLTFX lpDDBltFx LPDDBLTFX lpDDBltFx
) override; ) override;
HRESULT BltFast(DWORD dwX, DWORD dwY, LPDIRECTDRAWSURFACE lpDDSrcSurface, LPRECT lpSrcRect, DDBltFastFlags dwTrans) HRESULT BltFast(DWORD dwX, DWORD dwY, IDirectDrawSurface* lpDDSrcSurface, LPRECT lpSrcRect, DDBltFastFlags dwTrans)
override; override;
HRESULT Flip(LPDIRECTDRAWSURFACE lpDDSurfaceTargetOverride, DDFlipFlags dwFlags) override; HRESULT Flip(IDirectDrawSurface* lpDDSurfaceTargetOverride, DDFlipFlags dwFlags) override;
HRESULT GetAttachedSurface(LPDDSCAPS lpDDSCaps, LPDIRECTDRAWSURFACE* lplpDDAttachedSurface) override; HRESULT GetAttachedSurface(LPDDSCAPS lpDDSCaps, IDirectDrawSurface** lplpDDAttachedSurface) override;
HRESULT GetDC(HDC* lphDC) override; HRESULT GetDC(HDC* lphDC) override;
HRESULT GetPalette(LPDIRECTDRAWPALETTE* lplpDDPalette) override; HRESULT GetPalette(LPDIRECTDRAWPALETTE* lplpDDPalette) override;
HRESULT GetPixelFormat(LPDDPIXELFORMAT lpDDPixelFormat) override; HRESULT GetPixelFormat(LPDDPIXELFORMAT lpDDPixelFormat) override;
HRESULT GetSurfaceDesc(LPDDSURFACEDESC lpDDSurfaceDesc) override; HRESULT GetSurfaceDesc(DDSURFACEDESC* lpDDSurfaceDesc) override;
HRESULT IsLost() override; HRESULT IsLost() override;
HRESULT Lock(LPRECT lpDestRect, LPDDSURFACEDESC lpDDSurfaceDesc, DDLockFlags dwFlags, HANDLE hEvent) override; HRESULT Lock(LPRECT lpDestRect, DDSURFACEDESC* lpDDSurfaceDesc, DDLockFlags dwFlags, HANDLE hEvent) override;
HRESULT ReleaseDC(HDC hDC) override; HRESULT ReleaseDC(HDC hDC) override;
HRESULT Restore() override; HRESULT Restore() override;
HRESULT SetClipper(LPDIRECTDRAWCLIPPER lpDDClipper) override; HRESULT SetClipper(IDirectDrawClipper* lpDDClipper) override;
HRESULT SetColorKey(DDColorKeyFlags dwFlags, LPDDCOLORKEY lpDDColorKey) override; HRESULT SetColorKey(DDColorKeyFlags dwFlags, LPDDCOLORKEY lpDDColorKey) override;
HRESULT SetPalette(LPDIRECTDRAWPALETTE lpDDPalette) override; HRESULT SetPalette(LPDIRECTDRAWPALETTE lpDDPalette) override;
void SetAutoFlip(bool enabled);
HRESULT Unlock(LPVOID lpSurfaceData) override; HRESULT Unlock(LPVOID lpSurfaceData) override;
SDL_Surface* m_surface = nullptr; SDL_Texture* m_texture;
private:
bool m_autoFlip = false;
IDirectDrawPalette* m_palette = nullptr;
}; };

View File

@ -0,0 +1,103 @@
#pragma once
#include <miniwin.h>
#include <miniwin/ddraw.h>
struct DummySurfaceImpl : public IDirectDrawSurface3 {
// IUnknown interface
HRESULT QueryInterface(const GUID& riid, void** ppvObject) override
{
MINIWIN_NOT_IMPLEMENTED();
return DDERR_GENERIC;
}
// IDirectDrawSurface interface
HRESULT AddAttachedSurface(IDirectDrawSurface* lpDDSAttachedSurface) override
{
MINIWIN_NOT_IMPLEMENTED();
return DDERR_GENERIC;
}
HRESULT Blt(
LPRECT lpDestRect,
IDirectDrawSurface* lpDDSrcSurface,
LPRECT lpSrcRect,
DDBltFlags dwFlags,
LPDDBLTFX lpDDBltFx
) override
{
MINIWIN_NOT_IMPLEMENTED();
return DDERR_GENERIC;
}
HRESULT BltFast(DWORD dwX, DWORD dwY, IDirectDrawSurface* lpDDSrcSurface, LPRECT lpSrcRect, DDBltFastFlags dwTrans)
override
{
MINIWIN_NOT_IMPLEMENTED();
return DDERR_GENERIC;
}
HRESULT Flip(IDirectDrawSurface* lpDDSurfaceTargetOverride, DDFlipFlags dwFlags) override
{
MINIWIN_NOT_IMPLEMENTED();
return DDERR_GENERIC;
}
HRESULT GetAttachedSurface(LPDDSCAPS lpDDSCaps, IDirectDrawSurface** lplpDDAttachedSurface) override
{
MINIWIN_NOT_IMPLEMENTED();
return DDERR_GENERIC;
}
HRESULT GetDC(HDC* lphDC) override
{
MINIWIN_NOT_IMPLEMENTED();
return DDERR_GENERIC;
}
HRESULT GetPalette(LPDIRECTDRAWPALETTE* lplpDDPalette) override
{
MINIWIN_NOT_IMPLEMENTED();
return DDERR_GENERIC;
}
HRESULT GetPixelFormat(LPDDPIXELFORMAT lpDDPixelFormat) override
{
MINIWIN_NOT_IMPLEMENTED();
return DDERR_GENERIC;
}
HRESULT GetSurfaceDesc(DDSURFACEDESC* lpDDSurfaceDesc) override
{
MINIWIN_NOT_IMPLEMENTED();
return DDERR_GENERIC;
}
HRESULT IsLost() override { return DD_OK; }
HRESULT Lock(LPRECT lpDestRect, DDSURFACEDESC* lpDDSurfaceDesc, DDLockFlags dwFlags, HANDLE hEvent) override
{
MINIWIN_NOT_IMPLEMENTED();
return DDERR_GENERIC;
}
HRESULT ReleaseDC(HDC hDC) override
{
MINIWIN_NOT_IMPLEMENTED();
return DDERR_GENERIC;
}
HRESULT Restore() override
{
MINIWIN_NOT_IMPLEMENTED();
return DDERR_GENERIC;
}
HRESULT SetClipper(IDirectDrawClipper* lpDDClipper) override
{
MINIWIN_NOT_IMPLEMENTED();
return DDERR_GENERIC;
}
HRESULT SetColorKey(DDColorKeyFlags dwFlags, LPDDCOLORKEY lpDDColorKey) override
{
MINIWIN_NOT_IMPLEMENTED();
return DDERR_GENERIC;
}
HRESULT SetPalette(LPDIRECTDRAWPALETTE lpDDPalette) override
{
MINIWIN_NOT_IMPLEMENTED();
return DDERR_GENERIC;
}
HRESULT Unlock(LPVOID lpSurfaceData) override
{
MINIWIN_NOT_IMPLEMENTED();
return DDERR_GENERIC;
}
};

View File

@ -0,0 +1,45 @@
#pragma once
#include <SDL3/SDL.h>
#include <ddsurface_impl.h>
#include <miniwin/ddraw.h>
struct FrameBufferImpl : public IDirectDrawSurface3 {
FrameBufferImpl();
~FrameBufferImpl() override;
// IUnknown interface
HRESULT QueryInterface(const GUID& riid, void** ppvObject) override;
// IDirectDrawSurface interface
HRESULT AddAttachedSurface(IDirectDrawSurface* lpDDSAttachedSurface) override;
HRESULT Blt(
LPRECT lpDestRect,
IDirectDrawSurface* lpDDSrcSurface,
LPRECT lpSrcRect,
DDBltFlags dwFlags,
LPDDBLTFX lpDDBltFx
) override;
HRESULT BltFast(DWORD dwX, DWORD dwY, IDirectDrawSurface* lpDDSrcSurface, LPRECT lpSrcRect, DDBltFastFlags dwTrans)
override;
HRESULT Flip(IDirectDrawSurface* lpDDSurfaceTargetOverride, DDFlipFlags dwFlags) override;
HRESULT GetAttachedSurface(LPDDSCAPS lpDDSCaps, IDirectDrawSurface** lplpDDAttachedSurface) override;
HRESULT GetDC(HDC* lphDC) override;
HRESULT GetPalette(LPDIRECTDRAWPALETTE* lplpDDPalette) override;
HRESULT GetPixelFormat(LPDDPIXELFORMAT lpDDPixelFormat) override;
HRESULT GetSurfaceDesc(DDSURFACEDESC* lpDDSurfaceDesc) override;
HRESULT IsLost() override;
HRESULT Lock(LPRECT lpDestRect, DDSURFACEDESC* lpDDSurfaceDesc, DDLockFlags dwFlags, HANDLE hEvent) override;
HRESULT ReleaseDC(HDC hDC) override;
HRESULT Restore() override;
HRESULT SetClipper(IDirectDrawClipper* lpDDClipper) override;
HRESULT SetColorKey(DDColorKeyFlags dwFlags, LPDDCOLORKEY lpDDColorKey) override;
HRESULT SetPalette(LPDIRECTDRAWPALETTE lpDDPalette) override;
HRESULT Unlock(LPVOID lpSurfaceData) override;
void Upload(void* pixels, int pitch);
private:
SDL_Surface* m_readBackBuffer;
SDL_Texture* m_backBuffer;
SDL_Texture* m_uploadBuffer;
};