Split miniwin headers and implementation (#96)

* Split miniwin headers and implementation

* Update miniwin/miniwin/src/miniwin_ddsurface.cpp

Co-authored-by: Anders Jenbo <anders@jenbo.dk>

* Update miniwin/miniwin/src/miniwin_ddraw.cpp

Co-authored-by: Anders Jenbo <anders@jenbo.dk>

* Update miniwin/miniwin/src/miniwin_ddsurface.cpp

Co-authored-by: Anders Jenbo <anders@jenbo.dk>

* Update miniwin/miniwin/src/miniwin_ddsurface.cpp

* Update miniwin/miniwin/src/miniwin_ddraw.cpp

Co-authored-by: Anders Jenbo <anders@jenbo.dk>

* Update miniwin/miniwin/src/miniwin_ddraw.cpp

Co-authored-by: Anders Jenbo <anders@jenbo.dk>

---------

Co-authored-by: Anders Jenbo <anders@jenbo.dk>
This commit is contained in:
Anonymous Maarten 2025-05-16 21:37:16 +02:00 committed by GitHub
parent 115fa35d5a
commit c99f7c36c6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 585 additions and 347 deletions

View File

@ -87,11 +87,14 @@ endif()
#if (NOT WIN32)
add_library(miniwin STATIC EXCLUDE_FROM_ALL
miniwin/miniwin/src/miniwin.cpp
miniwin/miniwin/src/miniwin_ddclipper.cpp
miniwin/miniwin/src/miniwin_ddpalette.cpp
miniwin/miniwin/src/miniwin_ddsurface.cpp
miniwin/miniwin/src/miniwin_ddraw.cpp
miniwin/miniwin/src/miniwin_d3d.cpp
miniwin/miniwin/src/miniwin_d3drm.cpp
)
target_include_directories(miniwin PUBLIC "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/miniwin/miniwin/include>")
target_include_directories(miniwin PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/miniwin/miniwin/src/include")
target_compile_definitions(miniwin PUBLIC "MINIWIN")
target_link_libraries(miniwin PRIVATE SDL3::SDL3)

View File

@ -0,0 +1,14 @@
#pragma once
#include <SDL3/SDL.h>
#include <miniwin_ddraw.h>
class DirectDrawImpl;
struct DirectDrawClipperImpl : public IDirectDrawClipper {
DirectDrawClipperImpl(DirectDrawImpl* lpDD);
~DirectDrawClipperImpl() override;
// IDirectDrawClipper interface
HRESULT SetHWnd(DWORD unnamedParam1, HWND hWnd) override;
};

View File

@ -0,0 +1,10 @@
#pragma once
#include "miniwin_ddraw.h"
struct DirectDrawPaletteImpl : public IDirectDrawPalette {
DirectDrawPaletteImpl(LPPALETTEENTRY lpColorTable);
HRESULT GetCaps(LPDWORD lpdwCaps) override;
HRESULT GetEntries(DWORD dwFlags, DWORD dwBase, DWORD dwNumEntries, LPPALETTEENTRY lpEntries) override;
HRESULT SetEntries(DWORD dwFlags, DWORD dwStartingEntry, DWORD dwCount, LPPALETTEENTRY lpEntries) override;
};

View File

@ -0,0 +1,37 @@
#pragma once
#include "miniwin_d3d.h"
#include "miniwin_ddraw.h"
extern struct SDL_Renderer* renderer;
struct DirectDrawImpl : public IDirectDraw2, public IDirect3D2 {
// IUnknown interface
HRESULT QueryInterface(const GUID& riid, void** ppvObject) override;
// IDirectDraw interface
HRESULT CreateClipper(DWORD dwFlags, LPDIRECTDRAWCLIPPER* lplpDDClipper, IUnknown* pUnkOuter) override;
HRESULT
CreatePalette(
DDPixelCaps dwFlags,
LPPALETTEENTRY lpColorTable,
LPDIRECTDRAWPALETTE* lplpDDPalette,
IUnknown* pUnkOuter
) override;
HRESULT CreateSurface(LPDDSURFACEDESC lpDDSurfaceDesc, LPDIRECTDRAWSURFACE* lplpDDSurface, IUnknown* pUnkOuter)
override;
HRESULT EnumDisplayModes(
DWORD dwFlags,
LPDDSURFACEDESC lpDDSurfaceDesc,
LPVOID lpContext,
LPDDENUMMODESCALLBACK lpEnumModesCallback
) override;
HRESULT FlipToGDISurface() override;
HRESULT GetCaps(LPDDCAPS lpDDDriverCaps, LPDDCAPS lpDDHELCaps) override;
HRESULT GetDisplayMode(LPDDSURFACEDESC lpDDSurfaceDesc) override;
HRESULT RestoreDisplayMode() override;
HRESULT SetCooperativeLevel(HWND hWnd, DDSCLFlags dwFlags) override;
HRESULT SetDisplayMode(DWORD dwWidth, DWORD dwHeight, DWORD dwBPP) override;
// IDirect3D2 interface
HRESULT CreateDevice(const GUID& guid, void* pBackBuffer, IDirect3DDevice2** ppDirect3DDevice) override;
HRESULT EnumDevices(LPD3DENUMDEVICESCALLBACK cb, void* ctx) override;
};

View File

@ -0,0 +1,43 @@
#pragma once
#include <SDL3/SDL.h>
#include <miniwin_ddraw.h>
struct DirectDrawSurfaceImpl : public IDirectDrawSurface3 {
DirectDrawSurfaceImpl();
DirectDrawSurfaceImpl(int width, int height);
~DirectDrawSurfaceImpl() override;
// IUnknown interface
HRESULT QueryInterface(const GUID& riid, void** ppvObject) override;
// IDirectDrawSurface interface
HRESULT AddAttachedSurface(LPDIRECTDRAWSURFACE lpDDSAttachedSurface) override;
HRESULT Blt(
LPRECT lpDestRect,
LPDIRECTDRAWSURFACE lpDDSrcSurface,
LPRECT lpSrcRect,
DDBltFlags dwFlags,
LPDDBLTFX lpDDBltFx
) override;
HRESULT BltFast(DWORD dwX, DWORD dwY, LPDIRECTDRAWSURFACE lpDDSrcSurface, LPRECT lpSrcRect, DDBltFastFlags dwTrans)
override;
HRESULT Flip(LPDIRECTDRAWSURFACE lpDDSurfaceTargetOverride, DDFlipFlags dwFlags) override;
HRESULT GetAttachedSurface(LPDDSCAPS lpDDSCaps, LPDIRECTDRAWSURFACE* lplpDDAttachedSurface) override;
HRESULT GetCaps(LPDDSCAPS lpDDSCaps) override;
HRESULT GetDC(HDC* lphDC) override;
HRESULT GetOverlayPosition(LPLONG lplX, LPLONG lplY) override;
HRESULT GetPalette(LPDIRECTDRAWPALETTE* lplpDDPalette) override;
HRESULT GetPixelFormat(LPDDPIXELFORMAT lpDDPixelFormat) override;
HRESULT GetSurfaceDesc(LPDDSURFACEDESC lpDDSurfaceDesc) override;
HRESULT IsLost() override;
HRESULT Lock(LPRECT lpDestRect, LPDDSURFACEDESC lpDDSurfaceDesc, DDLockFlags dwFlags, HANDLE hEvent) override;
HRESULT ReleaseDC(HDC hDC) override;
HRESULT Restore() override;
HRESULT SetClipper(LPDIRECTDRAWCLIPPER lpDDClipper) override;
HRESULT SetColorKey(DDColorKeyFlags dwFlags, LPDDCOLORKEY lpDDColorKey) override;
HRESULT SetPalette(LPDIRECTDRAWPALETTE lpDDPalette) override;
HRESULT Unlock(LPVOID lpSurfaceData) override;
private:
SDL_Texture* texture = nullptr;
};

View File

@ -0,0 +1,25 @@
#pragma once
#include <SDL3/SDL.h>
#define LOG_CATEGORY_MINIWIN (SDL_LOG_CATEGORY_CUSTOM)
#define MINIWIN_TRACE(FUNCTION, MSG, ...) \
do { \
SDL_LogTrace(LOG_CATEGORY_MINIWIN, FUNCTION); \
}
#define MINIWIN_ERROR(MSG) \
do { \
SDL_LogError(LOG_CATEGORY_MINIWIN, "%s:%s", __func__, MSG); \
} while (0)
static SDL_FRect ConvertRect(const RECT* r)
{
SDL_FRect sdlRect;
sdlRect.x = r->left;
sdlRect.y = r->top;
sdlRect.w = r->right - r->left;
sdlRect.h = r->bottom - r->top;
return sdlRect;
}

View File

@ -1,7 +1,6 @@
#include "miniwin.h"
#include <SDL3/SDL.h>
#include <utility>
#include <vector>
ULONG IUnknown::AddRef()

View File

@ -1 +0,0 @@
#include "miniwin_d3d.h"

View File

@ -1,5 +1,7 @@
#include "miniwin_d3drm.h"
#include "miniwin_ddsurface_p.h"
#include <SDL3/SDL.h>
#include <assert.h>

View File

@ -0,0 +1,15 @@
#include "miniwin_ddclipper_p.h"
#include "miniwin_ddraw_p.h"
DirectDrawClipperImpl::DirectDrawClipperImpl(DirectDrawImpl* lpDD)
{
}
DirectDrawClipperImpl::~DirectDrawClipperImpl()
{
}
HRESULT DirectDrawClipperImpl::SetHWnd(DWORD unnamedParam1, HWND hWnd)
{
return DD_OK;
}

View File

@ -0,0 +1,21 @@
#include "miniwin_ddpalette_p.h"
#include "miniwin_ddraw.h"
DirectDrawPaletteImpl::DirectDrawPaletteImpl(LPPALETTEENTRY lpColorTable)
{
}
HRESULT DirectDrawPaletteImpl::GetCaps(LPDWORD lpdwCaps)
{
return DD_OK;
}
HRESULT DirectDrawPaletteImpl::GetEntries(DWORD dwFlags, DWORD dwBase, DWORD dwNumEntries, LPPALETTEENTRY lpEntries)
{
return DD_OK;
}
HRESULT DirectDrawPaletteImpl::SetEntries(DWORD dwFlags, DWORD dwStartingEntry, DWORD dwCount, LPPALETTEENTRY lpEntries)
{
return DD_OK;
}

View File

@ -1,6 +1,10 @@
#include "miniwin_ddraw.h"
#include "miniwin_d3d.h"
#include "miniwin_ddclipper_p.h"
#include "miniwin_ddpalette_p.h"
#include "miniwin_ddraw_p.h"
#include "miniwin_ddsurface_p.h"
#include "miniwin_p.h"
#include <SDL3/SDL.h>
#include <assert.h>
@ -10,360 +14,96 @@
SDL_Renderer* renderer;
static SDL_FRect ConvertRect(const RECT* r)
HRESULT DirectDrawImpl::QueryInterface(const GUID& riid, void** ppvObject)
{
SDL_FRect sdlRect;
sdlRect.x = r->left;
sdlRect.y = r->top;
sdlRect.w = r->right - r->left;
sdlRect.h = r->bottom - r->top;
return sdlRect;
if (SDL_memcmp(&riid, &IID_IDirectDraw2, sizeof(GUID)) == 0) {
this->IUnknown::AddRef();
*ppvObject = static_cast<IDirectDraw2*>(this);
return S_OK;
}
if (SDL_memcmp(&riid, &IID_IDirect3D2, sizeof(GUID)) == 0) {
this->IUnknown::AddRef();
*ppvObject = static_cast<IDirect3D2*>(this);
return S_OK;
}
SDL_LogError(LOG_CATEGORY_MINIWIN, "DirectDrawImpl does not implement guid");
return E_NOINTERFACE;
}
struct DirectDrawSurfaceImpl : public IDirectDrawSurface3 {
DirectDrawSurfaceImpl() {}
DirectDrawSurfaceImpl(int width, int height)
{
texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGB565, SDL_TEXTUREACCESS_STREAMING, width, height);
if (!texture) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to create texture: %s", SDL_GetError());
}
}
// IDirectDraw interface
HRESULT DirectDrawImpl::CreateClipper(DWORD dwFlags, LPDIRECTDRAWCLIPPER* lplpDDClipper, IUnknown* pUnkOuter)
{
*lplpDDClipper = static_cast<IDirectDrawClipper*>(new DirectDrawClipperImpl(this));
~DirectDrawSurfaceImpl() override
{
if (texture) {
SDL_DestroyTexture(texture);
}
}
// IUnknown interface
HRESULT QueryInterface(const GUID& riid, void** ppvObject) override
{
if (SDL_memcmp(&riid, &IID_IDirectDrawSurface3, sizeof(GUID)) == 0) {
this->IUnknown::AddRef();
*ppvObject = static_cast<IDirectDrawSurface3*>(this);
return S_OK;
}
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "DirectDrawImpl does not implement guid");
return E_NOINTERFACE;
}
// IDirectDrawSurface interface
HRESULT AddAttachedSurface(LPDIRECTDRAWSURFACE lpDDSAttachedSurface) override { return DD_OK; }
HRESULT Blt(
LPRECT lpDestRect,
LPDIRECTDRAWSURFACE lpDDSrcSurface,
LPRECT lpSrcRect,
DDBltFlags dwFlags,
LPDDBLTFX lpDDBltFx
) override
{
if (!renderer) {
return DDERR_GENERIC;
}
SDL_FRect srcRect = ConvertRect(lpSrcRect);
SDL_FRect dstRect = ConvertRect(lpDestRect);
SDL_RenderTexture(renderer, static_cast<DirectDrawSurfaceImpl*>(lpDDSrcSurface)->texture, &srcRect, &dstRect);
SDL_RenderPresent(renderer);
return DD_OK;
}
HRESULT BltFast(DWORD dwX, DWORD dwY, LPDIRECTDRAWSURFACE lpDDSrcSurface, LPRECT lpSrcRect, DDBltFastFlags dwTrans)
override
{
if (!renderer) {
return DDERR_GENERIC;
}
SDL_FRect dstRect = {
(float) dwX,
(float) dwY,
(float) (lpSrcRect->right - lpSrcRect->left),
(float) (lpSrcRect->bottom - lpSrcRect->top)
};
SDL_FRect srcRect = ConvertRect(lpSrcRect);
SDL_RenderTexture(renderer, static_cast<DirectDrawSurfaceImpl*>(lpDDSrcSurface)->texture, &srcRect, &dstRect);
SDL_RenderPresent(renderer);
return DD_OK;
}
HRESULT Flip(LPDIRECTDRAWSURFACE lpDDSurfaceTargetOverride, DDFlipFlags dwFlags) override
{
if (!renderer || !texture) {
return DDERR_GENERIC;
}
float width, height;
SDL_GetTextureSize(texture, &width, &height);
SDL_FRect rect{0, 0, width, height};
SDL_RenderTexture(renderer, texture, &rect, &rect);
SDL_RenderPresent(renderer);
return DD_OK;
}
HRESULT GetAttachedSurface(LPDDSCAPS lpDDSCaps, LPDIRECTDRAWSURFACE* lplpDDAttachedSurface) override
{
if ((lpDDSCaps->dwCaps & DDSCAPS_BACKBUFFER) != DDSCAPS_BACKBUFFER) {
return DDERR_INVALIDPARAMS;
}
*lplpDDAttachedSurface = static_cast<IDirectDrawSurface*>(this);
return DD_OK;
}
HRESULT GetCaps(LPDDSCAPS lpDDSCaps) override { return DD_OK; }
HRESULT GetDC(HDC* lphDC) override { return DD_OK; }
HRESULT GetOverlayPosition(LPLONG lplX, LPLONG lplY) override { return DD_OK; }
HRESULT GetPalette(LPDIRECTDRAWPALETTE* lplpDDPalette) override { return DDERR_GENERIC; }
HRESULT GetPixelFormat(LPDDPIXELFORMAT lpDDPixelFormat) override
{
memset(lpDDPixelFormat, 0, sizeof(*lpDDPixelFormat));
lpDDPixelFormat->dwFlags = DDPF_RGB;
return DD_OK;
}
HRESULT GetSurfaceDesc(LPDDSURFACEDESC lpDDSurfaceDesc) override
{
if (!texture) {
return DDERR_GENERIC;
}
const SDL_PixelFormatDetails* format = SDL_GetPixelFormatDetails(texture->format);
lpDDSurfaceDesc->ddpfPixelFormat.dwFlags = DDPF_RGB;
lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount = (format->bits_per_pixel == 8) ? 8 : 16;
lpDDSurfaceDesc->ddpfPixelFormat.dwRBitMask = format->Rmask;
lpDDSurfaceDesc->ddpfPixelFormat.dwGBitMask = format->Gmask;
lpDDSurfaceDesc->ddpfPixelFormat.dwBBitMask = format->Bmask;
return DD_OK;
}
HRESULT IsLost() override { return DD_OK; }
HRESULT Lock(LPRECT lpDestRect, LPDDSURFACEDESC lpDDSurfaceDesc, DDLockFlags dwFlags, HANDLE hEvent) override
{
if (!lpDDSurfaceDesc) {
return DDERR_INVALIDPARAMS;
}
if (!texture) {
return DDERR_GENERIC;
}
return DD_OK;
}
int pitch = 0;
void* pixels = nullptr;
if (SDL_LockTexture(texture, (SDL_Rect*) lpDestRect, &pixels, &pitch) < 0) {
return DDERR_GENERIC;
}
HRESULT DirectDrawImpl::CreatePalette(
DDPixelCaps dwFlags,
LPPALETTEENTRY lpColorTable,
LPDIRECTDRAWPALETTE* lplpDDPalette,
IUnknown* pUnkOuter
)
{
*lplpDDPalette = static_cast<LPDIRECTDRAWPALETTE>(new DirectDrawPaletteImpl(lpColorTable));
return DD_OK;
}
lpDDSurfaceDesc->lpSurface = pixels;
lpDDSurfaceDesc->lPitch = pitch;
const SDL_PixelFormatDetails* format = SDL_GetPixelFormatDetails(texture->format);
lpDDSurfaceDesc->ddpfPixelFormat.dwFlags = DDPF_RGB;
lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount = (format->bits_per_pixel == 8) ? 8 : 16;
lpDDSurfaceDesc->ddpfPixelFormat.dwRBitMask = format->Rmask;
lpDDSurfaceDesc->ddpfPixelFormat.dwGBitMask = format->Gmask;
lpDDSurfaceDesc->ddpfPixelFormat.dwBBitMask = format->Bmask;
return DD_OK;
}
HRESULT ReleaseDC(HDC hDC) override { return DD_OK; }
HRESULT Restore() override { return DD_OK; }
HRESULT SetClipper(LPDIRECTDRAWCLIPPER lpDDClipper) override { return DD_OK; }
HRESULT SetColorKey(DDColorKeyFlags dwFlags, LPDDCOLORKEY lpDDColorKey) override { return DD_OK; }
HRESULT SetPalette(LPDIRECTDRAWPALETTE lpDDPalette) override { return DD_OK; }
HRESULT Unlock(LPVOID lpSurfaceData) override
{
if (texture) {
SDL_UnlockTexture(texture);
HRESULT DirectDrawImpl::CreateSurface(
LPDDSURFACEDESC lpDDSurfaceDesc,
LPDIRECTDRAWSURFACE* lplpDDSurface,
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<IDirectDrawSurface*>(new DirectDrawSurfaceImpl);
return DD_OK;
}
return DDERR_GENERIC;
}
private:
SDL_Texture* texture = nullptr;
};
struct DirectDrawClipperImpl : public IDirectDrawClipper {
// IDirectDrawClipper interface
HRESULT SetHWnd(DWORD unnamedParam1, HWND hWnd) override { return DD_OK; }
};
struct DirectDrawPaletteImpl : public IDirectDrawPalette {
HRESULT GetCaps(LPDWORD lpdwCaps) override { return DD_OK; }
HRESULT GetEntries(DWORD dwFlags, DWORD dwBase, DWORD dwNumEntries, LPPALETTEENTRY lpEntries) override
{
return DD_OK;
}
HRESULT SetEntries(DWORD dwFlags, DWORD dwStartingEntry, DWORD dwCount, LPPALETTEENTRY lpEntries) override
{
return DD_OK;
}
};
struct DirectDrawImpl : public IDirectDraw2, public IDirect3D2 {
// IUnknown interface
HRESULT QueryInterface(const GUID& riid, void** ppvObject) override
{
if (SDL_memcmp(&riid, &IID_IDirectDraw2, sizeof(GUID)) == 0) {
this->IUnknown::AddRef();
*ppvObject = static_cast<IDirectDraw2*>(this);
return S_OK;
}
if (SDL_memcmp(&riid, &IID_IDirect3D2, sizeof(GUID)) == 0) {
this->IUnknown::AddRef();
*ppvObject = static_cast<IDirect3D2*>(this);
return S_OK;
}
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "DirectDrawImpl does not implement guid");
return E_NOINTERFACE;
}
// IDirecdtDraw interface
HRESULT CreateClipper(DWORD dwFlags, LPDIRECTDRAWCLIPPER* lplpDDClipper, IUnknown* pUnkOuter) override
{
*lplpDDClipper = static_cast<IDirectDrawClipper*>(new DirectDrawClipperImpl);
return DD_OK;
}
HRESULT CreatePalette(
DDPixelCaps dwFlags,
LPPALETTEENTRY lpColorTable,
LPDIRECTDRAWPALETTE* lplpDDPalette,
IUnknown* pUnkOuter
) override
{
*lplpDDPalette = static_cast<LPDIRECTDRAWPALETTE>(new DirectDrawPaletteImpl);
return DD_OK;
}
HRESULT CreateSurface(LPDDSURFACEDESC lpDDSurfaceDesc, LPDIRECTDRAWSURFACE* lplpDDSurface, IUnknown* pUnkOuter)
override
{
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) {
if ((lpDDSurfaceDesc->dwFlags & DDSD_BACKBUFFERCOUNT) == DDSD_BACKBUFFERCOUNT) {
SDL_Log("Todo: Switch to %d buffering", lpDDSurfaceDesc->dwBackBufferCount);
}
int width, height;
SDL_GetRenderOutputSize(renderer, &width, &height);
*lplpDDSurface = static_cast<IDirectDrawSurface*>(new DirectDrawSurfaceImpl(width, height));
return DD_OK;
}
if ((lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_OFFSCREENPLAIN) == DDSCAPS_OFFSCREENPLAIN) {
SDL_Log("DDSCAPS_OFFSCREENPLAIN"); // 2D surfaces?
}
if ((lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) == DDSCAPS_SYSTEMMEMORY) {
SDL_Log("DDSCAPS_SYSTEMMEMORY"); // Software rendering?
}
if ((lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_TEXTURE) == DDSCAPS_TEXTURE) {
SDL_Log("DDSCAPS_TEXTURE"); // Texture for use in 3D
}
if ((lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_3DDEVICE) == DDSCAPS_3DDEVICE) {
SDL_Log("DDSCAPS_3DDEVICE"); // back buffer
}
if ((lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY) == DDSCAPS_VIDEOMEMORY) {
SDL_Log("DDSCAPS_VIDEOMEMORY"); // front / back buffer
if ((lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) == DDSCAPS_PRIMARYSURFACE) {
if ((lpDDSurfaceDesc->dwFlags & DDSD_BACKBUFFERCOUNT) == DDSD_BACKBUFFERCOUNT) {
SDL_Log("Todo: Switch to %d buffering", lpDDSurfaceDesc->dwBackBufferCount);
}
int width, height;
SDL_GetRenderOutputSize(renderer, &width, &height);
*lplpDDSurface = static_cast<IDirectDrawSurface*>(new DirectDrawSurfaceImpl(width, height));
return DD_OK;
}
if ((lpDDSurfaceDesc->dwFlags & DDSD_PIXELFORMAT) == DDSD_PIXELFORMAT) {
if ((lpDDSurfaceDesc->ddpfPixelFormat.dwFlags & DDPF_RGB) == DDPF_RGB) {
SDL_Log("DDPF_RGB"); // Use dwRGBBitCount to choose the texture format
}
if ((lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_OFFSCREENPLAIN) == DDSCAPS_OFFSCREENPLAIN) {
SDL_Log("DDSCAPS_OFFSCREENPLAIN"); // 2D surfaces?
}
if ((lpDDSurfaceDesc->dwFlags & (DDSD_WIDTH | DDSD_HEIGHT)) != (DDSD_WIDTH | DDSD_HEIGHT)) {
return DDERR_INVALIDPARAMS;
if ((lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) == DDSCAPS_SYSTEMMEMORY) {
SDL_Log("DDSCAPS_SYSTEMMEMORY"); // Software rendering?
}
if ((lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_TEXTURE) == DDSCAPS_TEXTURE) {
SDL_Log("DDSCAPS_TEXTURE"); // Texture for use in 3D
}
if ((lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_3DDEVICE) == DDSCAPS_3DDEVICE) {
SDL_Log("DDSCAPS_3DDEVICE"); // back buffer
}
if ((lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY) == DDSCAPS_VIDEOMEMORY) {
SDL_Log("DDSCAPS_VIDEOMEMORY"); // front / back buffer
}
int width = lpDDSurfaceDesc->dwWidth;
int height = lpDDSurfaceDesc->dwHeight;
*lplpDDSurface = static_cast<IDirectDrawSurface*>(new DirectDrawSurfaceImpl(width, height));
return DD_OK;
}
HRESULT EnumDisplayModes(
DWORD dwFlags,
LPDDSURFACEDESC lpDDSurfaceDesc,
LPVOID lpContext,
LPDDENUMMODESCALLBACK lpEnumModesCallback
) override;
HRESULT FlipToGDISurface() override { return DD_OK; }
HRESULT GetCaps(LPDDCAPS lpDDDriverCaps, LPDDCAPS lpDDHELCaps) override;
HRESULT GetDisplayMode(LPDDSURFACEDESC lpDDSurfaceDesc) override
{
SDL_DisplayID displayID = SDL_GetPrimaryDisplay();
if (!displayID) {
return DDERR_GENERIC;
if ((lpDDSurfaceDesc->dwFlags & DDSD_PIXELFORMAT) == DDSD_PIXELFORMAT) {
if ((lpDDSurfaceDesc->ddpfPixelFormat.dwFlags & DDPF_RGB) == DDPF_RGB) {
SDL_Log("DDPF_RGB"); // Use dwRGBBitCount to choose the texture format
}
const SDL_DisplayMode* mode = SDL_GetCurrentDisplayMode(displayID);
if (!mode) {
return DDERR_GENERIC;
}
const SDL_PixelFormatDetails* format = SDL_GetPixelFormatDetails(mode->format);
lpDDSurfaceDesc->dwFlags = DDSD_WIDTH | DDSD_HEIGHT;
lpDDSurfaceDesc->dwWidth = mode->w;
lpDDSurfaceDesc->dwHeight = mode->h;
lpDDSurfaceDesc->ddpfPixelFormat.dwFlags = DDPF_RGB;
lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount = (format->bits_per_pixel == 8) ? 8 : 16;
lpDDSurfaceDesc->ddpfPixelFormat.dwRBitMask = format->Rmask;
lpDDSurfaceDesc->ddpfPixelFormat.dwGBitMask = format->Gmask;
lpDDSurfaceDesc->ddpfPixelFormat.dwBBitMask = format->Bmask;
return DD_OK;
}
HRESULT RestoreDisplayMode() override { return DD_OK; }
HRESULT SetCooperativeLevel(HWND hWnd, DDSCLFlags dwFlags) override
{
if (hWnd) {
renderer = SDL_CreateRenderer(hWnd, NULL);
}
return DD_OK;
}
HRESULT SetDisplayMode(DWORD dwWidth, DWORD dwHeight, DWORD dwBPP) override { return DD_OK; }
// IDirect3D2 interface
HRESULT CreateDevice(const GUID& guid, void* pBackBuffer, IDirect3DDevice2** ppDirect3DDevice) override
{
*ppDirect3DDevice = new IDirect3DDevice2;
return DD_OK;
}
HRESULT EnumDevices(LPD3DENUMDEVICESCALLBACK cb, void* ctx) override;
};
HRESULT DirectDrawImpl::EnumDevices(LPD3DENUMDEVICESCALLBACK cb, void* ctx)
{
if (!cb) {
if ((lpDDSurfaceDesc->dwFlags & (DDSD_WIDTH | DDSD_HEIGHT)) != (DDSD_WIDTH | DDSD_HEIGHT)) {
return DDERR_INVALIDPARAMS;
}
int numDrivers = SDL_GetNumRenderDrivers();
if (numDrivers <= 0) {
return DDERR_GENERIC;
}
const char* deviceDesc = "SDL3-backed renderer";
char* deviceDescDup = SDL_strdup(deviceDesc);
for (int i = 0; i < numDrivers; ++i) {
const char* deviceName = SDL_GetRenderDriver(i);
if (!deviceName) {
return DDERR_GENERIC;
}
GUID deviceGuid = {0x682656F3, 0x0000, 0x0000, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, (uint8_t) i}};
D3DDEVICEDESC halDesc = {};
halDesc.dcmColorModel = D3DCOLORMODEL::RGB;
halDesc.dwFlags = D3DDD_DEVICEZBUFFERBITDEPTH;
halDesc.dwDeviceZBufferBitDepth = DDBD_8 | DDBD_16 | DDBD_24 | DDBD_32;
halDesc.dwDeviceRenderBitDepth = DDBD_8 | DDBD_16;
halDesc.dpcTriCaps.dwTextureCaps = D3DPTEXTURECAPS_PERSPECTIVE;
halDesc.dpcTriCaps.dwShadeCaps = D3DPSHADECAPS_ALPHAFLATBLEND;
halDesc.dpcTriCaps.dwTextureFilterCaps = D3DPTFILTERCAPS_LINEAR;
char* deviceNameDup = SDL_strdup(deviceName);
cb(&deviceGuid, deviceNameDup, deviceDescDup, &halDesc, &halDesc, ctx);
SDL_free(deviceNameDup);
}
SDL_free(deviceDescDup);
return S_OK;
int width = lpDDSurfaceDesc->dwWidth;
int height = lpDDSurfaceDesc->dwHeight;
*lplpDDSurface = static_cast<IDirectDrawSurface*>(new DirectDrawSurfaceImpl(width, height));
return DD_OK;
}
HRESULT DirectDrawImpl::EnumDisplayModes(
@ -417,25 +157,137 @@ HRESULT DirectDrawImpl::EnumDisplayModes(
return status;
}
HRESULT DirectDrawImpl::FlipToGDISurface()
{
return DD_OK;
}
HRESULT DirectDrawImpl::GetCaps(LPDDCAPS lpDDDriverCaps, LPDDCAPS lpDDHELCaps)
{
if (lpDDDriverCaps) {
memset(lpDDDriverCaps, 0, sizeof(DDCAPS));
lpDDDriverCaps->dwSize = sizeof(DDCAPS);
lpDDDriverCaps->dwCaps2 = DDCAPS2_CERTIFIED; // Required to enable lighting
if (lpDDDriverCaps->dwSize >= sizeof(DDCAPS)) {
lpDDDriverCaps->dwCaps2 = DDCAPS2_CERTIFIED; // Required to enable lighting
}
}
if (lpDDHELCaps) {
memset(lpDDHELCaps, 0, sizeof(DDCAPS));
lpDDHELCaps->dwSize = sizeof(DDCAPS);
lpDDHELCaps->dwCaps2 = DDCAPS2_CERTIFIED; // Required to enable lighting
if (lpDDDriverCaps->dwSize >= sizeof(DDCAPS)) {
lpDDDriverCaps->dwCaps2 = DDCAPS2_CERTIFIED; // Required to enable lighting
}
}
return S_OK;
}
HRESULT DirectDrawImpl::EnumDevices(LPD3DENUMDEVICESCALLBACK cb, void* ctx)
{
if (!cb) {
return DDERR_INVALIDPARAMS;
}
int numDrivers = SDL_GetNumRenderDrivers();
if (numDrivers <= 0) {
return DDERR_GENERIC;
}
const char* deviceDesc = "SDL3 SDL_Renderer";
for (int i = 0; i < numDrivers; ++i) {
const char* deviceName = SDL_GetRenderDriver(i);
if (!deviceName) {
return DDERR_GENERIC;
}
GUID deviceGuid = {0x682656F3, 0x0000, 0x0000, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, (uint8_t) i}};
D3DDEVICEDESC halDesc = {};
halDesc.dcmColorModel = D3DCOLORMODEL::RGB;
halDesc.dwFlags = D3DDD_DEVICEZBUFFERBITDEPTH;
halDesc.dwDeviceZBufferBitDepth = DDBD_8 | DDBD_16 | DDBD_24 | DDBD_32;
halDesc.dwDeviceRenderBitDepth = DDBD_8 | DDBD_16;
halDesc.dpcTriCaps.dwTextureCaps = D3DPTEXTURECAPS_PERSPECTIVE;
halDesc.dpcTriCaps.dwShadeCaps = D3DPSHADECAPS_ALPHAFLATBLEND;
halDesc.dpcTriCaps.dwTextureFilterCaps = D3DPTFILTERCAPS_LINEAR;
char* deviceNameDup = SDL_strdup(deviceName);
char* deviceDescDup = SDL_strdup(deviceDesc);
cb(&deviceGuid, deviceNameDup, deviceDescDup, &halDesc, &halDesc, ctx);
SDL_free(deviceDescDup);
SDL_free(deviceNameDup);
}
return S_OK;
}
HRESULT DirectDrawImpl::GetDisplayMode(LPDDSURFACEDESC lpDDSurfaceDesc)
{
SDL_DisplayID displayID = SDL_GetPrimaryDisplay();
if (!displayID) {
return DDERR_GENERIC;
}
const SDL_DisplayMode* mode = SDL_GetCurrentDisplayMode(displayID);
if (!mode) {
return DDERR_GENERIC;
}
const SDL_PixelFormatDetails* format = SDL_GetPixelFormatDetails(mode->format);
lpDDSurfaceDesc->dwFlags = DDSD_WIDTH | DDSD_HEIGHT;
lpDDSurfaceDesc->dwWidth = mode->w;
lpDDSurfaceDesc->dwHeight = mode->h;
lpDDSurfaceDesc->ddpfPixelFormat.dwFlags = DDPF_RGB;
lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount = (format->bits_per_pixel == 8) ? 8 : 16;
lpDDSurfaceDesc->ddpfPixelFormat.dwRBitMask = format->Rmask;
lpDDSurfaceDesc->ddpfPixelFormat.dwGBitMask = format->Gmask;
lpDDSurfaceDesc->ddpfPixelFormat.dwBBitMask = format->Bmask;
return DD_OK;
}
HRESULT DirectDrawImpl::RestoreDisplayMode()
{
return DD_OK;
}
HRESULT DirectDrawImpl::SetCooperativeLevel(HWND hWnd, DDSCLFlags dwFlags)
{
if (hWnd) {
bool fullscreen;
if ((dwFlags & DDSCL_NORMAL) == DDSCL_NORMAL) {
fullscreen = false;
}
else if ((dwFlags & DDSCL_FULLSCREEN) == DDSCL_FULLSCREEN) {
fullscreen = true;
}
else {
return DDERR_INVALIDPARAMS;
}
if (!SDL_SetWindowFullscreen(hWnd, fullscreen)) {
return DDERR_GENERIC;
}
renderer = SDL_CreateRenderer(hWnd, NULL);
}
return DD_OK;
}
HRESULT DirectDrawImpl::SetDisplayMode(DWORD dwWidth, DWORD dwHeight, DWORD dwBPP)
{
return DD_OK;
}
// IDirect3D2 interface
HRESULT DirectDrawImpl::CreateDevice(const GUID& guid, void* pBackBuffer, IDirect3DDevice2** ppDirect3DDevice)
{
*ppDirect3DDevice = new IDirect3DDevice2;
return DD_OK;
}
HRESULT DirectDrawCreate(LPGUID lpGuid, LPDIRECTDRAW* lplpDD, IUnknown* pUnkOuter)
{
if (lpGuid) {
MINIWIN_ERROR("Specifying a DirectDraw driver is not implemented");
}
if (!lplpDD) {
return DDERR_INVALIDPARAMS;
}
@ -451,8 +303,10 @@ HRESULT DirectDrawEnumerate(LPDDENUMCALLBACKA cb, void* context)
for (int i = 0; i < numDrivers; ++i) {
const char* driverName = SDL_GetVideoDriver(i);
if (!cb(NULL, (LPSTR) driverName, NULL, context)) {
char* driverNameDup = SDL_strdup(driverName);
BOOL callback_result = cb(NULL, driverNameDup, NULL, context);
SDL_free(driverNameDup);
if (!callback_result) {
return DDERR_GENERIC;
}
}

View File

@ -0,0 +1,216 @@
#include "miniwin_ddraw_p.h"
#include "miniwin_ddsurface_p.h"
#include "miniwin_p.h"
#include <assert.h>
DirectDrawSurfaceImpl::DirectDrawSurfaceImpl()
{
}
DirectDrawSurfaceImpl::DirectDrawSurfaceImpl(int width, int height)
{
texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGB565, SDL_TEXTUREACCESS_STREAMING, width, height);
if (!texture) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to create texture: %s", SDL_GetError());
}
}
DirectDrawSurfaceImpl::~DirectDrawSurfaceImpl()
{
if (texture) {
SDL_DestroyTexture(texture);
}
}
// IUnknown interface
HRESULT DirectDrawSurfaceImpl::QueryInterface(const GUID& riid, void** ppvObject)
{
if (SDL_memcmp(&riid, &IID_IDirectDrawSurface3, sizeof(GUID)) == 0) {
this->IUnknown::AddRef();
*ppvObject = static_cast<IDirectDrawSurface3*>(this);
return S_OK;
}
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "DirectDrawImpl does not implement guid");
return E_NOINTERFACE;
}
// IDirectDrawSurface interface
HRESULT DirectDrawSurfaceImpl::AddAttachedSurface(LPDIRECTDRAWSURFACE lpDDSAttachedSurface)
{
return DD_OK;
}
HRESULT DirectDrawSurfaceImpl::Blt(
LPRECT lpDestRect,
LPDIRECTDRAWSURFACE lpDDSrcSurface,
LPRECT lpSrcRect,
DDBltFlags dwFlags,
LPDDBLTFX lpDDBltFx
)
{
if (!renderer) {
return DDERR_GENERIC;
}
SDL_FRect srcRect = ConvertRect(lpSrcRect);
SDL_FRect dstRect = ConvertRect(lpDestRect);
SDL_RenderTexture(renderer, static_cast<DirectDrawSurfaceImpl*>(lpDDSrcSurface)->texture, &srcRect, &dstRect);
SDL_RenderPresent(renderer);
return DD_OK;
}
HRESULT DirectDrawSurfaceImpl::BltFast(
DWORD dwX,
DWORD dwY,
LPDIRECTDRAWSURFACE lpDDSrcSurface,
LPRECT lpSrcRect,
DDBltFastFlags dwTrans
)
{
if (!renderer) {
return DDERR_GENERIC;
}
SDL_FRect dstRect = {
(float) dwX,
(float) dwY,
(float) (lpSrcRect->right - lpSrcRect->left),
(float) (lpSrcRect->bottom - lpSrcRect->top)
};
SDL_FRect srcRect = ConvertRect(lpSrcRect);
SDL_RenderTexture(renderer, static_cast<DirectDrawSurfaceImpl*>(lpDDSrcSurface)->texture, &srcRect, &dstRect);
SDL_RenderPresent(renderer);
return DD_OK;
}
HRESULT DirectDrawSurfaceImpl::Flip(LPDIRECTDRAWSURFACE lpDDSurfaceTargetOverride, DDFlipFlags dwFlags)
{
if (!renderer || !texture) {
return DDERR_GENERIC;
}
float width, height;
SDL_GetTextureSize(texture, &width, &height);
SDL_FRect rect{0, 0, width, height};
SDL_RenderTexture(renderer, texture, &rect, &rect);
SDL_RenderPresent(renderer);
return DD_OK;
}
HRESULT DirectDrawSurfaceImpl::GetAttachedSurface(LPDDSCAPS lpDDSCaps, LPDIRECTDRAWSURFACE* lplpDDAttachedSurface)
{
if ((lpDDSCaps->dwCaps & DDSCAPS_BACKBUFFER) != DDSCAPS_BACKBUFFER) {
return DDERR_INVALIDPARAMS;
}
*lplpDDAttachedSurface = static_cast<IDirectDrawSurface*>(this);
return DD_OK;
}
HRESULT DirectDrawSurfaceImpl::GetCaps(LPDDSCAPS lpDDSCaps)
{
return DD_OK;
}
HRESULT DirectDrawSurfaceImpl::GetDC(HDC* lphDC)
{
return DD_OK;
}
HRESULT DirectDrawSurfaceImpl::GetOverlayPosition(LPLONG lplX, LPLONG lplY)
{
return DD_OK;
}
HRESULT DirectDrawSurfaceImpl::GetPalette(LPDIRECTDRAWPALETTE* lplpDDPalette)
{
assert(false && "unimplemented");
return DDERR_GENERIC;
}
HRESULT DirectDrawSurfaceImpl::GetPixelFormat(LPDDPIXELFORMAT lpDDPixelFormat)
{
memset(lpDDPixelFormat, 0, sizeof(*lpDDPixelFormat));
lpDDPixelFormat->dwFlags = DDPF_RGB;
return DD_OK;
}
HRESULT DirectDrawSurfaceImpl::GetSurfaceDesc(LPDDSURFACEDESC lpDDSurfaceDesc)
{
if (!texture) {
return DDERR_GENERIC;
}
const SDL_PixelFormatDetails* format = SDL_GetPixelFormatDetails(texture->format);
lpDDSurfaceDesc->ddpfPixelFormat.dwFlags = DDPF_RGB;
lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount = (format->bits_per_pixel == 8) ? 8 : 16;
lpDDSurfaceDesc->ddpfPixelFormat.dwRBitMask = format->Rmask;
lpDDSurfaceDesc->ddpfPixelFormat.dwGBitMask = format->Gmask;
lpDDSurfaceDesc->ddpfPixelFormat.dwBBitMask = format->Bmask;
return DD_OK;
}
HRESULT DirectDrawSurfaceImpl::IsLost()
{
return DD_OK;
}
HRESULT DirectDrawSurfaceImpl::Lock(
LPRECT lpDestRect,
LPDDSURFACEDESC lpDDSurfaceDesc,
DDLockFlags dwFlags,
HANDLE hEvent
)
{
if (!lpDDSurfaceDesc) {
return DDERR_INVALIDPARAMS;
}
if (!texture) {
return DDERR_GENERIC;
}
int pitch = 0;
void* pixels = nullptr;
if (SDL_LockTexture(texture, (SDL_Rect*) lpDestRect, &pixels, &pitch) < 0) {
return DDERR_GENERIC;
}
lpDDSurfaceDesc->lpSurface = pixels;
lpDDSurfaceDesc->lPitch = pitch;
const SDL_PixelFormatDetails* format = SDL_GetPixelFormatDetails(texture->format);
lpDDSurfaceDesc->ddpfPixelFormat.dwFlags = DDPF_RGB;
lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount = (format->bits_per_pixel == 8) ? 8 : 16;
lpDDSurfaceDesc->ddpfPixelFormat.dwRBitMask = format->Rmask;
lpDDSurfaceDesc->ddpfPixelFormat.dwGBitMask = format->Gmask;
lpDDSurfaceDesc->ddpfPixelFormat.dwBBitMask = format->Bmask;
return DD_OK;
}
HRESULT DirectDrawSurfaceImpl::ReleaseDC(HDC hDC)
{
return DD_OK;
}
HRESULT DirectDrawSurfaceImpl::Restore()
{
return DD_OK;
}
HRESULT DirectDrawSurfaceImpl::SetClipper(LPDIRECTDRAWCLIPPER lpDDClipper)
{
return DD_OK;
}
HRESULT DirectDrawSurfaceImpl::SetColorKey(DDColorKeyFlags dwFlags, LPDDCOLORKEY lpDDColorKey)
{
return DD_OK;
}
HRESULT DirectDrawSurfaceImpl::SetPalette(LPDIRECTDRAWPALETTE lpDDPalette)
{
return DD_OK;
}
HRESULT DirectDrawSurfaceImpl::Unlock(LPVOID lpSurfaceData)
{
if (!texture) {
return DDERR_GENERIC;
}
SDL_UnlockTexture(texture);
return DD_OK;
}