Add WebGL support to Emscripten

This commit is contained in:
Christian Semmler 2025-06-28 10:58:01 -07:00
parent 02dd261ca9
commit e23cae6d27
No known key found for this signature in database
GPG Key ID: 086DAA1360BEEE5C
7 changed files with 61 additions and 28 deletions

View File

@ -4,7 +4,7 @@ project(isle LANGUAGES CXX C VERSION 0.1)
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 -sPTHREAD_POOL_SIZE_STRICT=0 -sFORCE_FILESYSTEM=1 -sWASMFS=1 -sEXIT_RUNTIME=1) 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)
set(SDL_PTHREADS ON CACHE BOOL "Enable SDL pthreads" FORCE) set(SDL_PTHREADS ON CACHE BOOL "Enable SDL pthreads" FORCE)
endif() endif()

View File

@ -42,14 +42,20 @@ else()
message(STATUS "🧩 OpenGL 1.x support not enabled — needs OpenGL and GLEW") message(STATUS "🧩 OpenGL 1.x support not enabled — needs OpenGL and GLEW")
endif() endif()
find_library(OPENGL_ES2_LIBRARY NAMES GLESv2) if(EMSCRIPTEN)
if(OPENGL_ES2_LIBRARY) message(STATUS "Found OpenGL: enabling OpenGL ES 2.x renderer for Emscripten")
message(STATUS "Found OpenGL: enabling OpenGL ES 2.x renderer")
target_sources(miniwin PRIVATE src/d3drm/backends/opengles2/renderer.cpp) target_sources(miniwin PRIVATE src/d3drm/backends/opengles2/renderer.cpp)
target_compile_definitions(miniwin PRIVATE USE_OPENGLES2) target_compile_definitions(miniwin PRIVATE USE_OPENGLES2)
target_link_libraries(miniwin PRIVATE OpenGL::GL)
else() else()
message(STATUS "🧩 OpenGL ES 2.x support not enabled") find_library(OPENGL_ES2_LIBRARY NAMES GLESv2)
if(OPENGL_ES2_LIBRARY)
message(STATUS "Found OpenGL: enabling OpenGL ES 2.x renderer")
target_sources(miniwin PRIVATE src/d3drm/backends/opengles2/renderer.cpp)
target_compile_definitions(miniwin PRIVATE USE_OPENGLES2)
target_link_libraries(miniwin PRIVATE OpenGL::GL)
else()
message(STATUS "🧩 OpenGL ES 2.x support not enabled")
endif()
endif() endif()
if(WIN32) if(WIN32)

View File

@ -177,6 +177,24 @@ Direct3DRMRenderer* OpenGLES2Renderer::Create(DWORD width, DWORD height)
return new OpenGLES2Renderer(width, height, context, shaderProgram); return new OpenGLES2Renderer(width, height, context, shaderProgram);
} }
void OpenGLES2Desc::GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc)
{
halDesc->dcmColorModel = D3DCOLORMODEL::RGB;
halDesc->dwFlags = D3DDD_DEVICEZBUFFERBITDEPTH;
halDesc->dwDeviceZBufferBitDepth = DDBD_16;
helDesc->dwDeviceRenderBitDepth = DDBD_32;
halDesc->dpcTriCaps.dwTextureCaps = D3DPTEXTURECAPS_PERSPECTIVE;
halDesc->dpcTriCaps.dwShadeCaps = D3DPSHADECAPS_ALPHAFLATBLEND;
halDesc->dpcTriCaps.dwTextureFilterCaps = D3DPTFILTERCAPS_LINEAR;
memset(helDesc, 0, sizeof(D3DDEVICEDESC));
}
const char* OpenGLES2Desc::GetName()
{
return "OpenGL ES 2.0 HAL";
}
OpenGLES2Renderer::OpenGLES2Renderer(DWORD width, DWORD height, SDL_GLContext context, GLuint shaderProgram) OpenGLES2Renderer::OpenGLES2Renderer(DWORD width, DWORD height, SDL_GLContext context, GLuint shaderProgram)
: m_context(context), m_shaderProgram(shaderProgram) : m_context(context), m_shaderProgram(shaderProgram)
{ {
@ -409,9 +427,8 @@ Uint32 OpenGLES2Renderer::GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* mesh
void OpenGLES2Renderer::GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc) void OpenGLES2Renderer::GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc)
{ {
halDesc->dcmColorModel = D3DCOLORMODEL::RGB; OpenGLES2Desc::GetDesc(halDesc, helDesc);
halDesc->dwFlags = D3DDD_DEVICEZBUFFERBITDEPTH;
halDesc->dwDeviceZBufferBitDepth = DDBD_16;
const char* extensions = (const char*) glGetString(GL_EXTENSIONS); const char* extensions = (const char*) glGetString(GL_EXTENSIONS);
if (extensions) { if (extensions) {
if (strstr(extensions, "GL_OES_depth24")) { if (strstr(extensions, "GL_OES_depth24")) {
@ -421,17 +438,11 @@ void OpenGLES2Renderer::GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc)
halDesc->dwDeviceZBufferBitDepth |= DDBD_32; halDesc->dwDeviceZBufferBitDepth |= DDBD_32;
} }
} }
helDesc->dwDeviceRenderBitDepth = DDBD_32;
halDesc->dpcTriCaps.dwTextureCaps = D3DPTEXTURECAPS_PERSPECTIVE;
halDesc->dpcTriCaps.dwShadeCaps = D3DPSHADECAPS_ALPHAFLATBLEND;
halDesc->dpcTriCaps.dwTextureFilterCaps = D3DPTFILTERCAPS_LINEAR;
memset(helDesc, 0, sizeof(D3DDEVICEDESC));
} }
const char* OpenGLES2Renderer::GetName() const char* OpenGLES2Renderer::GetName()
{ {
return "OpenGL ES 2.0 HAL"; return OpenGLES2Desc::GetName();
} }
HRESULT OpenGLES2Renderer::BeginFrame() HRESULT OpenGLES2Renderer::BeginFrame()

