From 11316f5699570d426247c12fe68167894607b1b7 Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Tue, 22 Jul 2025 16:19:35 -0700 Subject: [PATCH] MSAA WIP --- CMakeLists.txt | 2 +- ISLE/isleapp.cpp | 7 ++ ISLE/isleapp.h | 1 + .../legoomni/src/video/legovideomanager.cpp | 3 +- LEGO1/mxdirectx/mxdirect3d.cpp | 12 +- LEGO1/mxdirectx/mxdirect3d.h | 3 +- LEGO1/mxdirectx/mxdirectdraw.cpp | 3 +- LEGO1/mxdirectx/mxdirectdraw.h | 3 +- LEGO1/mxdirectx/mxdirectxinfo.cpp | 17 ++- LEGO1/omni/include/mxvideoparam.h | 6 + LEGO1/omni/src/video/mxvideoparam.cpp | 3 + miniwin/include/miniwin/miniwind3d.h | 8 ++ .../src/d3drm/backends/opengles2/renderer.cpp | 103 ++++++++++++++---- miniwin/src/d3drm/d3drm.cpp | 6 +- miniwin/src/d3drm/d3drmrenderer.cpp | 8 +- miniwin/src/ddraw/ddraw.cpp | 18 ++- miniwin/src/internal/d3drmrenderer.h | 7 +- .../src/internal/d3drmrenderer_opengles2.h | 14 ++- miniwin/src/internal/ddraw_impl.h | 7 +- 19 files changed, 195 insertions(+), 36 deletions(-) create mode 100644 miniwin/include/miniwin/miniwind3d.h diff --git a/CMakeLists.txt b/CMakeLists.txt index f43617c0..8cad4606 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,7 +14,7 @@ endif() if (EMSCRIPTEN) add_compile_options(-pthread) - add_link_options(-sALLOW_MEMORY_GROWTH=1 -sMAXIMUM_MEMORY=2gb -sUSE_PTHREADS=1 -sPROXY_TO_PTHREAD=1 -sOFFSCREENCANVAS_SUPPORT=1 -sPTHREAD_POOL_SIZE_STRICT=0 -sFORCE_FILESYSTEM=1 -sWASMFS=1 -sEXIT_RUNTIME=1) + add_link_options(-sUSE_WEBGL2=1 -sMIN_WEBGL_VERSION=2 -sALLOW_MEMORY_GROWTH=1 -sMAXIMUM_MEMORY=2gb -sUSE_PTHREADS=1 -sPROXY_TO_PTHREAD=1 -sOFFSCREENCANVAS_SUPPORT=1 -sPTHREAD_POOL_SIZE_STRICT=0 -sFORCE_FILESYSTEM=1 -sWASMFS=1 -sEXIT_RUNTIME=1) set(SDL_PTHREADS ON CACHE BOOL "Enable SDL pthreads" FORCE) endif() diff --git a/ISLE/isleapp.cpp b/ISLE/isleapp.cpp index ee440e8f..8dbc895b 100644 --- a/ISLE/isleapp.cpp +++ b/ISLE/isleapp.cpp @@ -179,6 +179,7 @@ IsleApp::IsleApp() m_yRes = 480; m_frameRate = 100.0f; m_exclusiveFullScreen = FALSE; + m_msaaSamples = 0; } // FUNCTION: ISLE 0x4011a0 @@ -912,6 +913,11 @@ MxResult IsleApp::SetupWindow() window = SDL_CreateWindowWithProperties(props); + SDL_SetPointerProperty(SDL_GetWindowProperties(window), ISLE_PROP_WINDOW_CREATE_VIDEO_PARAM, &m_videoParam); + MxVideoParam* p = (MxVideoParam*) + SDL_GetPointerProperty(SDL_GetWindowProperties(window), ISLE_PROP_WINDOW_CREATE_VIDEO_PARAM, nullptr); + SDL_Log("MSAA WINDOW: %p %d", p, (p)->GetMSAASamples()); + if (m_exclusiveFullScreen && m_fullScreen) { SDL_DisplayMode closestMode; SDL_DisplayID displayID = SDL_GetDisplayForWindow(window); @@ -1172,6 +1178,7 @@ bool IsleApp::LoadConfig() } m_frameRate = (1000.0f / iniparser_getdouble(dict, "isle:Frame Delta", m_frameDelta)); m_frameDelta = static_cast(std::round(iniparser_getdouble(dict, "isle:Frame Delta", m_frameDelta))); + m_videoParam.SetMSAASamples(iniparser_getint(dict, "isle:MSAA", m_msaaSamples)); const char* deviceId = iniparser_getstring(dict, "isle:3D Device ID", NULL); if (deviceId != NULL) { diff --git a/ISLE/isleapp.h b/ISLE/isleapp.h index 4a23ea23..bfd0ea0a 100644 --- a/ISLE/isleapp.h +++ b/ISLE/isleapp.h @@ -111,6 +111,7 @@ class IsleApp { MxS32 m_yRes; MxFloat m_frameRate; MxBool m_exclusiveFullScreen; + MxU32 m_msaaSamples; }; extern IsleApp* g_isle; diff --git a/LEGO1/lego/legoomni/src/video/legovideomanager.cpp b/LEGO1/lego/legoomni/src/video/legovideomanager.cpp index 383c6d35..5ba926de 100644 --- a/LEGO1/lego/legoomni/src/video/legovideomanager.cpp +++ b/LEGO1/lego/legoomni/src/video/legovideomanager.cpp @@ -148,7 +148,8 @@ MxResult LegoVideoManager::Create(MxVideoParam& p_videoParam, MxU32 p_frequencyM p_videoParam.GetRect().GetHeight(), bits, paletteEntries, - sizeof(paletteEntries) / sizeof(paletteEntries[0]) + sizeof(paletteEntries) / sizeof(paletteEntries[0]), + p_videoParam.GetMSAASamples() )) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "MxDirect3D::Create failed"); goto done; diff --git a/LEGO1/mxdirectx/mxdirect3d.cpp b/LEGO1/mxdirectx/mxdirect3d.cpp index 7f12d147..4b727ab5 100644 --- a/LEGO1/mxdirectx/mxdirect3d.cpp +++ b/LEGO1/mxdirectx/mxdirect3d.cpp @@ -2,6 +2,7 @@ #include // for SDL_Log #include +#include DECOMP_SIZE_ASSERT(MxDirect3D, 0x894) @@ -40,10 +41,12 @@ BOOL MxDirect3D::Create( int height, int bpp, const PALETTEENTRY* pPaletteEntries, - int paletteEntryCount + int paletteEntryCount, + DWORD msaaSamples ) { BOOL success = FALSE; + IDirect3DMiniwin* miniwind3d = nullptr; assert(m_currentDeviceInfo); if (!MxDirectDraw::Create( @@ -55,7 +58,8 @@ BOOL MxDirect3D::Create( height, bpp, pPaletteEntries, - paletteEntryCount + paletteEntryCount, + msaaSamples )) { goto done; } @@ -64,6 +68,10 @@ BOOL MxDirect3D::Create( goto done; } + if (msaaSamples && m_pDirect3d->QueryInterface(IID_IDirect3DMiniwin, (void**) &miniwind3d) == S_OK) { + miniwind3d->RequestMSAA(msaaSamples); + } + if (!D3DSetMode()) { goto done; } diff --git a/LEGO1/mxdirectx/mxdirect3d.h b/LEGO1/mxdirectx/mxdirect3d.h index b44c72e8..30e05a88 100644 --- a/LEGO1/mxdirectx/mxdirect3d.h +++ b/LEGO1/mxdirectx/mxdirect3d.h @@ -31,7 +31,8 @@ class MxDirect3D : public MxDirectDraw { int height, int bpp, const PALETTEENTRY* pPaletteEntries, - int paletteEntryCount + int paletteEntryCount, + DWORD msaaSamples ) override; // vtable+0x04 void Destroy() override; // vtable+0x08 void DestroyButNotDirectDraw() override; // vtable+0x0c diff --git a/LEGO1/mxdirectx/mxdirectdraw.cpp b/LEGO1/mxdirectx/mxdirectdraw.cpp index 7ccb78c2..2f78cf40 100644 --- a/LEGO1/mxdirectx/mxdirectdraw.cpp +++ b/LEGO1/mxdirectx/mxdirectdraw.cpp @@ -91,7 +91,8 @@ BOOL MxDirectDraw::Create( int height, int bpp, const PALETTEENTRY* pPaletteEntries, - int paletteEntryCount + int paletteEntryCount, + DWORD msaaSamples ) { assert(m_currentDevInfo); diff --git a/LEGO1/mxdirectx/mxdirectdraw.h b/LEGO1/mxdirectx/mxdirectdraw.h index 554de189..380122f1 100644 --- a/LEGO1/mxdirectx/mxdirectdraw.h +++ b/LEGO1/mxdirectx/mxdirectdraw.h @@ -33,7 +33,8 @@ class MxDirectDraw { int height, int bpp, const PALETTEENTRY* pPaletteEntries, - int paletteEntryCount + int paletteEntryCount, + DWORD msaaSamples ); // vtable+0x04 virtual void Destroy(); // vtable+0x08 virtual void DestroyButNotDirectDraw(); // vtable+0x0c diff --git a/LEGO1/mxdirectx/mxdirectxinfo.cpp b/LEGO1/mxdirectx/mxdirectxinfo.cpp index 3451b8fc..21182cc4 100644 --- a/LEGO1/mxdirectx/mxdirectxinfo.cpp +++ b/LEGO1/mxdirectx/mxdirectxinfo.cpp @@ -1,7 +1,10 @@ #include "mxdirectxinfo.h" +#include "mxvideoparam.h" + #include #include +#include #include // for vsprintf DECOMP_SIZE_ASSERT(MxAssignedDevice, 0xe4) @@ -216,12 +219,24 @@ BOOL MxDeviceEnumerate::EnumDirectDrawCallback(LPGUID p_guid, LPSTR p_driverDesc LPDIRECTDRAW lpDD = NULL; MxDriver& newDevice = m_ddInfo.back(); HRESULT result = DirectDrawCreate(newDevice.m_guid, &lpDD, NULL); + IDirect3DMiniwin* miniwind3d = nullptr; if (result != DD_OK) { BuildErrorString("DirectDraw Create failed: %s\n", EnumerateErrorToString(result)); goto done; } + result = lpDD->QueryInterface(IID_IDirect3DMiniwin, (void**) &miniwind3d); + if (result == DD_OK) { + MxVideoParam* videoParam = (MxVideoParam*) SDL_GetPointerProperty( + SDL_GetWindowProperties(reinterpret_cast(m_hWnd)), + ISLE_PROP_WINDOW_CREATE_VIDEO_PARAM, + nullptr + ); + assert(videoParam); + miniwind3d->RequestMSAA(videoParam->GetMSAASamples()); + } + result = lpDD->SetCooperativeLevel(m_hWnd, DDSCL_NORMAL); if (result != DD_OK) { BuildErrorString("SetCooperativeLevel failed: %s\n", EnumerateErrorToString(result)); @@ -243,7 +258,7 @@ BOOL MxDeviceEnumerate::EnumDirectDrawCallback(LPGUID p_guid, LPSTR p_driverDesc goto done; } - result = lpDirect3d2->EnumDevices(DevicesEnumerateCallback, this); + result = lpDirect3d2->EnumDevices(DevicesEnumerateCallback, miniwind3d); if (result != DD_OK) { BuildErrorString("D3D enum devices failed: %s\n", EnumerateErrorToString(result)); diff --git a/LEGO1/omni/include/mxvideoparam.h b/LEGO1/omni/include/mxvideoparam.h index ccc073ab..af2fcddf 100644 --- a/LEGO1/omni/include/mxvideoparam.h +++ b/LEGO1/omni/include/mxvideoparam.h @@ -15,6 +15,8 @@ class MxPalette; +#define ISLE_PROP_WINDOW_CREATE_VIDEO_PARAM "ISLE.window.create.videoParam" + // SIZE 0x24 class MxVideoParam { public: @@ -51,6 +53,9 @@ class MxVideoParam { // FUNCTION: BETA10 0x10141fe0 void SetBackBuffers(MxU32 p_backBuffers) { m_backBuffers = p_backBuffers; } + void SetMSAASamples(MxU32 p_msaaSamples) { m_msaaSamples = p_msaaSamples; } + MxU32 GetMSAASamples() { return m_msaaSamples; } + private: MxRect32 m_rect; // 0x00 MxPalette* m_palette; // 0x10 @@ -58,6 +63,7 @@ class MxVideoParam { MxVideoParamFlags m_flags; // 0x18 int m_unk0x1c; // 0x1c char* m_deviceId; // 0x20 + MxU32 m_msaaSamples; }; #endif // MXVIDEOPARAM_H diff --git a/LEGO1/omni/src/video/mxvideoparam.cpp b/LEGO1/omni/src/video/mxvideoparam.cpp index 9a095c4e..7c029e52 100644 --- a/LEGO1/omni/src/video/mxvideoparam.cpp +++ b/LEGO1/omni/src/video/mxvideoparam.cpp @@ -28,6 +28,7 @@ MxVideoParam::MxVideoParam(MxRect32& p_rect, MxPalette* p_palette, MxULong p_bac m_flags = p_flags; m_unk0x1c = 0; m_deviceId = NULL; + m_msaaSamples = 0; } // FUNCTION: LEGO1 0x100becf0 @@ -41,6 +42,7 @@ MxVideoParam::MxVideoParam(MxVideoParam& p_videoParam) m_unk0x1c = p_videoParam.m_unk0x1c; m_deviceId = NULL; SetDeviceName(p_videoParam.m_deviceId); + m_msaaSamples = p_videoParam.m_msaaSamples; } // FUNCTION: LEGO1 0x100bed50 @@ -82,6 +84,7 @@ MxVideoParam& MxVideoParam::operator=(const MxVideoParam& p_videoParam) m_flags = p_videoParam.m_flags; m_unk0x1c = p_videoParam.m_unk0x1c; SetDeviceName(p_videoParam.m_deviceId); + m_msaaSamples = p_videoParam.m_msaaSamples; return *this; } diff --git a/miniwin/include/miniwin/miniwind3d.h b/miniwin/include/miniwin/miniwind3d.h new file mode 100644 index 00000000..8204af17 --- /dev/null +++ b/miniwin/include/miniwin/miniwind3d.h @@ -0,0 +1,8 @@ +#pragma once + +DEFINE_GUID(IID_IDirect3DMiniwin, 0xf8a97f2d, 0x9b3a, 0x4f1c, 0x9e, 0x8d, 0x6a, 0x5b, 0x4c, 0x3d, 0x2e, 0x1f); + +struct IDirect3DMiniwin : virtual public IUnknown { + virtual HRESULT RequestMSAA(DWORD msaaSamples) = 0; + virtual DWORD GetMSAASamples() const = 0; +}; diff --git a/miniwin/src/d3drm/backends/opengles2/renderer.cpp b/miniwin/src/d3drm/backends/opengles2/renderer.cpp index e1c86a62..0f6f26f2 100644 --- a/miniwin/src/d3drm/backends/opengles2/renderer.cpp +++ b/miniwin/src/d3drm/backends/opengles2/renderer.cpp @@ -1,8 +1,8 @@ #include "d3drmrenderer_opengles2.h" #include "meshutils.h" -#include #include +#include #include #include #include @@ -28,7 +28,7 @@ struct SceneLightGLES2 { float direction[4]; }; -Direct3DRMRenderer* OpenGLES2Renderer::Create(DWORD width, DWORD height) +Direct3DRMRenderer* OpenGLES2Renderer::Create(DWORD width, DWORD height, DWORD msaaSamples) { // We have to reset the attributes here after having enumerated the // OpenGL ES 2.0 renderer, or else SDL gets very confused by SDL_GL_DEPTH_SIZE @@ -37,9 +37,14 @@ Direct3DRMRenderer* OpenGLES2Renderer::Create(DWORD width, DWORD height) // But ResetAttributes resets it to 16. SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); + if (msaaSamples > 1) { + SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1); + SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, msaaSamples); + } + if (!DDWindow) { SDL_Log("No window handler"); return nullptr; @@ -168,7 +173,7 @@ Direct3DRMRenderer* OpenGLES2Renderer::Create(DWORD width, DWORD height) glDeleteShader(vs); glDeleteShader(fs); - return new OpenGLES2Renderer(width, height, context, shaderProgram); + return new OpenGLES2Renderer(width, height, msaaSamples, context, shaderProgram); } GLES2MeshCacheEntry GLES2UploadMesh(const MeshGroup& meshGroup, bool forceUV = false) @@ -278,14 +283,25 @@ bool UploadTexture(SDL_Surface* source, GLuint& outTexId, bool isUI) return true; } -OpenGLES2Renderer::OpenGLES2Renderer(DWORD width, DWORD height, SDL_GLContext context, GLuint shaderProgram) +OpenGLES2Renderer::OpenGLES2Renderer( + DWORD width, + DWORD height, + DWORD msaaSamples, + SDL_GLContext context, + GLuint shaderProgram +) : m_context(context), m_shaderProgram(shaderProgram) { glGenFramebuffers(1, &m_fbo); - glBindFramebuffer(GL_FRAMEBUFFER, m_fbo); + + if (msaaSamples > 1) { + glGenFramebuffers(1, &m_msaaFbo); + } m_virtualWidth = width; m_virtualHeight = height; + m_requestedMsaaSamples = msaaSamples; + SDL_Log("Requested MSAA %d", m_requestedMsaaSamples); ViewportTransform viewportTransform = {1.0f, 0.0f, 0.0f}; Resize(width, height, viewportTransform); @@ -488,7 +504,7 @@ HRESULT OpenGLES2Renderer::BeginFrame() SDL_GL_MakeCurrent(DDWindow, m_context); m_dirty = true; - glBindFramebuffer(GL_FRAMEBUFFER, m_fbo); + glBindFramebuffer(GL_FRAMEBUFFER, m_useMsaa ? m_msaaFbo : m_fbo); glEnable(GL_CULL_FACE); glDisable(GL_BLEND); @@ -610,6 +626,52 @@ void OpenGLES2Renderer::Resize(int width, int height, const ViewportTransform& v } m_renderedImage = SDL_CreateSurface(m_width, m_height, SDL_PIXELFORMAT_RGBA32); + if (m_colorTarget) { + glDeleteTextures(1, &m_colorTarget); + } + if (m_depthTarget) { + glDeleteRenderbuffers(1, &m_depthTarget); + } + if (m_msaaColorRbo) { + glDeleteRenderbuffers(1, &m_msaaColorRbo); + } + if (m_msaaDepthRbo) { + glDeleteRenderbuffers(1, &m_msaaDepthRbo); + } + m_colorTarget = m_depthTarget = m_msaaColorRbo = m_msaaDepthRbo = 0; + + GLint samples; + glGetIntegerv(GL_SAMPLES, &samples); + m_useMsaa = samples > 1; + + if (m_useMsaa) { + glBindFramebuffer(GL_FRAMEBUFFER, m_msaaFbo); + + glGenRenderbuffers(1, &m_msaaColorRbo); + glBindRenderbuffer(GL_RENDERBUFFER, m_msaaColorRbo); + glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, GL_RGBA8, width, height); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_msaaColorRbo); + + glGenRenderbuffers(1, &m_msaaDepthRbo); + glBindRenderbuffer(GL_RENDERBUFFER, m_msaaDepthRbo); + glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, GL_DEPTH24_STENCIL8, width, height); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_msaaDepthRbo); + + if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { + SDL_Log("MSAA Framebuffer is not complete! Disabling MSAA."); + m_useMsaa = false; + } + } + + if (m_useMsaa) { + GLint max_samples; + glGetIntegerv(GL_MAX_SAMPLES, &max_samples); + SDL_Log("MSAA: ON! samples %d max samples %d", samples, max_samples); + } + else { + SDL_Log("MSAA: OFF! %d %d", samples, m_requestedMsaaSamples); + } + glBindFramebuffer(GL_FRAMEBUFFER, m_fbo); // Create color texture @@ -625,16 +687,7 @@ void OpenGLES2Renderer::Resize(int width, int height, const ViewportTransform& v // Create depth renderbuffer glGenRenderbuffers(1, &m_depthTarget); glBindRenderbuffer(GL_RENDERBUFFER, m_depthTarget); - - if (SDL_GL_ExtensionSupported("GL_OES_depth24")) { - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24_OES, width, height); - } - else if (SDL_GL_ExtensionSupported("GL_OES_depth32")) { - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT32_OES, width, height); - } - else { - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height); - } + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, width, height); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depthTarget); glViewport(0, 0, m_width, m_height); @@ -645,7 +698,7 @@ void OpenGLES2Renderer::Clear(float r, float g, float b) SDL_GL_MakeCurrent(DDWindow, m_context); m_dirty = true; - glBindFramebuffer(GL_FRAMEBUFFER, m_fbo); + glBindFramebuffer(GL_FRAMEBUFFER, m_useMsaa ? m_msaaFbo : m_fbo); glEnable(GL_DEPTH_TEST); glDepthMask(GL_TRUE); @@ -660,6 +713,12 @@ void OpenGLES2Renderer::Flip() return; } + if (m_useMsaa) { + glBindFramebuffer(GL_READ_FRAMEBUFFER, m_msaaFbo); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_fbo); + glBlitFramebuffer(0, 0, m_width, m_height, 0, 0, m_width, m_height, GL_COLOR_BUFFER_BIT, GL_NEAREST); + } + glBindFramebuffer(GL_FRAMEBUFFER, 0); glDisable(GL_DEPTH_TEST); @@ -722,7 +781,7 @@ void OpenGLES2Renderer::Draw2DImage(Uint32 textureId, const SDL_Rect& srcRect, c SDL_GL_MakeCurrent(DDWindow, m_context); m_dirty = true; - glBindFramebuffer(GL_FRAMEBUFFER, m_fbo); + glBindFramebuffer(GL_FRAMEBUFFER, m_useMsaa ? m_msaaFbo : m_fbo); glDisable(GL_DEPTH_TEST); glDepthMask(GL_FALSE); @@ -809,6 +868,12 @@ void OpenGLES2Renderer::Download(SDL_Surface* target) { glFinish(); + if (m_useMsaa) { + glBindFramebuffer(GL_READ_FRAMEBUFFER, m_msaaFbo); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_fbo); + glBlitFramebuffer(0, 0, m_width, m_height, 0, 0, m_width, m_height, GL_COLOR_BUFFER_BIT, GL_NEAREST); + } + glBindFramebuffer(GL_FRAMEBUFFER, m_fbo); glReadPixels(0, 0, m_width, m_height, GL_RGBA, GL_UNSIGNED_BYTE, m_renderedImage->pixels); diff --git a/miniwin/src/d3drm/d3drm.cpp b/miniwin/src/d3drm/d3drm.cpp index 7328d21c..9340b9d5 100644 --- a/miniwin/src/d3drm/d3drm.cpp +++ b/miniwin/src/d3drm/d3drm.cpp @@ -132,7 +132,11 @@ HRESULT Direct3DRMImpl::CreateDeviceFromSurface( DDSDesc.dwSize = sizeof(DDSURFACEDESC); surface->GetSurfaceDesc(&DDSDesc); - DDRenderer = CreateDirect3DRMRenderer(DDSDesc, guid); + IDirect3DMiniwin* miniwind3d = nullptr; + miniwind3d->QueryInterface(IID_IDirect3DMiniwin, (void**) &miniwind3d); + SDL_assert(miniwind3d); + + DDRenderer = CreateDirect3DRMRenderer(miniwind3d, DDSDesc, guid); if (!DDRenderer) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Device GUID not recognized"); return E_NOINTERFACE; diff --git a/miniwin/src/d3drm/d3drmrenderer.cpp b/miniwin/src/d3drm/d3drmrenderer.cpp index ca9b5541..23eb671c 100644 --- a/miniwin/src/d3drm/d3drmrenderer.cpp +++ b/miniwin/src/d3drm/d3drmrenderer.cpp @@ -18,7 +18,11 @@ #include "d3drmrenderer_software.h" #endif -Direct3DRMRenderer* CreateDirect3DRMRenderer(const DDSURFACEDESC& DDSDesc, const GUID* guid) +Direct3DRMRenderer* CreateDirect3DRMRenderer( + const IDirect3DMiniwin* d3d, + const DDSURFACEDESC& DDSDesc, + const GUID* guid +) { #ifdef USE_SDL_GPU if (SDL_memcmp(guid, &SDL3_GPU_GUID, sizeof(GUID)) == 0) { @@ -32,7 +36,7 @@ Direct3DRMRenderer* CreateDirect3DRMRenderer(const DDSURFACEDESC& DDSDesc, const #endif #ifdef USE_OPENGLES2 if (SDL_memcmp(guid, &OpenGLES2_GUID, sizeof(GUID)) == 0) { - return OpenGLES2Renderer::Create(DDSDesc.dwWidth, DDSDesc.dwHeight); + return OpenGLES2Renderer::Create(DDSDesc.dwWidth, DDSDesc.dwHeight, d3d->GetMSAASamples()); } #endif #ifdef USE_OPENGL1 diff --git a/miniwin/src/ddraw/ddraw.cpp b/miniwin/src/ddraw/ddraw.cpp index 264ceeb1..edfae063 100644 --- a/miniwin/src/ddraw/ddraw.cpp +++ b/miniwin/src/ddraw/ddraw.cpp @@ -29,6 +29,11 @@ HRESULT DirectDrawImpl::QueryInterface(const GUID& riid, void** ppvObject) *ppvObject = static_cast(this); return S_OK; } + if (SDL_memcmp(&riid, &IID_IDirect3DMiniwin, sizeof(GUID)) == 0) { + this->IUnknown::AddRef(); + *ppvObject = static_cast(this); + return S_OK; + } MINIWIN_NOT_IMPLEMENTED(); return E_NOINTERFACE; } @@ -317,7 +322,7 @@ HRESULT DirectDrawImpl::CreateDevice( DDSDesc.dwSize = sizeof(DDSURFACEDESC); pBackBuffer->GetSurfaceDesc(&DDSDesc); - DDRenderer = CreateDirect3DRMRenderer(DDSDesc, &guid); + DDRenderer = CreateDirect3DRMRenderer(this, DDSDesc, &guid); if (!DDRenderer) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Device GUID not recognized"); return E_NOINTERFACE; @@ -326,6 +331,17 @@ HRESULT DirectDrawImpl::CreateDevice( return DD_OK; } +HRESULT DirectDrawImpl::RequestMSAA(DWORD msaaSamples) +{ + m_msaaSamples = msaaSamples; + return DD_OK; +} + +DWORD DirectDrawImpl::GetMSAASamples() const +{ + return m_msaaSamples; +} + HRESULT DirectDrawEnumerate(LPDDENUMCALLBACKA cb, void* context) { const char* driverName = SDL_GetCurrentVideoDriver(); diff --git a/miniwin/src/internal/d3drmrenderer.h b/miniwin/src/internal/d3drmrenderer.h index 85b2d1b9..01ba5b64 100644 --- a/miniwin/src/internal/d3drmrenderer.h +++ b/miniwin/src/internal/d3drmrenderer.h @@ -3,6 +3,7 @@ #include "d3drmmesh_impl.h" #include "mathutils.h" #include "miniwin/d3drm.h" +#include "miniwin/miniwind3d.h" #include "miniwin/miniwindevice.h" #include "structs.h" @@ -61,5 +62,9 @@ class Direct3DRMRenderer : public IDirect3DDevice2 { ViewportTransform m_viewportTransform; }; -Direct3DRMRenderer* CreateDirect3DRMRenderer(const DDSURFACEDESC& DDSDesc, const GUID* guid); +Direct3DRMRenderer* CreateDirect3DRMRenderer( + const IDirect3DMiniwin* d3d, + const DDSURFACEDESC& DDSDesc, + const GUID* guid +); void Direct3DRMRenderer_EnumDevices(LPD3DENUMDEVICESCALLBACK cb, void* ctx); diff --git a/miniwin/src/internal/d3drmrenderer_opengles2.h b/miniwin/src/internal/d3drmrenderer_opengles2.h index d4985f32..1a1f62d2 100644 --- a/miniwin/src/internal/d3drmrenderer_opengles2.h +++ b/miniwin/src/internal/d3drmrenderer_opengles2.h @@ -32,8 +32,8 @@ struct GLES2MeshCacheEntry { class OpenGLES2Renderer : public Direct3DRMRenderer { public: - static Direct3DRMRenderer* Create(DWORD width, DWORD height); - OpenGLES2Renderer(DWORD width, DWORD height, SDL_GLContext context, GLuint shaderProgram); + static Direct3DRMRenderer* Create(DWORD width, DWORD height, DWORD msaaSamples); + OpenGLES2Renderer(DWORD width, DWORD height, DWORD msaaSamples, SDL_GLContext context, GLuint shaderProgram); ~OpenGLES2Renderer() override; void PushLights(const SceneLight* lightsArray, size_t count) override; @@ -72,7 +72,12 @@ class OpenGLES2Renderer : public Direct3DRMRenderer { bool m_dirty = false; std::vector m_lights; SDL_GLContext m_context; + uint32_t m_requestedMsaaSamples; + bool m_useMsaa; GLuint m_fbo; + GLuint m_msaaFbo; + GLuint m_msaaColorRbo; + GLuint m_msaaDepthRbo; GLuint m_colorTarget; GLuint m_depthTarget; GLuint m_shaderProgram; @@ -94,7 +99,10 @@ class OpenGLES2Renderer : public Direct3DRMRenderer { inline static void OpenGLES2Renderer_EnumDevice(LPD3DENUMDEVICESCALLBACK cb, void* ctx) { - Direct3DRMRenderer* device = OpenGLES2Renderer::Create(640, 480); + IDirect3DMiniwin* miniwind3d = reinterpret_cast(ctx); + SDL_assert(miniwind3d); + + Direct3DRMRenderer* device = OpenGLES2Renderer::Create(640, 480, miniwind3d->GetMSAASamples()); if (!device) { return; } diff --git a/miniwin/src/internal/ddraw_impl.h b/miniwin/src/internal/ddraw_impl.h index 4adfb4a5..ac4e01a9 100644 --- a/miniwin/src/internal/ddraw_impl.h +++ b/miniwin/src/internal/ddraw_impl.h @@ -4,6 +4,7 @@ #include "framebuffer_impl.h" #include "miniwin/d3d.h" #include "miniwin/ddraw.h" +#include "miniwin/miniwind3d.h" #include @@ -15,7 +16,7 @@ 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 { +struct DirectDrawImpl : public IDirectDraw2, public IDirect3D2, public IDirect3DMiniwin { // IUnknown interface HRESULT QueryInterface(const GUID& riid, void** ppvObject) override; // IDirectDraw interface @@ -45,11 +46,15 @@ struct DirectDrawImpl : public IDirectDraw2, public IDirect3D2 { HRESULT CreateDevice(const GUID& guid, IDirectDrawSurface* pBackBuffer, IDirect3DDevice2** ppDirect3DDevice) override; HRESULT EnumDevices(LPD3DENUMDEVICESCALLBACK cb, void* ctx) override; + // IDirect3DMiniwin interface + HRESULT RequestMSAA(DWORD msaaSamples) override; + DWORD GetMSAASamples() const override; private: FrameBufferImpl* m_frameBuffer; int m_virtualWidth = 0; int m_virtualHeight = 0; + DWORD m_msaaSamples = 0; }; HRESULT DirectDrawEnumerate(LPDDENUMCALLBACKA cb, void* context);