This commit is contained in:
Christian Semmler 2025-07-22 16:19:35 -07:00
parent e86fd71560
commit 11316f5699
No known key found for this signature in database
GPG Key ID: 086DAA1360BEEE5C
19 changed files with 195 additions and 36 deletions

View File

@ -14,7 +14,7 @@ endif()
if (EMSCRIPTEN) if (EMSCRIPTEN)
add_compile_options(-pthread) 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) set(SDL_PTHREADS ON CACHE BOOL "Enable SDL pthreads" FORCE)
endif() endif()

View File

@ -179,6 +179,7 @@ IsleApp::IsleApp()
m_yRes = 480; m_yRes = 480;
m_frameRate = 100.0f; m_frameRate = 100.0f;
m_exclusiveFullScreen = FALSE; m_exclusiveFullScreen = FALSE;
m_msaaSamples = 0;
} }
// FUNCTION: ISLE 0x4011a0 // FUNCTION: ISLE 0x4011a0
@ -912,6 +913,11 @@ MxResult IsleApp::SetupWindow()
window = SDL_CreateWindowWithProperties(props); 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) { if (m_exclusiveFullScreen && m_fullScreen) {
SDL_DisplayMode closestMode; SDL_DisplayMode closestMode;
SDL_DisplayID displayID = SDL_GetDisplayForWindow(window); 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_frameRate = (1000.0f / iniparser_getdouble(dict, "isle:Frame Delta", m_frameDelta));
m_frameDelta = static_cast<int>(std::round(iniparser_getdouble(dict, "isle:Frame Delta", m_frameDelta))); m_frameDelta = static_cast<int>(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); const char* deviceId = iniparser_getstring(dict, "isle:3D Device ID", NULL);
if (deviceId != NULL) { if (deviceId != NULL) {

View File

@ -111,6 +111,7 @@ class IsleApp {
MxS32 m_yRes; MxS32 m_yRes;
MxFloat m_frameRate; MxFloat m_frameRate;
MxBool m_exclusiveFullScreen; MxBool m_exclusiveFullScreen;
MxU32 m_msaaSamples;
}; };
extern IsleApp* g_isle; extern IsleApp* g_isle;

View File

@ -148,7 +148,8 @@ MxResult LegoVideoManager::Create(MxVideoParam& p_videoParam, MxU32 p_frequencyM
p_videoParam.GetRect().GetHeight(), p_videoParam.GetRect().GetHeight(),
bits, bits,
paletteEntries, paletteEntries,
sizeof(paletteEntries) / sizeof(paletteEntries[0]) sizeof(paletteEntries) / sizeof(paletteEntries[0]),
p_videoParam.GetMSAASamples()
)) { )) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "MxDirect3D::Create failed"); SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "MxDirect3D::Create failed");
goto done; goto done;

View File