View File

@ -207,12 +207,12 @@ HRESULT DirectDrawImpl::GetCaps(LPDDCAPS lpDDDriverCaps, LPDDCAPS lpDDHELCaps)
return S_OK; return S_OK;
} }
void EnumDevice(LPD3DENUMDEVICESCALLBACK cb, void* ctx, Direct3DRMRenderer* device, GUID deviceGuid) void EnumDevice(LPD3DENUMDEVICESCALLBACK cb, void* ctx, Direct3DRMDesc* desc, GUID deviceGuid)
{ {
D3DDEVICEDESC halDesc = {}; D3DDEVICEDESC halDesc = {};
D3DDEVICEDESC helDesc = {}; D3DDEVICEDESC helDesc = {};
device->GetDesc(&halDesc, &helDesc); desc->GetDesc(&halDesc, &helDesc);
char* deviceNameDup = SDL_strdup(device->GetName()); char* deviceNameDup = SDL_strdup(desc->GetName());
char* deviceDescDup = SDL_strdup("Miniwin driver"); char* deviceDescDup = SDL_strdup("Miniwin driver");
cb(&deviceGuid, deviceNameDup, deviceDescDup, &halDesc, &helDesc, ctx); cb(&deviceGuid, deviceNameDup, deviceDescDup, &halDesc, &helDesc, ctx);
SDL_free(deviceDescDup); SDL_free(deviceDescDup);

View File

@ -26,7 +26,14 @@ struct Plane {
float d; float d;
}; };
class Direct3DRMRenderer : public IDirect3DDevice2 { class Direct3DRMDesc {
public:
virtual ~Direct3DRMDesc() {}
virtual void GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc) = 0;
virtual const char* GetName() = 0;
};
class Direct3DRMRenderer : public IDirect3DDevice2, public Direct3DRMDesc {
public: public:
virtual void PushLights(const SceneLight* vertices, size_t count) = 0; virtual void PushLights(const SceneLight* vertices, size_t count) = 0;
virtual void SetProjection(const D3DRMMATRIX4D& projection, D3DVALUE front, D3DVALUE back) = 0; virtual void SetProjection(const D3DRMMATRIX4D& projection, D3DVALUE front, D3DVALUE back) = 0;
@ -37,8 +44,6 @@ class Direct3DRMRenderer : public IDirect3DDevice2 {
int GetHeight() { return m_height; } int GetHeight() { return m_height; }
int GetVirtualWidth() { return m_virtualWidth; } int GetVirtualWidth() { return m_virtualWidth; }
int GetVirtualHeight() { return m_virtualHeight; } int GetVirtualHeight() { return m_virtualHeight; }
virtual void GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc) = 0;
virtual const char* GetName() = 0;
virtual HRESULT BeginFrame() = 0; virtual HRESULT BeginFrame() = 0;
virtual void EnableTransparency() = 0; virtual void EnableTransparency() = 0;
virtual void SubmitDraw( virtual void SubmitDraw(

View File

@ -30,7 +30,13 @@ struct GLES2MeshCacheEntry {
GLuint ibo; GLuint ibo;
}; };
class OpenGLES2Renderer : public Direct3DRMRenderer { class OpenGLES2Desc : public Direct3DRMDesc {
public:
void GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc) override;
const char* GetName() override;
};
class OpenGLES2Renderer : public Direct3DRMRenderer, public OpenGLES2Desc {
public: public:
static Direct3DRMRenderer* Create(DWORD width, DWORD height); static Direct3DRMRenderer* Create(DWORD width, DWORD height);
OpenGLES2Renderer(DWORD width, DWORD height, SDL_GLContext context, GLuint shaderProgram); OpenGLES2Renderer(DWORD width, DWORD height, SDL_GLContext context, GLuint shaderProgram);
@ -77,9 +83,14 @@ 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); #ifdef __EMSCRIPTEN__
if (device) { // We need a static description since creating test windows, context changes etc. are not allowed
EnumDevice(cb, ctx, device, OpenGLES2_GUID); Direct3DRMDesc* desc = new OpenGLES2Desc();
delete device; #else
Direct3DRMDesc* desc = OpenGLES2Renderer::Create(640, 480);
#endif
if (desc) {
EnumDevice(cb, ctx, desc, OpenGLES2_GUID);
delete desc;
} }
} }

View File

@ -56,4 +56,4 @@ HRESULT DirectDrawEnumerate(LPDDENUMCALLBACKA cb, void* context);
HRESULT DirectDrawCreate(LPGUID lpGuid, LPDIRECTDRAW* lplpDD, IUnknown* pUnkOuter); HRESULT DirectDrawCreate(LPGUID lpGuid, LPDIRECTDRAW* lplpDD, IUnknown* pUnkOuter);
void EnumDevice(LPD3DENUMDEVICESCALLBACK cb, void* ctx, Direct3DRMRenderer* device, GUID deviceGuid); void EnumDevice(LPD3DENUMDEVICESCALLBACK cb, void* ctx, Direct3DRMDesc* desc, GUID deviceGuid);