From 79726d25a4f88ef92dfde4f81e0d5c312d3d6033 Mon Sep 17 00:00:00 2001 From: Anders Jenbo Date: Mon, 16 Jun 2025 18:11:56 +0200 Subject: [PATCH] Split framebuffer from general surfaces (#319) --- miniwin/CMakeLists.txt | 5 +- miniwin/src/ddraw/ddraw.cpp | 70 +++---- miniwin/src/ddraw/ddsurface.cpp | 149 ++------------- miniwin/src/ddraw/framebuffer.cpp | 232 +++++++++++++++++++++++ miniwin/src/internal/ddraw_impl.h | 9 +- miniwin/src/internal/ddsurface_impl.h | 3 - miniwin/src/internal/dummysurface_impl.h | 103 ++++++++++ miniwin/src/internal/framebuffer_impl.h | 42 ++++ 8 files changed, 431 insertions(+), 182 deletions(-) create mode 100644 miniwin/src/ddraw/framebuffer.cpp create mode 100644 miniwin/src/internal/dummysurface_impl.h create mode 100644 miniwin/src/internal/framebuffer_impl.h diff --git a/miniwin/CMakeLists.txt b/miniwin/CMakeLists.txt index 9c8d2793..1071afcf 100644 --- a/miniwin/CMakeLists.txt +++ b/miniwin/CMakeLists.txt @@ -6,9 +6,10 @@ add_library(miniwin STATIC EXCLUDE_FROM_ALL src/windows/windows.cpp # DDraw - src/ddraw/ddraw.cpp src/ddraw/ddpalette.cpp + src/ddraw/ddraw.cpp src/ddraw/ddsurface.cpp + src/ddraw/framebuffer.cpp # D3DRM src/d3drm/d3drm.cpp @@ -21,9 +22,9 @@ add_library(miniwin STATIC EXCLUDE_FROM_ALL src/internal/meshutils.cpp # D3DRM backends - src/d3drm/backends/software/renderer.cpp src/d3drm/backends/sdl3gpu/renderer.cpp src/d3drm/backends/sdl3gpu/shaders/generated/ShaderIndex.cpp + src/d3drm/backends/software/renderer.cpp ) find_package(OpenGL) diff --git a/miniwin/src/ddraw/ddraw.cpp b/miniwin/src/ddraw/ddraw.cpp index 6789c5c4..b3c000cf 100644 --- a/miniwin/src/ddraw/ddraw.cpp +++ b/miniwin/src/ddraw/ddraw.cpp @@ -6,6 +6,7 @@ #include "ddpalette_impl.h" #include "ddraw_impl.h" #include "ddsurface_impl.h" +#include "dummysurface_impl.h" #include "miniwin.h" #include "miniwin/d3d.h" @@ -17,8 +18,7 @@ SDL_Window* DDWindow; SDL_Surface* DDBackBuffer; -SDL_Texture* HWBackBuffer; -SDL_PixelFormat HWBackBufferFormat; +FrameBufferImpl* DDFrameBuffer; SDL_Renderer* DDRenderer; HRESULT DirectDrawImpl::QueryInterface(const GUID& riid, void** ppvObject) @@ -66,6 +66,30 @@ HRESULT DirectDrawImpl::CreateSurface( IUnknown* pUnkOuter ) { + 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(new DummySurfaceImpl); + return DD_OK; + } + if ((lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) == DDSCAPS_PRIMARYSURFACE) { + DDFrameBuffer = new FrameBufferImpl(); + *lplpDDSurface = static_cast(DDFrameBuffer); + return DD_OK; + } + if ((lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_3DDEVICE) == DDSCAPS_3DDEVICE) { + DDFrameBuffer->AddRef(); + *lplpDDSurface = static_cast(DDFrameBuffer); + return DD_OK; + } + if ((lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_TEXTURE) == DDSCAPS_TEXTURE) { + MINIWIN_TRACE("DDSCAPS_TEXTURE"); // Texture for use in 3D + } + } + SDL_PixelFormat format; #ifdef MINIWIN_PIXELFORMAT format = MINIWIN_PIXELFORMAT; @@ -84,44 +108,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(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(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)) { return DDERR_INVALIDPARAMS; @@ -305,14 +291,14 @@ HRESULT DirectDrawImpl::SetCooperativeLevel(HWND hWnd, DDSCLFlags dwFlags) } DDWindow = sdlWindow; DDRenderer = SDL_CreateRenderer(DDWindow, NULL); - SDL_SetRenderLogicalPresentation(DDRenderer, 640, 480, SDL_LOGICAL_PRESENTATION_LETTERBOX); + SDL_PropertiesID prop = SDL_GetRendererProperties(DDRenderer); } return DD_OK; } HRESULT DirectDrawImpl::SetDisplayMode(DWORD dwWidth, DWORD dwHeight, DWORD dwBPP) { - MINIWIN_NOT_IMPLEMENTED(); + SDL_SetRenderLogicalPresentation(DDRenderer, dwWidth, dwHeight, SDL_LOGICAL_PRESENTATION_LETTERBOX); return DD_OK; } diff --git a/miniwin/src/ddraw/ddsurface.cpp b/miniwin/src/ddraw/ddsurface.cpp index dc1518f1..59c4569a 100644 --- a/miniwin/src/ddraw/ddsurface.cpp +++ b/miniwin/src/ddraw/ddsurface.cpp @@ -5,10 +5,6 @@ #include -DirectDrawSurfaceImpl::DirectDrawSurfaceImpl() -{ -} - DirectDrawSurfaceImpl::DirectDrawSurfaceImpl(int width, int height, SDL_PixelFormat format) { m_surface = SDL_CreateSurface(width, height, format); @@ -19,9 +15,7 @@ DirectDrawSurfaceImpl::DirectDrawSurfaceImpl(int width, int height, SDL_PixelFor DirectDrawSurfaceImpl::~DirectDrawSurfaceImpl() { - if (m_surface) { - SDL_DestroySurface(m_surface); - } + SDL_DestroySurface(m_surface); if (m_palette) { m_palette->Release(); } @@ -42,44 +36,10 @@ HRESULT DirectDrawSurfaceImpl::QueryInterface(const GUID& riid, void** ppvObject // IDirectDrawSurface interface HRESULT DirectDrawSurfaceImpl::AddAttachedSurface(LPDIRECTDRAWSURFACE lpDDSAttachedSurface) { + MINIWIN_NOT_IMPLEMENTED(); return DD_OK; } -void DirectDrawSurfaceImpl::SetAutoFlip(bool enabled) -{ - m_autoFlip = enabled; -} - -static SDL_Rect ConvertRect(const RECT* r) -{ - 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( LPRECT lpDestRect, LPDIRECTDRAWSURFACE lpDDSrcSurface, @@ -88,53 +48,15 @@ HRESULT DirectDrawSurfaceImpl::Blt( LPDDBLTFX lpDDBltFx ) { - if ((dwFlags & DDBLT_COLORFILL) == DDBLT_COLORFILL) { - SDL_Rect rect = {0, 0, m_surface->w, m_surface->h}; - const SDL_PixelFormatDetails* details = SDL_GetPixelFormatDetails(m_surface->format); - Uint8 r = (lpDDBltFx->dwFillColor >> 16) & 0xFF; - Uint8 g = (lpDDBltFx->dwFillColor >> 8) & 0xFF; - Uint8 b = lpDDBltFx->dwFillColor & 0xFF; - DirectDrawPaletteImpl* ddPal = static_cast(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(lpDDSrcSurface); - if (!srcSurface || !srcSurface->m_surface) { - return DDERR_GENERIC; - } - if (m_autoFlip) { - DDBackBuffer = srcSurface->m_surface; - if (!HWBackBuffer && !SetupHWBackBuffer()) { - return DDERR_GENERIC; - } - return Flip(nullptr, DDFLIP_WAIT); - } + auto other = static_cast(lpDDSrcSurface); - SDL_Rect srcRect; - if (lpSrcRect) { - srcRect = ConvertRect(lpSrcRect); - } - else { - srcRect = {0, 0, srcSurface->m_surface->w, srcSurface->m_surface->h}; - } + SDL_Rect srcRect = lpSrcRect ? ConvertRect(lpSrcRect) : SDL_Rect{0, 0, other->m_surface->w, other->m_surface->h}; + SDL_Rect dstRect = lpDestRect ? ConvertRect(lpDestRect) : SDL_Rect{0, 0, m_surface->w, m_surface->h}; - SDL_Rect dstRect; - if (lpDestRect) { - dstRect = ConvertRect(lpDestRect); - } - else { - dstRect = {0, 0, m_surface->w, m_surface->h}; - } + SDL_Surface* blitSource = other->m_surface; - SDL_Surface* blitSource = srcSurface->m_surface; - - if (srcSurface->m_surface->format != m_surface->format) { - blitSource = SDL_ConvertSurface(srcSurface->m_surface, m_surface->format); + if (other->m_surface->format != m_surface->format) { + blitSource = SDL_ConvertSurface(other->m_surface, m_surface->format); if (!blitSource) { return DDERR_GENERIC; } @@ -144,7 +66,7 @@ HRESULT DirectDrawSurfaceImpl::Blt( return DDERR_GENERIC; } - if (blitSource != srcSurface->m_surface) { + if (blitSource != other->m_surface) { SDL_DestroySurface(blitSource); } return DD_OK; @@ -169,39 +91,13 @@ HRESULT DirectDrawSurfaceImpl::BltFast( HRESULT DirectDrawSurfaceImpl::Flip(LPDIRECTDRAWSURFACE lpDDSurfaceTargetOverride, DDFlipFlags dwFlags) { - if (!DDBackBuffer || !DDRenderer) { - return DDERR_GENERIC; - } - - SDL_Surface* blitSource; - if (HWBackBufferFormat != DDBackBuffer->format) { - blitSource = SDL_ConvertSurface(DDBackBuffer, HWBackBufferFormat); - if (!blitSource) { - return DDERR_GENERIC; - } - } - else { - blitSource = DDBackBuffer; - } - SDL_UpdateTexture(HWBackBuffer, nullptr, blitSource->pixels, blitSource->pitch); - if (HWBackBufferFormat != DDBackBuffer->format) { - SDL_DestroySurface(blitSource); - } - SDL_RenderTexture(DDRenderer, HWBackBuffer, nullptr, nullptr); - SDL_RenderPresent(DDRenderer); + MINIWIN_NOT_IMPLEMENTED(); return DD_OK; } HRESULT DirectDrawSurfaceImpl::GetAttachedSurface(LPDDSCAPS lpDDSCaps, LPDIRECTDRAWSURFACE* lplpDDAttachedSurface) { - if ((lpDDSCaps->dwCaps & DDSCAPS_BACKBUFFER) != DDSCAPS_BACKBUFFER) { - return DDERR_INVALIDPARAMS; - } - DDBackBuffer = m_surface; - if (!SetupHWBackBuffer()) { - return DDERR_GENERIC; - } - *lplpDDAttachedSurface = static_cast(this); + MINIWIN_NOT_IMPLEMENTED(); return DD_OK; } @@ -223,9 +119,6 @@ HRESULT DirectDrawSurfaceImpl::GetPalette(LPDIRECTDRAWPALETTE* lplpDDPalette) HRESULT DirectDrawSurfaceImpl::GetPixelFormat(LPDDPIXELFORMAT lpDDPixelFormat) { - if (!m_surface) { - return DDERR_GENERIC; - } memset(lpDDPixelFormat, 0, sizeof(*lpDDPixelFormat)); lpDDPixelFormat->dwFlags = DDPF_RGB; const SDL_PixelFormatDetails* details = SDL_GetPixelFormatDetails(m_surface->format); @@ -242,16 +135,11 @@ HRESULT DirectDrawSurfaceImpl::GetPixelFormat(LPDDPIXELFORMAT lpDDPixelFormat) HRESULT DirectDrawSurfaceImpl::GetSurfaceDesc(LPDDSURFACEDESC lpDDSurfaceDesc) { - if (!m_surface) { - return DDERR_GENERIC; - } lpDDSurfaceDesc->dwFlags = DDSD_PIXELFORMAT; GetPixelFormat(&lpDDSurfaceDesc->ddpfPixelFormat); - if (m_surface) { - lpDDSurfaceDesc->dwFlags |= DDSD_WIDTH | DDSD_HEIGHT; - lpDDSurfaceDesc->dwWidth = m_surface->w; - lpDDSurfaceDesc->dwHeight = m_surface->h; - } + lpDDSurfaceDesc->dwFlags |= DDSD_WIDTH | DDSD_HEIGHT; + lpDDSurfaceDesc->dwWidth = m_surface->w; + lpDDSurfaceDesc->dwHeight = m_surface->h; return DD_OK; } @@ -267,10 +155,6 @@ HRESULT DirectDrawSurfaceImpl::Lock( HANDLE hEvent ) { - if (!m_surface) { - return DDERR_GENERIC; - } - if (!SDL_LockSurface(m_surface)) { return DDERR_GENERIC; } @@ -290,11 +174,13 @@ HRESULT DirectDrawSurfaceImpl::ReleaseDC(HDC hDC) HRESULT DirectDrawSurfaceImpl::Restore() { + MINIWIN_NOT_IMPLEMENTED(); return DD_OK; } HRESULT DirectDrawSurfaceImpl::SetClipper(LPDIRECTDRAWCLIPPER lpDDClipper) { + MINIWIN_NOT_IMPLEMENTED(); return DD_OK; } @@ -329,9 +215,6 @@ HRESULT DirectDrawSurfaceImpl::SetPalette(LPDIRECTDRAWPALETTE lpDDPalette) HRESULT DirectDrawSurfaceImpl::Unlock(LPVOID lpSurfaceData) { - if (!m_surface) { - return DDERR_GENERIC; - } SDL_UnlockSurface(m_surface); return DD_OK; } diff --git a/miniwin/src/ddraw/framebuffer.cpp b/miniwin/src/ddraw/framebuffer.cpp new file mode 100644 index 00000000..eee8b7cb --- /dev/null +++ b/miniwin/src/ddraw/framebuffer.cpp @@ -0,0 +1,232 @@ +#include "ddpalette_impl.h" +#include "ddraw_impl.h" +#include "dummysurface_impl.h" +#include "framebuffer_impl.h" +#include "miniwin.h" + +#include + +FrameBufferImpl::FrameBufferImpl() +{ + int width, height; + SDL_GetRenderOutputSize(DDRenderer, &width, &height); + DDBackBuffer = SDL_CreateSurface(width, height, SDL_PIXELFORMAT_RGBA8888); + if (!DDBackBuffer) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to create surface: %s", SDL_GetError()); + } + m_uploadBuffer = + SDL_CreateTexture(DDRenderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STREAMING, width, height); +} + +FrameBufferImpl::~FrameBufferImpl() +{ + SDL_DestroySurface(DDBackBuffer); + if (m_palette) { + m_palette->Release(); + } +} + +// IUnknown interface +HRESULT FrameBufferImpl::QueryInterface(const GUID& riid, void** ppvObject) +{ + MINIWIN_NOT_IMPLEMENTED(); + return E_NOINTERFACE; +} + +// IDirectDrawSurface interface +HRESULT FrameBufferImpl::AddAttachedSurface(LPDIRECTDRAWSURFACE lpDDSAttachedSurface) +{ + if (dynamic_cast(lpDDSAttachedSurface)) { + return DD_OK; + } + MINIWIN_NOT_IMPLEMENTED(); + return DDERR_GENERIC; +} + +HRESULT FrameBufferImpl::Blt( + LPRECT lpDestRect, + LPDIRECTDRAWSURFACE lpDDSrcSurface, + LPRECT lpSrcRect, + DDBltFlags dwFlags, + LPDDBLTFX lpDDBltFx +) +{ + if (dynamic_cast(lpDDSrcSurface) == this) { + return Flip(nullptr, DDFLIP_WAIT); + } + if ((dwFlags & DDBLT_COLORFILL) == DDBLT_COLORFILL) { + SDL_Rect rect = {0, 0, DDBackBuffer->w, DDBackBuffer->h}; + const SDL_PixelFormatDetails* details = SDL_GetPixelFormatDetails(DDBackBuffer->format); + Uint8 r = (lpDDBltFx->dwFillColor >> 16) & 0xFF; + Uint8 g = (lpDDBltFx->dwFillColor >> 8) & 0xFF; + Uint8 b = lpDDBltFx->dwFillColor & 0xFF; + DirectDrawPaletteImpl* ddPal = static_cast(m_palette); + SDL_Palette* sdlPalette = ddPal ? ddPal->m_palette : nullptr; + Uint32 color = SDL_MapRGB(details, sdlPalette, r, g, b); + SDL_FillSurfaceRect(DDBackBuffer, &rect, color); + return DD_OK; + } + auto other = static_cast(lpDDSrcSurface); + if (!other) { + return DDERR_GENERIC; + } + SDL_Rect srcRect = lpSrcRect ? ConvertRect(lpSrcRect) : SDL_Rect{0, 0, other->m_surface->w, other->m_surface->h}; + SDL_Rect dstRect = lpDestRect ? ConvertRect(lpDestRect) : SDL_Rect{0, 0, DDBackBuffer->w, DDBackBuffer->h}; + + SDL_Surface* blitSource = other->m_surface; + + if (other->m_surface->format != DDBackBuffer->format) { + blitSource = SDL_ConvertSurface(other->m_surface, DDBackBuffer->format); + if (!blitSource) { + return DDERR_GENERIC; + } + } + + if (!SDL_BlitSurfaceScaled(blitSource, &srcRect, DDBackBuffer, &dstRect, SDL_SCALEMODE_NEAREST)) { + return DDERR_GENERIC; + } + + if (blitSource != other->m_surface) { + SDL_DestroySurface(blitSource); + } + return DD_OK; +} + +HRESULT FrameBufferImpl::BltFast( + DWORD dwX, + DWORD dwY, + LPDIRECTDRAWSURFACE 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(LPDIRECTDRAWSURFACE lpDDSurfaceTargetOverride, DDFlipFlags dwFlags) +{ + SDL_UpdateTexture(m_uploadBuffer, nullptr, DDBackBuffer->pixels, DDBackBuffer->pitch); + SDL_RenderTexture(DDRenderer, m_uploadBuffer, nullptr, nullptr); + SDL_RenderPresent(DDRenderer); + return DD_OK; +} + +HRESULT FrameBufferImpl::GetAttachedSurface(LPDDSCAPS lpDDSCaps, LPDIRECTDRAWSURFACE* lplpDDAttachedSurface) +{ + if ((lpDDSCaps->dwCaps & DDSCAPS_BACKBUFFER) != DDSCAPS_BACKBUFFER) { + return DDERR_INVALIDPARAMS; + } + *lplpDDAttachedSurface = static_cast(this); + return DD_OK; +} + +HRESULT FrameBufferImpl::GetDC(HDC* lphDC) +{ + MINIWIN_NOT_IMPLEMENTED(); + return DD_OK; +} + +HRESULT FrameBufferImpl::GetPalette(LPDIRECTDRAWPALETTE* lplpDDPalette) +{ + if (!m_palette) { + return DDERR_GENERIC; + } + m_palette->AddRef(); + *lplpDDPalette = m_palette; + return DD_OK; +} + +HRESULT FrameBufferImpl::GetPixelFormat(LPDDPIXELFORMAT lpDDPixelFormat) +{ + memset(lpDDPixelFormat, 0, sizeof(*lpDDPixelFormat)); + lpDDPixelFormat->dwFlags = DDPF_RGB; + const SDL_PixelFormatDetails* details = SDL_GetPixelFormatDetails(DDBackBuffer->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 FrameBufferImpl::GetSurfaceDesc(LPDDSURFACEDESC lpDDSurfaceDesc) +{ + lpDDSurfaceDesc->dwFlags = DDSD_PIXELFORMAT; + GetPixelFormat(&lpDDSurfaceDesc->ddpfPixelFormat); + lpDDSurfaceDesc->dwFlags |= DDSD_WIDTH | DDSD_HEIGHT; + lpDDSurfaceDesc->dwWidth = DDBackBuffer->w; + lpDDSurfaceDesc->dwHeight = DDBackBuffer->h; + return DD_OK; +} + +HRESULT FrameBufferImpl::IsLost() +{ + return DD_OK; +} + +HRESULT FrameBufferImpl::Lock(LPRECT lpDestRect, DDSURFACEDESC* lpDDSurfaceDesc, DDLockFlags dwFlags, HANDLE hEvent) +{ + if (!SDL_LockSurface(DDBackBuffer)) { + return DDERR_GENERIC; + } + + GetSurfaceDesc(lpDDSurfaceDesc); + lpDDSurfaceDesc->lpSurface = DDBackBuffer->pixels; + lpDDSurfaceDesc->lPitch = DDBackBuffer->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(LPDIRECTDRAWCLIPPER lpDDClipper) +{ + return DD_OK; +} + +HRESULT FrameBufferImpl::SetColorKey(DDColorKeyFlags dwFlags, LPDDCOLORKEY lpDDColorKey) +{ + MINIWIN_NOT_IMPLEMENTED(); + return DD_OK; +} + +HRESULT FrameBufferImpl::SetPalette(LPDIRECTDRAWPALETTE lpDDPalette) +{ + if (DDBackBuffer->format != SDL_PIXELFORMAT_INDEX8) { + MINIWIN_NOT_IMPLEMENTED(); + } + + if (m_palette) { + m_palette->Release(); + } + + m_palette = lpDDPalette; + SDL_SetSurfacePalette(DDBackBuffer, ((DirectDrawPaletteImpl*) m_palette)->m_palette); + m_palette->AddRef(); + return DD_OK; +} + +HRESULT FrameBufferImpl::Unlock(LPVOID lpSurfaceData) +{ + SDL_UnlockSurface(DDBackBuffer); + return DD_OK; +} diff --git a/miniwin/src/internal/ddraw_impl.h b/miniwin/src/internal/ddraw_impl.h index 00256835..7cefe2f6 100644 --- a/miniwin/src/internal/ddraw_impl.h +++ b/miniwin/src/internal/ddraw_impl.h @@ -1,6 +1,7 @@ #pragma once #include "d3drmrenderer.h" +#include "framebuffer_impl.h" #include "miniwin/d3d.h" #include "miniwin/ddraw.h" @@ -8,10 +9,14 @@ extern SDL_Window* DDWindow; extern SDL_Surface* DDBackBuffer; -extern SDL_Texture* HWBackBuffer; -extern SDL_PixelFormat HWBackBufferFormat; +extern FrameBufferImpl* DDFrameBuffer; extern SDL_Renderer* DDRenderer; +inline static SDL_Rect ConvertRect(const RECT* r) +{ + return {r->left, r->top, r->right - r->left, r->bottom - r->top}; +} + struct DirectDrawImpl : public IDirectDraw2, public IDirect3D2 { // IUnknown interface HRESULT QueryInterface(const GUID& riid, void** ppvObject) override; diff --git a/miniwin/src/internal/ddsurface_impl.h b/miniwin/src/internal/ddsurface_impl.h index 3a149b91..4218e157 100644 --- a/miniwin/src/internal/ddsurface_impl.h +++ b/miniwin/src/internal/ddsurface_impl.h @@ -4,7 +4,6 @@ #include struct DirectDrawSurfaceImpl : public IDirectDrawSurface3 { - DirectDrawSurfaceImpl(); DirectDrawSurfaceImpl(int width, int height, SDL_PixelFormat format); ~DirectDrawSurfaceImpl() override; @@ -34,12 +33,10 @@ struct DirectDrawSurfaceImpl : public IDirectDrawSurface3 { HRESULT SetClipper(LPDIRECTDRAWCLIPPER lpDDClipper) override; HRESULT SetColorKey(DDColorKeyFlags dwFlags, LPDDCOLORKEY lpDDColorKey) override; HRESULT SetPalette(LPDIRECTDRAWPALETTE lpDDPalette) override; - void SetAutoFlip(bool enabled); HRESULT Unlock(LPVOID lpSurfaceData) override; SDL_Surface* m_surface = nullptr; private: - bool m_autoFlip = false; IDirectDrawPalette* m_palette = nullptr; }; diff --git a/miniwin/src/internal/dummysurface_impl.h b/miniwin/src/internal/dummysurface_impl.h new file mode 100644 index 00000000..9502adcb --- /dev/null +++ b/miniwin/src/internal/dummysurface_impl.h @@ -0,0 +1,103 @@ +#pragma once + +#include +#include + +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; + } +}; diff --git a/miniwin/src/internal/framebuffer_impl.h b/miniwin/src/internal/framebuffer_impl.h new file mode 100644 index 00000000..c2d9e3c8 --- /dev/null +++ b/miniwin/src/internal/framebuffer_impl.h @@ -0,0 +1,42 @@ +#pragma once + +#include +#include +#include + +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; + +private: + SDL_Texture* m_uploadBuffer; + IDirectDrawPalette* m_palette = nullptr; +};