@ -2,6 +2,7 @@
#include <SDL3/SDL.h> // for SDL_Log #include <SDL3/SDL.h> // for SDL_Log
#include <assert.h> #include <assert.h>
#include <miniwin/miniwind3d.h>
DECOMP_SIZE_ASSERT(MxDirect3D, 0x894) DECOMP_SIZE_ASSERT(MxDirect3D, 0x894)
@ -40,10 +41,12 @@ BOOL MxDirect3D::Create(
int height, int height,
int bpp, int bpp,
const PALETTEENTRY* pPaletteEntries, const PALETTEENTRY* pPaletteEntries,
int paletteEntryCount int paletteEntryCount,
DWORD msaaSamples
) )
{ {
BOOL success = FALSE; BOOL success = FALSE;
IDirect3DMiniwin* miniwind3d = nullptr;
assert(m_currentDeviceInfo); assert(m_currentDeviceInfo);
if (!MxDirectDraw::Create( if (!MxDirectDraw::Create(
@ -55,7 +58,8 @@ BOOL MxDirect3D::Create(
height, height,
bpp, bpp,
pPaletteEntries, pPaletteEntries,
paletteEntryCount paletteEntryCount,
msaaSamples
)) { )) {
goto done; goto done;
} }
@ -64,6 +68,10 @@ BOOL MxDirect3D::Create(
goto done; goto done;
} }
if (msaaSamples && m_pDirect3d->QueryInterface(IID_IDirect3DMiniwin, (void**) &miniwind3d) == S_OK) {
miniwind3d->RequestMSAA(msaaSamples);
}
if (!D3DSetMode()) { if (!D3DSetMode()) {
goto done; goto done;
} }

View File

@ -31,7 +31,8 @@ class MxDirect3D : public MxDirectDraw {
int height, int height,
int bpp, int bpp,
const PALETTEENTRY* pPaletteEntries, const PALETTEENTRY* pPaletteEntries,
int paletteEntryCount int paletteEntryCount,
DWORD msaaSamples
) override; // vtable+0x04 ) override; // vtable+0x04
void Destroy() override; // vtable+0x08 void Destroy() override; // vtable+0x08
void DestroyButNotDirectDraw() override; // vtable+0x0c void DestroyButNotDirectDraw() override; // vtable+0x0c

View File

@ -91,7 +91,8 @@ BOOL MxDirectDraw::Create(
int height, int height,
int bpp, int bpp,
const PALETTEENTRY* pPaletteEntries, const PALETTEENTRY* pPaletteEntries,
int paletteEntryCount int paletteEntryCount,
DWORD msaaSamples
) )
{ {
assert(m_currentDevInfo); assert(m_currentDevInfo);

View File

@ -33,7 +33,8 @@ class MxDirectDraw {
int height, int height,
int bpp, int bpp,
const PALETTEENTRY* pPaletteEntries, const PALETTEENTRY* pPaletteEntries,
int paletteEntryCount int paletteEntryCount,
DWORD msaaSamples
); // vtable+0x04 ); // vtable+0x04
virtual void Destroy(); // vtable+0x08 virtual void Destroy(); // vtable+0x08
virtual void DestroyButNotDirectDraw(); // vtable+0x0c virtual void DestroyButNotDirectDraw(); // vtable+0x0c

View File

@ -1,7 +1,10 @@
#include "mxdirectxinfo.h" #include "mxdirectxinfo.h"
#include "mxvideoparam.h"
#include <SDL3/SDL_log.h> #include <SDL3/SDL_log.h>
#include <assert.h> #include <assert.h>
#include <miniwin/miniwind3d.h>
#include <stdio.h> // for vsprintf #include <stdio.h> // for vsprintf
DECOMP_SIZE_ASSERT(MxAssignedDevice, 0xe4) DECOMP_SIZE_ASSERT(MxAssignedDevice, 0xe4)
@ -216,12 +219,24 @@ BOOL MxDeviceEnumerate::EnumDirectDrawCallback(LPGUID p_guid, LPSTR p_driverDesc
LPDIRECTDRAW lpDD = NULL; LPDIRECTDRAW lpDD = NULL;
MxDriver& newDevice = m_ddInfo.back(); MxDriver& newDevice = m_ddInfo.back();
HRESULT result = DirectDrawCreate(newDevice.m_guid, &lpDD, NULL); HRESULT result = DirectDrawCreate(newDevice.m_guid, &lpDD, NULL);
IDirect3DMiniwin* miniwind3d = nullptr;
if (result != DD_OK) { if (result != DD_OK) {
BuildErrorString("DirectDraw Create failed: %s\n", EnumerateErrorToString(result)); BuildErrorString("DirectDraw Create failed: %s\n", EnumerateErrorToString(result));
goto done; goto done;
} }
result = lpDD->QueryInterface(IID_IDirect3DMiniwin, (void**) &miniwind3d);
if (result == DD_OK) {
MxVideoParam* videoParam = (MxVideoParam*) SDL_GetPointerProperty(
SDL_GetWindowProperties(reinterpret_cast<SDL_Window*>(m_hWnd)),
ISLE_PROP_WINDOW_CREATE_VIDEO_PARAM,
nullptr
);
assert(videoParam);
miniwind3d->RequestMSAA(videoParam->GetMSAASamples());
}
result = lpDD->SetCooperativeLevel(m_hWnd, DDSCL_NORMAL); result = lpDD->SetCooperativeLevel(m_hWnd, DDSCL_NORMAL);
if (result != DD_OK) { if (result != DD_OK) {
BuildErrorString("SetCooperativeLevel failed: %s\n", EnumerateErrorToString(result)); BuildErrorString("SetCooperativeLevel failed: %s\n", EnumerateErrorToString(result));
@ -243,7 +258,7 @@ BOOL MxDeviceEnumerate::EnumDirectDrawCallback(LPGUID p_guid, LPSTR p_driverDesc
goto done; goto done;
} }
result = lpDirect3d2->EnumDevices(DevicesEnumerateCallback, this); result = lpDirect3d2->EnumDevices(DevicesEnumerateCallback, miniwind3d);
if (result != DD_OK) { if (result != DD_OK) {
BuildErrorString("D3D enum devices failed: %s\n", EnumerateErrorToString(result)); BuildErrorString("D3D enum devices failed: %s\n", EnumerateErrorToString(result));

View File

@ -15,6 +15,8 @@
class MxPalette; class MxPalette;
#define ISLE_PROP_WINDOW_CREATE_VIDEO_PARAM "ISLE.window.create.videoParam"
// SIZE 0x24 // SIZE 0x24
class MxVideoParam { class MxVideoParam {
public: public:
@ -51,6 +53,9 @@ class MxVideoParam {
// FUNCTION: BETA10 0x10141fe0 // FUNCTION: BETA10 0x10141fe0
void SetBackBuffers(MxU32 p_backBuffers) { m_backBuffers = p_backBuffers; } void SetBackBuffers(MxU32 p_backBuffers) { m_backBuffers = p_backBuffers; }
void SetMSAASamples(MxU32 p_msaaSamples) { m_msaaSamples = p_msaaSamples; }
MxU32 GetMSAASamples() { return m_msaaSamples; }
private: private:
MxRect32 m_rect; // 0x00 MxRect32 m_rect; // 0x00
MxPalette* m_palette; // 0x10 MxPalette* m_palette; // 0x10
@ -58,6 +63,7 @@ class MxVideoParam {
MxVideoParamFlags m_flags; // 0x18 MxVideoParamFlags m_flags; // 0x18
int m_unk0x1c; // 0x1c int m_unk0x1c; // 0x1c
char* m_deviceId; // 0x20 char* m_deviceId; // 0x20
MxU32 m_msaaSamples;
}; };
#endif // MXVIDEOPARAM_H #endif // MXVIDEOPARAM_H

View File

@ -28,6 +28,7 @@ MxVideoParam::MxVideoParam(MxRect32& p_rect, MxPalette* p_palette, MxULong p_bac
m_flags = p_flags; m_flags = p_flags;
m_unk0x1c = 0; m_unk0x1c = 0;
m_deviceId = NULL; m_deviceId = NULL;
m_msaaSamples = 0;
} }
// FUNCTION: LEGO1 0x100becf0 // FUNCTION: LEGO1 0x100becf0
@ -41,6 +42,7 @@ MxVideoParam::MxVideoParam(MxVideoParam& p_videoParam)
m_unk0x1c = p_videoParam.m_unk0x1c; m_unk0x1c = p_videoParam.m_unk0x1c;
m_deviceId = NULL; m_deviceId = NULL;
SetDeviceName(p_videoParam.m_deviceId); SetDeviceName(p_videoParam.m_deviceId);
m_msaaSamples = p_videoParam.m_msaaSamples;
} }
// FUNCTION: LEGO1 0x100bed50 // FUNCTION: LEGO1 0x100bed50
@ -82,6 +84,7 @@ MxVideoParam& MxVideoParam::operator=(const MxVideoParam& p_videoParam)
m_flags = p_videoParam.m_flags; m_flags = p_videoParam.m_flags;
m_unk0x1c = p_videoParam.m_unk0x1c; m_unk0x1c = p_videoParam.m_unk0x1c;
SetDeviceName(p_videoParam.m_deviceId); SetDeviceName(p_videoParam.m_deviceId);
m_msaaSamples = p_videoParam.m_msaaSamples;
return *this; return *this;
} }

View File

@ -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;
};

View File

@ -1,8 +1,8 @@
#include "d3drmrenderer_opengles2.h" #include "d3drmrenderer_opengles2.h"
#include "meshutils.h" #include "meshutils.h"
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h> #include <GLES2/gl2ext.h>
#include <GLES3/gl3.h>
#include <SDL3/SDL.h> #include <SDL3/SDL.h>
#include <algorithm> #include <algorithm>
#include <string> #include <string>
@ -28,7 +28,7 @@ struct SceneLightGLES2 {
float direction[4]; 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 // 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 // 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. // But ResetAttributes resets it to 16.
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); 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_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); 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) { if (!DDWindow) {
SDL_Log("No window handler"); SDL_Log("No window handler");
return nullptr; return nullptr;
@ -168,7 +173,7 @@ Direct3DRMRenderer* OpenGLES2Renderer::Create(DWORD width, DWORD height)
glDeleteShader(vs); glDeleteShader(vs);
glDeleteShader(fs); 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) GLES2MeshCacheEntry GLES2UploadMesh(const MeshGroup& meshGroup, bool forceUV = false)
@ -278,14 +283,25 @@ bool UploadTexture(SDL_Surface* source, GLuint& outTexId, bool isUI)
return true; 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) : m_context(context), m_shaderProgram(shaderProgram)
{ {
glGenFramebuffers(1, &m_fbo); glGenFramebuffers(1, &m_fbo);
glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
if (msaaSamples > 1) {
glGenFramebuffers(1, &m_msaaFbo);
}
m_virtualWidth = width; m_virtualWidth = width;
m_virtualHeight = height; m_virtualHeight = height;
m_requestedMsaaSamples = msaaSamples;
SDL_Log("Requested MSAA %d", m_requestedMsaaSamples);
ViewportTransform viewportTransform = {1.0f, 0.0f, 0.0f}; ViewportTransform viewportTransform = {1.0f, 0.0f, 0.0f};
Resize(width, height, viewportTransform); Resize(width, height, viewportTransform);
@ -488,7 +504,7 @@ HRESULT OpenGLES2Renderer::BeginFrame()
SDL_GL_MakeCurrent(DDWindow, m_context); SDL_GL_MakeCurrent(DDWindow, m_context);
m_dirty = true; m_dirty = true;
glBindFramebuffer(GL_FRAMEBUFFER, m_fbo); glBindFramebuffer(GL_FRAMEBUFFER, m_useMsaa ? m_msaaFbo : m_fbo);
glEnable(GL_CULL_FACE); glEnable(GL_CULL_FACE);
glDisable(GL_BLEND); 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); 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); glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
// Create color texture // Create color texture
@ -625,16 +687,7 @@ void OpenGLES2Renderer::Resize(int width, int height, const ViewportTransform& v
// Create depth renderbuffer // Create depth renderbuffer
glGenRenderbuffers(1, &m_depthTarget); glGenRenderbuffers(1, &m_depthTarget);
glBindRenderbuffer(GL_RENDERBUFFER, m_depthTarget); glBindRenderbuffer(GL_RENDERBUFFER, m_depthTarget);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, width, height);
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);
}
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depthTarget); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depthTarget);
glViewport(0, 0, m_width, m_height); 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); SDL_GL_MakeCurrent(DDWindow, m_context);
m_dirty = true; m_dirty = true;
glBindFramebuffer(GL_FRAMEBUFFER, m_fbo); glBindFramebuffer(GL_FRAMEBUFFER, m_useMsaa ? m_msaaFbo : m_fbo);
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE); glDepthMask(GL_TRUE);
@ -660,6 +713,12 @@ void OpenGLES2Renderer::Flip()
return; 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); glBindFramebuffer(GL_FRAMEBUFFER, 0);
glDisable(GL_DEPTH_TEST); glDisable(GL_DEPTH_TEST);
@ -722,7 +781,7 @@ void OpenGLES2Renderer::Draw2DImage(Uint32 textureId, const SDL_Rect& srcRect, c
SDL_GL_MakeCurrent(DDWindow, m_context); SDL_GL_MakeCurrent(DDWindow, m_context);
m_dirty = true; m_dirty = true;
glBindFramebuffer(GL_FRAMEBUFFER, m_fbo); glBindFramebuffer(GL_FRAMEBUFFER, m_useMsaa ? m_msaaFbo : m_fbo);
glDisable(GL_DEPTH_TEST); glDisable(GL_DEPTH_TEST);
glDepthMask(GL_FALSE); glDepthMask(GL_FALSE);
@ -809,6 +868,12 @@ void OpenGLES2Renderer::Download(SDL_Surface* target)
{ {
glFinish(); 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); glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
glReadPixels(0, 0, m_width, m_height, GL_RGBA, GL_UNSIGNED_BYTE, m_renderedImage->pixels); glReadPixels(0, 0, m_width, m_height, GL_RGBA, GL_UNSIGNED_BYTE, m_renderedImage->pixels);

View File

@ -132,7 +132,11 @@ HRESULT Direct3DRMImpl::CreateDeviceFromSurface(
DDSDesc.dwSize = sizeof(DDSURFACEDESC); DDSDesc.dwSize = sizeof(DDSURFACEDESC);
surface->GetSurfaceDesc(&DDSDesc); 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) { if (!DDRenderer) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Device GUID not recognized"); SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Device GUID not recognized");
return E_NOINTERFACE; return E_NOINTERFACE;

View File

@ -18,7 +18,11 @@
#include "d3drmrenderer_software.h" #include "d3drmrenderer_software.h"
#endif #endif
Direct3DRMRenderer* CreateDirect3DRMRenderer(const DDSURFACEDESC& DDSDesc, const GUID* guid) Direct3DRMRenderer* CreateDirect3DRMRenderer(
const IDirect3DMiniwin* d3d,
const DDSURFACEDESC& DDSDesc,
const GUID* guid
)
{ {
#ifdef USE_SDL_GPU #ifdef USE_SDL_GPU
if (SDL_memcmp(guid, &SDL3_GPU_GUID, sizeof(GUID)) == 0) { if (SDL_memcmp(guid, &SDL3_GPU_GUID, sizeof(GUID)) == 0) {
@ -32,7 +36,7 @@ Direct3DRMRenderer* CreateDirect3DRMRenderer(const DDSURFACEDESC& DDSDesc, const
#endif #endif
#ifdef USE_OPENGLES2 #ifdef USE_OPENGLES2
if (SDL_memcmp(guid, &OpenGLES2_GUID, sizeof(GUID)) == 0) { 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 #endif
#ifdef USE_OPENGL1 #ifdef USE_OPENGL1

View File

@ -29,6 +29,11 @@ HRESULT DirectDrawImpl::QueryInterface(const GUID& riid, void** ppvObject)
*ppvObject = static_cast<IDirect3D2*>(this); *ppvObject = static_cast<IDirect3D2*>(this);
return S_OK; return S_OK;
} }
if (SDL_memcmp(&riid, &IID_IDirect3DMiniwin, sizeof(GUID)) == 0) {
this->IUnknown::AddRef();
*ppvObject = static_cast<IDirect3DMiniwin*>(this);
return S_OK;
}
MINIWIN_NOT_IMPLEMENTED(); MINIWIN_NOT_IMPLEMENTED();
return E_NOINTERFACE; return E_NOINTERFACE;
} }
@ -317,7 +322,7 @@ HRESULT DirectDrawImpl::CreateDevice(
DDSDesc.dwSize = sizeof(DDSURFACEDESC); DDSDesc.dwSize = sizeof(DDSURFACEDESC);
pBackBuffer->GetSurfaceDesc(&DDSDesc); pBackBuffer->GetSurfaceDesc(&DDSDesc);
DDRenderer = CreateDirect3DRMRenderer(DDSDesc, &guid); DDRenderer = CreateDirect3DRMRenderer(this, DDSDesc, &guid);
if (!DDRenderer) { if (!DDRenderer) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Device GUID not recognized"); SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Device GUID not recognized");
return E_NOINTERFACE; return E_NOINTERFACE;
@ -326,6 +331,17 @@ HRESULT DirectDrawImpl::CreateDevice(
return DD_OK; 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) HRESULT DirectDrawEnumerate(LPDDENUMCALLBACKA cb, void* context)
{ {
const char* driverName = SDL_GetCurrentVideoDriver(); const char* driverName = SDL_GetCurrentVideoDriver();

View File

@ -3,6 +3,7 @@
#include "d3drmmesh_impl.h" #include "d3drmmesh_impl.h"
#include "mathutils.h" #include "mathutils.h"
#include "miniwin/d3drm.h" #include "miniwin/d3drm.h"
#include "miniwin/miniwind3d.h"
#include "miniwin/miniwindevice.h" #include "miniwin/miniwindevice.h"
#include "structs.h" #include "structs.h"
@ -61,5 +62,9 @@ class Direct3DRMRenderer : public IDirect3DDevice2 {
ViewportTransform m_viewportTransform; 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); void Direct3DRMRenderer_EnumDevices(LPD3DENUMDEVICESCALLBACK cb, void* ctx);

View File

@ -32,8 +32,8 @@ struct GLES2MeshCacheEntry {
class OpenGLES2Renderer : public Direct3DRMRenderer { class OpenGLES2Renderer : public Direct3DRMRenderer {
public: public:
static Direct3DRMRenderer* Create(DWORD width, DWORD height); static Direct3DRMRenderer* Create(DWORD width, DWORD height, DWORD msaaSamples);
OpenGLES2Renderer(DWORD width, DWORD height, SDL_GLContext context, GLuint shaderProgram); OpenGLES2Renderer(DWORD width, DWORD height, DWORD msaaSamples, SDL_GLContext context, GLuint shaderProgram);
~OpenGLES2Renderer() override; ~OpenGLES2Renderer() override;
void PushLights(const SceneLight* lightsArray, size_t count) override; void PushLights(const SceneLight* lightsArray, size_t count) override;
@ -72,7 +72,12 @@ class OpenGLES2Renderer : public Direct3DRMRenderer {
bool m_dirty = false; bool m_dirty = false;
std::vector<SceneLight> m_lights; std::vector<SceneLight> m_lights;
SDL_GLContext m_context; SDL_GLContext m_context;
uint32_t m_requestedMsaaSamples;
bool m_useMsaa;
GLuint m_fbo; GLuint m_fbo;
GLuint m_msaaFbo;
GLuint m_msaaColorRbo;
GLuint m_msaaDepthRbo;
GLuint m_colorTarget; GLuint m_colorTarget;
GLuint m_depthTarget; GLuint m_depthTarget;
GLuint m_shaderProgram; GLuint m_shaderProgram;
@ -94,7 +99,10 @@ class OpenGLES2Renderer : public Direct3DRMRenderer {
inline static void OpenGLES2Renderer_EnumDevice(LPD3DENUMDEVICESCALLBACK cb, void* ctx) inline static void OpenGLES2Renderer_EnumDevice(LPD3DENUMDEVICESCALLBACK cb, void* ctx)
{ {
Direct3DRMRenderer* device = OpenGLES2Renderer::Create(640, 480); IDirect3DMiniwin* miniwind3d = reinterpret_cast<IDirect3DMiniwin*>(ctx);
SDL_assert(miniwind3d);
Direct3DRMRenderer* device = OpenGLES2Renderer::Create(640, 480, miniwind3d->GetMSAASamples());
if (!device) { if (!device) {
return; return;
} }

View File

@ -4,6 +4,7 @@
#include "framebuffer_impl.h" #include "framebuffer_impl.h"
#include "miniwin/d3d.h" #include "miniwin/d3d.h"
#include "miniwin/ddraw.h" #include "miniwin/ddraw.h"
#include "miniwin/miniwind3d.h"
#include <SDL3/SDL.h> #include <SDL3/SDL.h>
@ -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}; 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 // IUnknown interface
HRESULT QueryInterface(const GUID& riid, void** ppvObject) override; HRESULT QueryInterface(const GUID& riid, void** ppvObject) override;
// IDirectDraw interface // IDirectDraw interface
@ -45,11 +46,15 @@ struct DirectDrawImpl : public IDirectDraw2, public IDirect3D2 {
HRESULT CreateDevice(const GUID& guid, IDirectDrawSurface* pBackBuffer, IDirect3DDevice2** ppDirect3DDevice) HRESULT CreateDevice(const GUID& guid, IDirectDrawSurface* pBackBuffer, IDirect3DDevice2** ppDirect3DDevice)
override; override;
HRESULT EnumDevices(LPD3DENUMDEVICESCALLBACK cb, void* ctx) override; HRESULT EnumDevices(LPD3DENUMDEVICESCALLBACK cb, void* ctx) override;
// IDirect3DMiniwin interface
HRESULT RequestMSAA(DWORD msaaSamples) override;
DWORD GetMSAASamples() const override;
private: private:
FrameBufferImpl* m_frameBuffer; FrameBufferImpl* m_frameBuffer;
int m_virtualWidth = 0; int m_virtualWidth = 0;
int m_virtualHeight = 0; int m_virtualHeight = 0;
DWORD m_msaaSamples = 0;
}; };
HRESULT DirectDrawEnumerate(LPDDENUMCALLBACKA cb, void* context); HRESULT DirectDrawEnumerate(LPDDENUMCALLBACKA cb, void* context);