Merge branch 'master' into master

This commit is contained in:
VoxelTek 2025-06-26 11:02:14 +10:00 committed by GitHub
commit 7e1001fb54
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
49 changed files with 1552 additions and 740 deletions

View File

@ -394,6 +394,7 @@ SDL_AppResult SDL_AppEvent(void* appstate, SDL_Event* event)
#endif #endif
switch (event->type) { switch (event->type) {
case SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED:
case SDL_EVENT_MOUSE_MOTION: case SDL_EVENT_MOUSE_MOTION:
case SDL_EVENT_MOUSE_BUTTON_DOWN: case SDL_EVENT_MOUSE_BUTTON_DOWN:
case SDL_EVENT_MOUSE_BUTTON_UP: case SDL_EVENT_MOUSE_BUTTON_UP:
@ -658,6 +659,7 @@ MxResult IsleApp::SetupWindow()
SDL_SetStringProperty(props, SDL_PROP_WINDOW_CREATE_TITLE_STRING, WINDOW_TITLE); SDL_SetStringProperty(props, SDL_PROP_WINDOW_CREATE_TITLE_STRING, WINDOW_TITLE);
#ifdef MINIWIN #ifdef MINIWIN
SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_OPENGL_BOOLEAN, true); SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_OPENGL_BOOLEAN, true);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
#endif #endif
window = SDL_CreateWindowWithProperties(props); window = SDL_CreateWindowWithProperties(props);

View File

@ -83,7 +83,7 @@ LegoTextureInfo* LegoTextureInfo::Create(const char* p_name, LegoTexture* p_text
memset(&desc, 0, sizeof(desc)); memset(&desc, 0, sizeof(desc));
desc.dwSize = sizeof(desc); desc.dwSize = sizeof(desc);
if (textureInfo->m_surface->Lock(NULL, &desc, DDLOCK_SURFACEMEMORYPTR, NULL) != DD_OK) { if (textureInfo->m_surface->Lock(NULL, &desc, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WRITEONLY, NULL) != DD_OK) {
goto done; goto done;
} }
@ -193,7 +193,7 @@ LegoResult LegoTextureInfo::LoadBits(const LegoU8* p_bits)
memset(&desc, 0, sizeof(desc)); memset(&desc, 0, sizeof(desc));
desc.dwSize = sizeof(desc); desc.dwSize = sizeof(desc);
if (m_surface->Lock(NULL, &desc, DDLOCK_SURFACEMEMORYPTR, NULL) == DD_OK) { if (m_surface->Lock(NULL, &desc, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WRITEONLY, NULL) == DD_OK) {
MxU8* surface = (MxU8*) desc.lpSurface; MxU8* surface = (MxU8*) desc.lpSurface;
const LegoU8* bits = p_bits; const LegoU8* bits = p_bits;

View File

@ -708,7 +708,7 @@ void WriteDefaultTexture(LegoStorage* p_storage, const char* p_name)
memset(&desc, 0, sizeof(desc)); memset(&desc, 0, sizeof(desc));
desc.dwSize = sizeof(desc); desc.dwSize = sizeof(desc);
if (surface->Lock(NULL, &desc, DDLOCK_SURFACEMEMORYPTR, NULL) == DD_OK) { if (surface->Lock(NULL, &desc, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WRITEONLY, NULL) == DD_OK) {
LegoImage* image = new LegoImage(desc.dwWidth, desc.dwHeight); LegoImage* image = new LegoImage(desc.dwWidth, desc.dwHeight);
if (image != NULL) { if (image != NULL) {

View File

@ -210,10 +210,10 @@ void MxTransitionManager::DissolveTransition()
memset(&ddsd, 0, sizeof(ddsd)); memset(&ddsd, 0, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd); ddsd.dwSize = sizeof(ddsd);
HRESULT res = m_ddSurface->Lock(NULL, &ddsd, DDLOCK_WAIT, NULL); HRESULT res = m_ddSurface->Lock(NULL, &ddsd, DDLOCK_WAIT | DDLOCK_WRITEONLY, NULL);
if (res == DDERR_SURFACELOST) { if (res == DDERR_SURFACELOST) {
m_ddSurface->Restore(); m_ddSurface->Restore();
res = m_ddSurface->Lock(NULL, &ddsd, DDLOCK_WAIT, NULL); res = m_ddSurface->Lock(NULL, &ddsd, DDLOCK_WAIT | DDLOCK_WRITEONLY, NULL);
} }
if (res == DD_OK) { if (res == DD_OK) {
@ -402,10 +402,10 @@ void MxTransitionManager::WipeDownTransition()
memset(&ddsd, 0, sizeof(ddsd)); memset(&ddsd, 0, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd); ddsd.dwSize = sizeof(ddsd);
HRESULT res = m_ddSurface->Lock(NULL, &ddsd, DDLOCK_WAIT, NULL); HRESULT res = m_ddSurface->Lock(NULL, &ddsd, DDLOCK_WAIT | DDLOCK_WRITEONLY, NULL);
if (res == DDERR_SURFACELOST) { if (res == DDERR_SURFACELOST) {
m_ddSurface->Restore(); m_ddSurface->Restore();
res = m_ddSurface->Lock(NULL, &ddsd, DDLOCK_WAIT, NULL); res = m_ddSurface->Lock(NULL, &ddsd, DDLOCK_WAIT | DDLOCK_WRITEONLY, NULL);
} }
if (res == DD_OK) { if (res == DD_OK) {
@ -439,10 +439,10 @@ void MxTransitionManager::WindowsTransition()
memset(&ddsd, 0, sizeof(ddsd)); memset(&ddsd, 0, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd); ddsd.dwSize = sizeof(ddsd);
HRESULT res = m_ddSurface->Lock(NULL, &ddsd, DDLOCK_WAIT, NULL); HRESULT res = m_ddSurface->Lock(NULL, &ddsd, DDLOCK_WAIT | DDLOCK_WRITEONLY, NULL);
if (res == DDERR_SURFACELOST) { if (res == DDERR_SURFACELOST) {
m_ddSurface->Restore(); m_ddSurface->Restore();
res = m_ddSurface->Lock(NULL, &ddsd, DDLOCK_WAIT, NULL); res = m_ddSurface->Lock(NULL, &ddsd, DDLOCK_WAIT | DDLOCK_WRITEONLY, NULL);
} }
if (res == DD_OK) { if (res == DD_OK) {
@ -483,10 +483,10 @@ void MxTransitionManager::BrokenTransition()
memset(&ddsd, 0, sizeof(ddsd)); memset(&ddsd, 0, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd); ddsd.dwSize = sizeof(ddsd);
HRESULT res = m_ddSurface->Lock(NULL, &ddsd, DDLOCK_WAIT, NULL); HRESULT res = m_ddSurface->Lock(NULL, &ddsd, DDLOCK_WAIT | DDLOCK_WRITEONLY, NULL);
if (res == DDERR_SURFACELOST) { if (res == DDERR_SURFACELOST) {
m_ddSurface->Restore(); m_ddSurface->Restore();
res = m_ddSurface->Lock(NULL, &ddsd, DDLOCK_WAIT, NULL); res = m_ddSurface->Lock(NULL, &ddsd, DDLOCK_WAIT | DDLOCK_WRITEONLY, NULL);
} }
if (res == DD_OK) { if (res == DD_OK) {

View File

@ -254,7 +254,7 @@ void Score::Paint()
memset(&desc, 0, sizeof(desc)); memset(&desc, 0, sizeof(desc));
desc.dwSize = sizeof(desc); desc.dwSize = sizeof(desc);
HRESULT result = cube->m_surface->Lock(NULL, &desc, DDLOCK_SURFACEMEMORYPTR, NULL); HRESULT result = cube->m_surface->Lock(NULL, &desc, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WRITEONLY, NULL);
if (result == DD_OK) { if (result == DD_OK) {
if (desc.lPitch != desc.dwWidth) { if (desc.lPitch != desc.dwWidth) {
cube->m_surface->Unlock(desc.lpSurface); cube->m_surface->Unlock(desc.lpSurface);

View File

@ -154,7 +154,7 @@ double Lego3DView::Render(double p_und)
} }
// FUNCTION: LEGO1 0x100ab2b0 // FUNCTION: LEGO1 0x100ab2b0
ViewROI* Lego3DView::Pick(unsigned int x, unsigned int y) ViewROI* Lego3DView::Pick(int x, int y)
{ {
return m_pViewManager->Pick(GetView(), x, y); return m_pViewManager->Pick(GetView(), x, y);
} }

View File

@ -27,7 +27,7 @@ class Lego3DView : public LegoView1 {
double Render(double p_und); double Render(double p_und);
ViewROI* Pick(unsigned int x, unsigned int y); ViewROI* Pick(int x, int y);
ViewROI* GetPointOfView(); ViewROI* GetPointOfView();
ViewManager* GetViewManager(); ViewManager* GetViewManager();

View File

@ -22,7 +22,7 @@ LegoTextureInfo* LegoTextureContainer::GetCached(LegoTextureInfo* p_textureInfo)
memset(&desc, 0, sizeof(desc)); memset(&desc, 0, sizeof(desc));
desc.dwSize = sizeof(desc); desc.dwSize = sizeof(desc);
if (p_textureInfo->m_surface->Lock(NULL, &desc, DDLOCK_SURFACEMEMORYPTR, NULL) == DD_OK) { if (p_textureInfo->m_surface->Lock(NULL, &desc, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WRITEONLY, NULL) == DD_OK) {
width = desc.dwWidth; width = desc.dwWidth;
height = desc.dwHeight; height = desc.dwHeight;
p_textureInfo->m_surface->Unlock(desc.lpSurface); p_textureInfo->m_surface->Unlock(desc.lpSurface);
@ -35,7 +35,7 @@ LegoTextureInfo* LegoTextureContainer::GetCached(LegoTextureInfo* p_textureInfo)
memset(&newDesc, 0, sizeof(newDesc)); memset(&newDesc, 0, sizeof(newDesc));
newDesc.dwSize = sizeof(newDesc); newDesc.dwSize = sizeof(newDesc);
if (surface->Lock(NULL, &newDesc, DDLOCK_SURFACEMEMORYPTR, NULL) == DD_OK) { if (surface->Lock(NULL, &newDesc, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WRITEONLY, NULL) == DD_OK) {
BOOL und = FALSE; BOOL und = FALSE;
if (newDesc.dwWidth == width && newDesc.dwHeight == height) { if (newDesc.dwWidth == width && newDesc.dwHeight == height) {
und = TRUE; und = TRUE;

View File

@ -174,7 +174,7 @@ BOOL MxDirect3D::D3DSetMode()
memset(&desc, 0, sizeof(desc)); memset(&desc, 0, sizeof(desc));
desc.dwSize = sizeof(desc); desc.dwSize = sizeof(desc);
if (backBuffer->Lock(NULL, &desc, DDLOCK_WAIT, NULL) == DD_OK) { if (backBuffer->Lock(NULL, &desc, DDLOCK_WAIT | DDLOCK_WRITEONLY, NULL) == DD_OK) {
unsigned char* surface = (unsigned char*) desc.lpSurface; unsigned char* surface = (unsigned char*) desc.lpSurface;
for (int i = 0; i < mode.height; i++) { for (int i = 0; i < mode.height; i++) {
@ -192,7 +192,7 @@ BOOL MxDirect3D::D3DSetMode()
memset(&desc, 0, sizeof(desc)); memset(&desc, 0, sizeof(desc));
desc.dwSize = sizeof(desc); desc.dwSize = sizeof(desc);
if (frontBuffer->Lock(NULL, &desc, DDLOCK_WAIT, NULL) == DD_OK) { if (frontBuffer->Lock(NULL, &desc, DDLOCK_WAIT | DDLOCK_WRITEONLY, NULL) == DD_OK) {
unsigned char* surface = (unsigned char*) desc.lpSurface; unsigned char* surface = (unsigned char*) desc.lpSurface;
for (int i = 0; i < mode.height; i++) { for (int i = 0; i < mode.height; i++) {

View File

@ -539,10 +539,10 @@ void MxDirectDraw::ClearBackBuffers()
memset(&ddsd, 0, sizeof(ddsd)); memset(&ddsd, 0, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd); ddsd.dwSize = sizeof(ddsd);
result = m_pBackBuffer->Lock(NULL, &ddsd, DDLOCK_WAIT, NULL); result = m_pBackBuffer->Lock(NULL, &ddsd, DDLOCK_WAIT | DDLOCK_WRITEONLY, NULL);
if (result == DDERR_SURFACELOST) { if (result == DDERR_SURFACELOST) {
m_pBackBuffer->Restore(); m_pBackBuffer->Restore();
result = m_pBackBuffer->Lock(NULL, &ddsd, DDLOCK_WAIT, NULL); result = m_pBackBuffer->Lock(NULL, &ddsd, DDLOCK_WAIT | DDLOCK_WRITEONLY, NULL);
} }
if (result != DD_OK) { if (result != DD_OK) {

View File

@ -402,10 +402,10 @@ void MxDisplaySurface::VTable0x28(
memset(&ddsd, 0, sizeof(ddsd)); memset(&ddsd, 0, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd); ddsd.dwSize = sizeof(ddsd);
HRESULT hr = m_ddSurface2->Lock(NULL, &ddsd, DDLOCK_WAIT, NULL); HRESULT hr = m_ddSurface2->Lock(NULL, &ddsd, DDLOCK_WAIT | DDLOCK_WRITEONLY, NULL);
if (hr == DDERR_SURFACELOST) { if (hr == DDERR_SURFACELOST) {
m_ddSurface2->Restore(); m_ddSurface2->Restore();
hr = m_ddSurface2->Lock(NULL, &ddsd, DDLOCK_WAIT, NULL); hr = m_ddSurface2->Lock(NULL, &ddsd, DDLOCK_WAIT | DDLOCK_WRITEONLY, NULL);
} }
if (hr != DD_OK) { if (hr != DD_OK) {
@ -514,10 +514,10 @@ void MxDisplaySurface::VTable0x30(
memset(&ddsd, 0, sizeof(ddsd)); memset(&ddsd, 0, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd); ddsd.dwSize = sizeof(ddsd);
HRESULT hr = m_ddSurface2->Lock(NULL, &ddsd, DDLOCK_WAIT, NULL); HRESULT hr = m_ddSurface2->Lock(NULL, &ddsd, DDLOCK_WAIT | DDLOCK_WRITEONLY, NULL);
if (hr == DDERR_SURFACELOST) { if (hr == DDERR_SURFACELOST) {
m_ddSurface2->Restore(); m_ddSurface2->Restore();
hr = m_ddSurface2->Lock(NULL, &ddsd, DDLOCK_WAIT, NULL); hr = m_ddSurface2->Lock(NULL, &ddsd, DDLOCK_WAIT | DDLOCK_WRITEONLY, NULL);
} }
if (hr != DD_OK) { if (hr != DD_OK) {
@ -726,11 +726,11 @@ void MxDisplaySurface::VTable0x34(MxU8* p_pixels, MxS32 p_bpp, MxS32 p_width, Mx
memset(&surfaceDesc, 0, sizeof(surfaceDesc)); memset(&surfaceDesc, 0, sizeof(surfaceDesc));
surfaceDesc.dwSize = sizeof(surfaceDesc); surfaceDesc.dwSize = sizeof(surfaceDesc);
HRESULT result = m_ddSurface2->Lock(NULL, &surfaceDesc, DDLOCK_WAIT, NULL); HRESULT result = m_ddSurface2->Lock(NULL, &surfaceDesc, DDLOCK_WAIT | DDLOCK_WRITEONLY, NULL);
if (result == DDERR_SURFACELOST) { if (result == DDERR_SURFACELOST) {
m_ddSurface2->Restore(); m_ddSurface2->Restore();
result = m_ddSurface2->Lock(NULL, &surfaceDesc, DDLOCK_WAIT, NULL); result = m_ddSurface2->Lock(NULL, &surfaceDesc, DDLOCK_WAIT | DDLOCK_WRITEONLY, NULL);
} }
if (result == DD_OK) { if (result == DD_OK) {
@ -784,7 +784,7 @@ void MxDisplaySurface::Display(MxS32 p_left, MxS32 p_top, MxS32 p_left2, MxS32 p
DDSURFACEDESC ddsd; DDSURFACEDESC ddsd;
memset(&ddsd, 0, sizeof(ddsd)); memset(&ddsd, 0, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd); ddsd.dwSize = sizeof(ddsd);
if (m_ddSurface2->Lock(NULL, &ddsd, DDLOCK_WAIT, NULL) == DD_OK) { if (m_ddSurface2->Lock(NULL, &ddsd, DDLOCK_WAIT | DDLOCK_WRITEONLY, NULL) == DD_OK) {
MxU8* surface = (MxU8*) ddsd.lpSurface; MxU8* surface = (MxU8*) ddsd.lpSurface;
MxS32 height = m_videoParam.GetRect().GetHeight(); MxS32 height = m_videoParam.GetRect().GetHeight();
@ -891,7 +891,7 @@ LPDIRECTDRAWSURFACE MxDisplaySurface::VTable0x44(
memset(&ddsd, 0, sizeof(ddsd)); memset(&ddsd, 0, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd); ddsd.dwSize = sizeof(ddsd);
if (surface->Lock(NULL, &ddsd, DDLOCK_WAIT, 0) != DD_OK) { if (surface->Lock(NULL, &ddsd, DDLOCK_WAIT | DDLOCK_WRITEONLY, 0) != DD_OK) {
surface->Release(); surface->Release();
surface = NULL; surface = NULL;
} }
@ -1067,7 +1067,7 @@ LPDIRECTDRAWSURFACE MxDisplaySurface::CreateCursorSurface()
memset(&ddsd, 0, sizeof(ddsd)); memset(&ddsd, 0, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd); ddsd.dwSize = sizeof(ddsd);
if (newSurface->Lock(NULL, &ddsd, DDLOCK_WAIT, NULL) != DD_OK) { if (newSurface->Lock(NULL, &ddsd, DDLOCK_WAIT | DDLOCK_WRITEONLY, NULL) != DD_OK) {
goto done; goto done;
} }
else { else {

View File

@ -252,8 +252,8 @@ class ViewImpl : public View {
Result TransformWorldToScreen(const float world[3], float screen[4]) override; Result TransformWorldToScreen(const float world[3], float screen[4]) override;
Result TransformScreenToWorld(const float screen[4], float world[3]) override; Result TransformScreenToWorld(const float screen[4], float world[3]) override;
Result Pick( Result Pick(
unsigned int x, int x,
unsigned int y, int y,
const Group** ppGroupsToPickFrom, const Group** ppGroupsToPickFrom,
int groupsToPickFromCount, int groupsToPickFromCount,
const Group**& rppPickedGroups, const Group**& rppPickedGroups,
@ -277,8 +277,8 @@ class ViewImpl : public View {
Result SetCamera(const CameraImpl& rCamera); Result SetCamera(const CameraImpl& rCamera);
Result Render(const GroupImpl& rScene); Result Render(const GroupImpl& rScene);
Result Pick( Result Pick(
unsigned int x, int x,
unsigned int y, int y,
const GroupImpl** ppGroupsToPickFrom, const GroupImpl** ppGroupsToPickFrom,
int groupsToPickFromCount, int groupsToPickFromCount,
const Group**& rppPickedGroups, const Group**& rppPickedGroups,

View File

@ -495,8 +495,8 @@ Result ViewImpl::ForceUpdate(unsigned int x, unsigned int y, unsigned int width,
// FUNCTION: BETA10 0x101710f0 // FUNCTION: BETA10 0x101710f0
inline Result ViewImpl::Pick( inline Result ViewImpl::Pick(
unsigned int x, int x,
unsigned int y, int y,
const GroupImpl** ppGroupsToPickFrom, const GroupImpl** ppGroupsToPickFrom,
int groupsToPickFromCount, int groupsToPickFromCount,
const Group**& rppPickedGroups, const Group**& rppPickedGroups,
@ -519,8 +519,8 @@ inline Result ViewImpl::Pick(
// FUNCTION: LEGO1 0x100a30c0 // FUNCTION: LEGO1 0x100a30c0
// FUNCTION: BETA10 0x1016ee10 // FUNCTION: BETA10 0x1016ee10
Result ViewImpl::Pick( Result ViewImpl::Pick(
unsigned int x, int x,
unsigned int y, int y,
const Group** ppGroupsToPickFrom, const Group** ppGroupsToPickFrom,
int groupsToPickFromCount, int groupsToPickFromCount,
const Group**& rppPickedGroups, const Group**& rppPickedGroups,

View File

@ -257,8 +257,8 @@ class View : public Object {
// output parameter // output parameter
// size of rppPickedGroups // size of rppPickedGroups
virtual Result Pick( virtual Result Pick(
unsigned int x, int x,
unsigned int y, int y,
const Group** ppGroupsToPickFrom, const Group** ppGroupsToPickFrom,
int groupsToPickFromCount, int groupsToPickFromCount,
const Group**& rppPickedGroups, const Group**& rppPickedGroups,

View File

@ -499,7 +499,7 @@ float ViewManager::ProjectedSize(const BoundingSphere& p_bounding_sphere)
} }
// FUNCTION: LEGO1 0x100a6e00 // FUNCTION: LEGO1 0x100a6e00
ViewROI* ViewManager::Pick(Tgl::View* p_view, unsigned int x, unsigned int y) ViewROI* ViewManager::Pick(Tgl::View* p_view, int x, int y)
{ {
LPDIRECT3DRMPICKEDARRAY picked = NULL; LPDIRECT3DRMPICKEDARRAY picked = NULL;
ViewROI* result = NULL; ViewROI* result = NULL;

View File

@ -33,7 +33,7 @@ class ViewManager {
void RemoveROIDetailFromScene(ViewROI* p_roi); void RemoveROIDetailFromScene(ViewROI* p_roi);
void SetPOVSource(const OrientableROI* point_of_view); void SetPOVSource(const OrientableROI* point_of_view);
float ProjectedSize(const BoundingSphere& p_bounding_sphere); float ProjectedSize(const BoundingSphere& p_bounding_sphere);
ViewROI* Pick(Tgl::View* p_view, unsigned int x, unsigned int y); ViewROI* Pick(Tgl::View* p_view, int x, int y);
void SetResolution(int width, int height); void SetResolution(int width, int height);
void SetFrustrum(float fov, float front, float back); void SetFrustrum(float fov, float front, float back);
inline void ManageVisibilityAndDetailRecursively(ViewROI* p_from, int p_lodLevel); inline void ManageVisibilityAndDetailRecursively(ViewROI* p_from, int p_lodLevel);

View File

@ -27,6 +27,10 @@ add_library(miniwin STATIC EXCLUDE_FROM_ALL
src/d3drm/backends/software/renderer.cpp src/d3drm/backends/software/renderer.cpp
) )
target_compile_definitions(miniwin PRIVATE
$<$<CONFIG:Debug>:DEBUG>
)
find_package(OpenGL) find_package(OpenGL)
find_package(GLEW) find_package(GLEW)
if(OpenGL_FOUND AND GLEW_FOUND) if(OpenGL_FOUND AND GLEW_FOUND)

View File

@ -159,12 +159,15 @@ enum class DDBltFastFlags : uint32_t {
}; };
ENABLE_BITMASK_OPERATORS(DDBltFastFlags) ENABLE_BITMASK_OPERATORS(DDBltFastFlags)
#define DDLOCK_WAIT DDLockFlags::WAIT
#define DDLOCK_SURFACEMEMORYPTR DDLockFlags::SURFACEMEMORYPTR #define DDLOCK_SURFACEMEMORYPTR DDLockFlags::SURFACEMEMORYPTR
#define DDLOCK_WAIT DDLockFlags::WAIT
#define DDLOCK_WRITEONLY DDLockFlags::WRITEONLY
enum class DDLockFlags : uint32_t { enum class DDLockFlags : uint32_t {
SURFACEMEMORYPTR, SURFACEMEMORYPTR = 0,
WAIT, WAIT = 1 << 0,
WRITEONLY = 1 << 5,
}; };
ENABLE_BITMASK_OPERATORS(DDLockFlags)
#define DDSCL_FULLSCREEN DDSCLFlags::FULLSCREEN #define DDSCL_FULLSCREEN DDSCLFlags::FULLSCREEN
#define DDSCL_ALLOWREBOOT DDSCLFlags::ALLOWREBOOT #define DDSCL_ALLOWREBOOT DDSCLFlags::ALLOWREBOOT

View File

@ -11,19 +11,22 @@
static LPDIRECT3D9 g_d3d; static LPDIRECT3D9 g_d3d;
static LPDIRECT3DDEVICE9 g_device; static LPDIRECT3DDEVICE9 g_device;
static HWND g_hwnd; static HWND g_hwnd;
static LPDIRECT3DTEXTURE9 g_renderTargetTex; static int g_width;
static LPDIRECT3DSURFACE9 g_renderTargetSurf; static int g_height;
static LPDIRECT3DSURFACE9 g_oldRenderTarget; static int g_virtualWidth;
static int m_width; static int g_virtualHeight;
static int m_height; static bool g_hasScene = false;
static std::vector<BridgeSceneLight> m_lights; static std::vector<BridgeSceneLight> g_lights;
static Matrix4x4 m_projection; static Matrix4x4 g_projection;
static ViewportTransform g_viewportTransform;
bool Actual_Initialize(void* hwnd, int width, int height) bool Actual_Initialize(void* hwnd, int width, int height)
{ {
g_hwnd = (HWND) hwnd; g_hwnd = (HWND) hwnd;
m_width = width; g_width = width;
m_height = height; g_height = height;
g_virtualWidth = width;
g_virtualHeight = height;
g_d3d = Direct3DCreate9(D3D_SDK_VERSION); g_d3d = Direct3DCreate9(D3D_SDK_VERSION);
if (!g_d3d) { if (!g_d3d) {
return false; return false;
@ -52,45 +55,17 @@ bool Actual_Initialize(void* hwnd, int width, int height)
return false; return false;
} }
hr = g_device->CreateTexture(
width,
height,
1,
D3DUSAGE_RENDERTARGET,
D3DFMT_A8R8G8B8,
D3DPOOL_DEFAULT,
&g_renderTargetTex,
nullptr
);
if (FAILED(hr)) { if (FAILED(hr)) {
g_device->Release(); g_device->Release();
g_d3d->Release(); g_d3d->Release();
return false; return false;
} }
hr = g_renderTargetTex->GetSurfaceLevel(0, &g_renderTargetSurf);
if (FAILED(hr)) {
g_renderTargetTex->Release();
g_device->Release();
g_d3d->Release();
return false;
}
g_device->SetFVF(D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1);
return true; return true;
} }
void Actual_Shutdown() void Actual_Shutdown()
{ {
if (g_renderTargetSurf) {
g_renderTargetSurf->Release();
g_renderTargetSurf = nullptr;
}
if (g_renderTargetTex) {
g_renderTargetTex->Release();
g_renderTargetTex = nullptr;
}
if (g_device) { if (g_device) {
g_device->Release(); g_device->Release();
g_device = nullptr; g_device = nullptr;
@ -103,12 +78,12 @@ void Actual_Shutdown()
void Actual_PushLights(const BridgeSceneLight* lightsArray, size_t count) void Actual_PushLights(const BridgeSceneLight* lightsArray, size_t count)
{ {
m_lights.assign(lightsArray, lightsArray + count); g_lights.assign(lightsArray, lightsArray + count);
} }
void Actual_SetProjection(const Matrix4x4* projection, float front, float back) void Actual_SetProjection(const Matrix4x4* projection, float front, float back)
{ {
memcpy(&m_projection, projection, sizeof(Matrix4x4)); memcpy(&g_projection, projection, sizeof(Matrix4x4));
} }
IDirect3DTexture9* UploadSurfaceToD3DTexture(SDL_Surface* surface) IDirect3DTexture9* UploadSurfaceToD3DTexture(SDL_Surface* surface)
@ -188,18 +163,71 @@ void UploadMeshBuffers(
cache.ibo->Unlock(); cache.ibo->Unlock();
} }
constexpr float PI = 3.14159265358979323846f; void Actual_Resize(int width, int height, const ViewportTransform& viewportTransform)
void SetupLights()
{ {
g_width = width;
g_height = height;
g_viewportTransform = viewportTransform;
D3DPRESENT_PARAMETERS pp = {};
pp.Windowed = TRUE;
pp.SwapEffect = D3DSWAPEFFECT_DISCARD;
pp.hDeviceWindow = g_hwnd;
pp.BackBufferFormat = D3DFMT_A8R8G8B8;
pp.BackBufferWidth = width;
pp.BackBufferHeight = height;
pp.EnableAutoDepthStencil = TRUE;
pp.AutoDepthStencilFormat = D3DFMT_D24S8;
g_device->Reset(&pp);
}
void StartScene()
{
if (g_hasScene) {
return;
}
g_device->BeginScene();
g_hasScene = true;
}
void Actual_Clear(float r, float g, float b)
{
StartScene();
g_device->Clear(
0,
nullptr,
D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
D3DCOLOR_ARGB(255, static_cast<int>(r * 255), static_cast<int>(g * 255), static_cast<int>(b * 255)),
1.0f,
0
);
}
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
uint32_t Actual_BeginFrame()
{
StartScene();
g_device->SetRenderState(D3DRS_LIGHTING, TRUE); g_device->SetRenderState(D3DRS_LIGHTING, TRUE);
g_device->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
g_device->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
g_device->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL);
g_device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
g_device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
g_device->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_NONE);
for (DWORD i = 0; i < 8; ++i) { for (DWORD i = 0; i < 8; ++i) {
g_device->LightEnable(i, FALSE); g_device->LightEnable(i, FALSE);
} }
DWORD lightIdx = 0; DWORD lightIdx = 0;
for (const auto& l : m_lights) { for (const auto& l : g_lights) {
if (lightIdx >= 8) { if (lightIdx >= 8) {
break; break;
} }
@ -235,30 +263,16 @@ void SetupLights()
} }
light.Falloff = 1.0f; light.Falloff = 1.0f;
light.Phi = PI; light.Phi = M_PI;
light.Theta = PI / 2; light.Theta = M_PI / 2;
if (SUCCEEDED(g_device->SetLight(lightIdx, &light))) { if (SUCCEEDED(g_device->SetLight(lightIdx, &light))) {
g_device->LightEnable(lightIdx, TRUE); g_device->LightEnable(lightIdx, TRUE);
} }
++lightIdx; ++lightIdx;
} }
}
uint32_t Actual_BeginFrame() g_device->SetFVF(D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1);
{
g_device->GetRenderTarget(0, &g_oldRenderTarget);
g_device->SetRenderTarget(0, g_renderTargetSurf);
g_device->Clear(0, nullptr, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_ARGB(0, 0, 0, 0), 1.0f, 0);
g_device->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
g_device->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
g_device->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL);
g_device->BeginScene();
SetupLights();
return D3D_OK; return D3D_OK;
} }
@ -286,15 +300,19 @@ D3DMATRIX ToD3DMATRIX(const Matrix4x4& in)
void Actual_SubmitDraw( void Actual_SubmitDraw(
const D3D9MeshCacheEntry* mesh, const D3D9MeshCacheEntry* mesh,
const Matrix4x4* modelViewMatrix, const Matrix4x4* modelViewMatrix,
const Matrix4x4* worldMatrix,
const Matrix4x4* viewMatrix,
const Matrix3x3* normalMatrix, const Matrix3x3* normalMatrix,
const Appearance* appearance, const Appearance* appearance,
IDirect3DTexture9* texture IDirect3DTexture9* texture
) )
{ {
D3DMATRIX worldView = ToD3DMATRIX(*modelViewMatrix); D3DMATRIX proj = ToD3DMATRIX(g_projection);
g_device->SetTransform(D3DTS_WORLD, &worldView);
D3DMATRIX proj = ToD3DMATRIX(m_projection);
g_device->SetTransform(D3DTS_PROJECTION, &proj); g_device->SetTransform(D3DTS_PROJECTION, &proj);
D3DMATRIX view = ToD3DMATRIX(*viewMatrix);
g_device->SetTransform(D3DTS_VIEW, &view);
D3DMATRIX world = ToD3DMATRIX(*worldMatrix);
g_device->SetTransform(D3DTS_WORLD, &world);
D3DMATERIAL9 mat = {}; D3DMATERIAL9 mat = {};
mat.Diffuse.r = appearance->color.r / 255.0f; mat.Diffuse.r = appearance->color.r / 255.0f;
@ -342,44 +360,149 @@ void Actual_SubmitDraw(
g_device->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, mesh->vertexCount, 0, mesh->indexCount / 3); g_device->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, mesh->vertexCount, 0, mesh->indexCount / 3);
} }
uint32_t Actual_FinalizeFrame(void* pixels, int pitch) uint32_t Actual_Flip()
{ {
g_device->EndScene(); g_device->EndScene();
g_hasScene = false;
g_device->SetRenderTarget(0, g_oldRenderTarget); return g_device->Present(nullptr, nullptr, nullptr, nullptr);
g_oldRenderTarget->Release(); }
LPDIRECT3DSURFACE9 sysMemSurf; void Actual_Draw2DImage(IDirect3DTexture9* texture, const SDL_Rect& srcRect, const SDL_Rect& dstRect)
HRESULT hr = {
g_device StartScene();
->CreateOffscreenPlainSurface(m_width, m_height, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &sysMemSurf, nullptr);
if (FAILED(hr)) { float left = -g_viewportTransform.offsetX / g_viewportTransform.scale;
return hr; float right = (g_width - g_viewportTransform.offsetX) / g_viewportTransform.scale;
} float top = -g_viewportTransform.offsetY / g_viewportTransform.scale;
float bottom = (g_height - g_viewportTransform.offsetY) / g_viewportTransform.scale;
hr = g_device->GetRenderTargetData(g_renderTargetSurf, sysMemSurf);
if (FAILED(hr)) { auto virtualToScreenX = [&](float x) { return ((x - left) / (right - left)) * g_width; };
sysMemSurf->Release(); auto virtualToScreenY = [&](float y) { return ((y - top) / (bottom - top)) * g_height; };
return hr;
} float x1_virtual = static_cast<float>(dstRect.x);
float y1_virtual = static_cast<float>(dstRect.y);
D3DLOCKED_RECT lockedRect; float x2_virtual = x1_virtual + dstRect.w;
hr = sysMemSurf->LockRect(&lockedRect, nullptr, D3DLOCK_READONLY); float y2_virtual = y1_virtual + dstRect.h;
if (FAILED(hr)) {
sysMemSurf->Release(); float x1 = virtualToScreenX(x1_virtual);
return hr; float y1 = virtualToScreenY(y1_virtual);
} float x2 = virtualToScreenX(x2_virtual);
float y2 = virtualToScreenY(y2_virtual);
BYTE* src = static_cast<BYTE*>(lockedRect.pBits);
BYTE* dst = static_cast<BYTE*>(pixels); D3DMATRIX identity =
int copyWidth = m_width * 4; {1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
g_device->SetTransform(D3DTS_PROJECTION, &identity);
for (int y = 0; y < m_height; y++) { g_device->SetTransform(D3DTS_VIEW, &identity);
memcpy(dst + y * pitch, src + y * lockedRect.Pitch, copyWidth); g_device->SetTransform(D3DTS_WORLD, &identity);
}
g_device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
sysMemSurf->UnlockRect(); g_device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
sysMemSurf->Release();
g_device->SetRenderState(D3DRS_ZENABLE, FALSE);
return hr; g_device->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
g_device->SetRenderState(D3DRS_LIGHTING, FALSE);
g_device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
g_device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
g_device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
g_device->SetTexture(0, texture);
g_device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
g_device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
g_device->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
D3DSURFACE_DESC texDesc;
texture->GetLevelDesc(0, &texDesc);
float texW = static_cast<float>(texDesc.Width);
float texH = static_cast<float>(texDesc.Height);
float u1 = static_cast<float>(srcRect.x) / texW;
float v1 = static_cast<float>(srcRect.y) / texH;
float u2 = static_cast<float>(srcRect.x + srcRect.w) / texW;
float v2 = static_cast<float>(srcRect.y + srcRect.h) / texH;
struct Vertex {
float x, y, z, rhw;
float u, v;
};
Vertex quad[4] = {
{x1, y1, 0.0f, 1.0f, u1, v1},
{x2, y1, 0.0f, 1.0f, u2, v1},
{x2, y2, 0.0f, 1.0f, u2, v2},
{x1, y2, 0.0f, 1.0f, u1, v2},
};
g_device->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1);
g_device->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, quad, sizeof(Vertex));
}
uint32_t Actual_Download(SDL_Surface* target)
{
IDirect3DSurface9* backBuffer;
HRESULT hr = g_device->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &backBuffer);
if (FAILED(hr)) {
return hr;
}
IDirect3DSurface9* sysMemSurface;
hr = g_device->CreateOffscreenPlainSurface(
g_width,
g_height,
D3DFMT_A8R8G8B8,
D3DPOOL_SYSTEMMEM,
&sysMemSurface,
nullptr
);
if (FAILED(hr)) {
backBuffer->Release();
return hr;
}
hr = g_device->GetRenderTargetData(backBuffer, sysMemSurface);
backBuffer->Release();
if (FAILED(hr)) {
sysMemSurface->Release();
return hr;
}
D3DLOCKED_RECT locked;
hr = sysMemSurface->LockRect(&locked, nullptr, D3DLOCK_READONLY);
if (FAILED(hr)) {
sysMemSurface->Release();
return hr;
}
SDL_Surface* srcSurface =
SDL_CreateSurfaceFrom(g_width, g_height, SDL_PIXELFORMAT_ARGB8888, locked.pBits, locked.Pitch);
if (!srcSurface) {
sysMemSurface->UnlockRect();
sysMemSurface->Release();
return E_FAIL;
}
float srcAspect = static_cast<float>(g_width) / g_height;
float dstAspect = static_cast<float>(target->w) / target->h;
SDL_Rect srcRect;
if (srcAspect > dstAspect) {
int cropWidth = static_cast<int>(g_height * dstAspect);
srcRect = {(g_width - cropWidth) / 2, 0, cropWidth, g_height};
}
else {
int cropHeight = static_cast<int>(g_width / dstAspect);
srcRect = {0, (g_height - cropHeight) / 2, g_width, cropHeight};
}
if (SDL_BlitSurfaceScaled(srcSurface, &srcRect, target, nullptr, SDL_SCALEMODE_NEAREST)) {
SDL_DestroySurface(srcSurface);
sysMemSurface->UnlockRect();
sysMemSurface->Release();
return E_FAIL;
}
SDL_DestroySurface(srcSurface);
sysMemSurface->UnlockRect();
sysMemSurface->Release();
return D3D_OK;
} }

View File

@ -69,8 +69,14 @@ void Actual_EnableTransparency();
void Actual_SubmitDraw( void Actual_SubmitDraw(
const D3D9MeshCacheEntry* mesh, const D3D9MeshCacheEntry* mesh,
const Matrix4x4* modelViewMatrix, const Matrix4x4* modelViewMatrix,
const Matrix4x4* worldMatrix,
const Matrix4x4* viewMatrix,
const Matrix3x3* normalMatrix, const Matrix3x3* normalMatrix,
const Appearance* appearance, const Appearance* appearance,
IDirect3DTexture9* texture IDirect3DTexture9* texture
); );
uint32_t Actual_FinalizeFrame(void* pixels, int pitch); void Actual_Resize(int width, int height, const ViewportTransform& viewportTransform);
void Actual_Clear(float r, float g, float b);
uint32_t Actual_Flip();
void Actual_Draw2DImage(IDirect3DTexture9* texture, const SDL_Rect& srcRect, const SDL_Rect& dstRect);
uint32_t Actual_Download(SDL_Surface* target);

View File

@ -20,14 +20,18 @@ Direct3DRMRenderer* DirectX9Renderer::Create(DWORD width, DWORD height)
return new DirectX9Renderer(width, height); return new DirectX9Renderer(width, height);
} }
DirectX9Renderer::DirectX9Renderer(DWORD width, DWORD height) : m_width(width), m_height(height) DirectX9Renderer::DirectX9Renderer(DWORD width, DWORD height)
{ {
m_width = width;
m_height = height;
m_virtualWidth = width;
m_virtualHeight = height;
Actual_Initialize( Actual_Initialize(
SDL_GetPointerProperty(SDL_GetWindowProperties(DDWindow), SDL_PROP_WINDOW_WIN32_HWND_POINTER, NULL), SDL_GetPointerProperty(SDL_GetWindowProperties(DDWindow), SDL_PROP_WINDOW_WIN32_HWND_POINTER, NULL),
width, width,
height height
); );
m_renderedImage = SDL_CreateSurface(m_width, m_height, SDL_PIXELFORMAT_ARGB8888); m_renderedImage = SDL_CreateSurface(m_width, m_height, SDL_PIXELFORMAT_RGBA32);
} }
DirectX9Renderer::~DirectX9Renderer() DirectX9Renderer::~DirectX9Renderer()
@ -212,16 +216,6 @@ Uint32 DirectX9Renderer::GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* meshG
return static_cast<Uint32>(m_meshs.size() - 1); return static_cast<Uint32>(m_meshs.size() - 1);
} }
DWORD DirectX9Renderer::GetWidth()
{
return m_width;
}
DWORD DirectX9Renderer::GetHeight()
{
return m_height;
}
void DirectX9Renderer::GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc) void DirectX9Renderer::GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc)
{ {
halDesc->dcmColorModel = D3DCOLORMODEL::RGB; halDesc->dcmColorModel = D3DCOLORMODEL::RGB;
@ -253,6 +247,8 @@ void DirectX9Renderer::EnableTransparency()
void DirectX9Renderer::SubmitDraw( void DirectX9Renderer::SubmitDraw(
DWORD meshId, DWORD meshId,
const D3DRMMATRIX4D& modelViewMatrix, const D3DRMMATRIX4D& modelViewMatrix,
const D3DRMMATRIX4D& worldMatrix,
const D3DRMMATRIX4D& viewMatrix,
const Matrix3x3& normalMatrix, const Matrix3x3& normalMatrix,
const Appearance& appearance const Appearance& appearance
) )
@ -261,17 +257,46 @@ void DirectX9Renderer::SubmitDraw(
if (appearance.textureId != NO_TEXTURE_ID) { if (appearance.textureId != NO_TEXTURE_ID) {
texture = m_textures[appearance.textureId].dxTexture; texture = m_textures[appearance.textureId].dxTexture;
} }
Actual_SubmitDraw(&m_meshs[meshId], &modelViewMatrix, &normalMatrix, &appearance, texture); Actual_SubmitDraw(
&m_meshs[meshId],
&modelViewMatrix,
&worldMatrix,
&viewMatrix,
&normalMatrix,
&appearance,
texture
);
} }
HRESULT DirectX9Renderer::FinalizeFrame() HRESULT DirectX9Renderer::FinalizeFrame()
{ {
HRESULT hr = Actual_FinalizeFrame(m_renderedImage->pixels, m_renderedImage->pitch); return DD_OK;
if (hr != DD_OK) { }
return hr;
} void DirectX9Renderer::Resize(int width, int height, const ViewportTransform& viewportTransform)
{
// Composite onto SDL backbuffer m_width = width;
SDL_BlitSurface(m_renderedImage, nullptr, DDBackBuffer, nullptr); m_height = height;
return hr; m_viewportTransform = viewportTransform;
Actual_Resize(width, height, viewportTransform);
}
void DirectX9Renderer::Clear(float r, float g, float b)
{
Actual_Clear(r, g, b);
}
void DirectX9Renderer::Flip()
{
Actual_Flip();
}
void DirectX9Renderer::Draw2DImage(Uint32 textureId, const SDL_Rect& srcRect, const SDL_Rect& dstRect)
{
Actual_Draw2DImage(m_textures[textureId].dxTexture, srcRect, dstRect);
}
void DirectX9Renderer::Download(SDL_Surface* target)
{
Actual_Download(target);
} }

View File

@ -15,17 +15,24 @@ Direct3DRMRenderer* OpenGL1Renderer::Create(DWORD width, DWORD height)
{ {
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY); SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 1); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 1);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
SDL_Window* window = DDWindow; SDL_Window* window = DDWindow;
bool testWindow = false; bool testWindow = false;
if (!window) { if (!window) {
window = SDL_CreateWindow("OpenGL 1.2 test", width, height, SDL_WINDOW_HIDDEN | SDL_WINDOW_OPENGL); window = SDL_CreateWindow("OpenGL 1.1 test", width, height, SDL_WINDOW_HIDDEN | SDL_WINDOW_OPENGL);
if (!window) {
SDL_Log("SDL_CreateWindow: %s", SDL_GetError());
return nullptr;
}
testWindow = true; testWindow = true;
} }
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
SDL_GLContext context = SDL_GL_CreateContext(window); SDL_GLContext context = SDL_GL_CreateContext(window);
if (!context) { if (!context) {
SDL_Log("SDL_GL_CreateContext: %s", SDL_GetError());
if (testWindow) { if (testWindow) {
SDL_DestroyWindow(window); SDL_DestroyWindow(window);
} }
@ -33,18 +40,16 @@ Direct3DRMRenderer* OpenGL1Renderer::Create(DWORD width, DWORD height)
} }
if (!SDL_GL_MakeCurrent(window, context)) { if (!SDL_GL_MakeCurrent(window, context)) {
return nullptr; SDL_Log("SDL_GL_MakeCurrent: %s", SDL_GetError());
}
GLenum err = glewInit();
if (err != GLEW_OK) {
if (testWindow) { if (testWindow) {
SDL_DestroyWindow(window); SDL_DestroyWindow(window);
} }
return nullptr; return nullptr;
} }
if (!GLEW_EXT_framebuffer_object) { GLenum err = glewInit();
if (err != GLEW_OK) {
SDL_Log("glewInit: %s", glewGetErrorString(err));
if (testWindow) { if (testWindow) {
SDL_DestroyWindow(window); SDL_DestroyWindow(window);
} }
@ -53,65 +58,37 @@ Direct3DRMRenderer* OpenGL1Renderer::Create(DWORD width, DWORD height)
glEnable(GL_CULL_FACE); glEnable(GL_CULL_FACE);
glCullFace(GL_BACK); glCullFace(GL_BACK);
glFrontFace(GL_CCW); glFrontFace(GL_CW);
// Setup FBO
GLuint fbo;
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
// Create color texture
GLuint colorTex;
glGenTextures(1, &colorTex);
glBindTexture(GL_TEXTURE_2D, colorTex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTex, 0);
// Create depth renderbuffer
GLuint depthRb;
glGenRenderbuffers(1, &depthRb);
glBindRenderbuffer(GL_RENDERBUFFER, depthRb);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, width, height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthRb);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
return nullptr;
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);
if (testWindow) { if (testWindow) {
SDL_DestroyWindow(window); SDL_DestroyWindow(window);
} }
return new OpenGL1Renderer(width, height, context, fbo, colorTex, depthRb); return new OpenGL1Renderer(width, height, context);
} }
OpenGL1Renderer::OpenGL1Renderer( OpenGL1Renderer::OpenGL1Renderer(DWORD width, DWORD height, SDL_GLContext context) : m_context(context)
DWORD width,
DWORD height,
SDL_GLContext context,
GLuint fbo,
GLuint colorTex,
GLuint depthRb
)
: m_width(width), m_height(height), m_context(context), m_fbo(fbo), m_colorTex(colorTex), m_depthRb(depthRb)
{ {
m_renderedImage = SDL_CreateSurface(m_width, m_height, SDL_PIXELFORMAT_ABGR8888); m_width = width;
m_height = height;
m_virtualWidth = width;
m_virtualHeight = height;
m_renderedImage = SDL_CreateSurface(m_width, m_height, SDL_PIXELFORMAT_RGBA32);
m_useVBOs = GLEW_ARB_vertex_buffer_object; m_useVBOs = GLEW_ARB_vertex_buffer_object;
} }
OpenGL1Renderer::~OpenGL1Renderer() OpenGL1Renderer::~OpenGL1Renderer()
{ {
SDL_DestroySurface(m_renderedImage); SDL_DestroySurface(m_renderedImage);
glDeleteFramebuffers(1, &m_fbo);
glDeleteRenderbuffers(1, &m_depthRb);
glDeleteTextures(1, &m_colorTex);
} }
void OpenGL1Renderer::PushLights(const SceneLight* lightsArray, size_t count) void OpenGL1Renderer::PushLights(const SceneLight* lightsArray, size_t count)
{ {
if (count > 8) {
SDL_Log("Unsupported number of lights (%d)", static_cast<int>(count));
count = 8;
}
m_lights.assign(lightsArray, lightsArray + count); m_lights.assign(lightsArray, lightsArray + count);
} }
@ -122,7 +99,6 @@ void OpenGL1Renderer::SetFrustumPlanes(const Plane* frustumPlanes)
void OpenGL1Renderer::SetProjection(const D3DRMMATRIX4D& projection, D3DVALUE front, D3DVALUE back) void OpenGL1Renderer::SetProjection(const D3DRMMATRIX4D& projection, D3DVALUE front, D3DVALUE back)
{ {
memcpy(&m_projection, projection, sizeof(D3DRMMATRIX4D)); memcpy(&m_projection, projection, sizeof(D3DRMMATRIX4D));
m_projection[1][1] *= -1.0f; // OpenGL is upside down
} }
struct TextureDestroyContextGL { struct TextureDestroyContextGL {
@ -161,14 +137,12 @@ Uint32 OpenGL1Renderer::GetTextureId(IDirect3DRMTexture* iTexture)
glGenTextures(1, &tex.glTextureId); glGenTextures(1, &tex.glTextureId);
glBindTexture(GL_TEXTURE_2D, tex.glTextureId); glBindTexture(GL_TEXTURE_2D, tex.glTextureId);
SDL_Surface* surf = SDL_ConvertSurface(surface->m_surface, SDL_PIXELFORMAT_ABGR8888); SDL_Surface* surf = SDL_ConvertSurface(surface->m_surface, SDL_PIXELFORMAT_RGBA32);
if (!surf) { if (!surf) {
return NO_TEXTURE_ID; return NO_TEXTURE_ID;
} }
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, surf->w, surf->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, surf->pixels); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, surf->w, surf->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, surf->pixels);
SDL_DestroySurface(surf); SDL_DestroySurface(surf);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
tex.version = texture->m_version; tex.version = texture->m_version;
} }
@ -180,14 +154,12 @@ Uint32 OpenGL1Renderer::GetTextureId(IDirect3DRMTexture* iTexture)
glGenTextures(1, &texId); glGenTextures(1, &texId);
glBindTexture(GL_TEXTURE_2D, texId); glBindTexture(GL_TEXTURE_2D, texId);
SDL_Surface* surf = SDL_ConvertSurface(surface->m_surface, SDL_PIXELFORMAT_ABGR8888); SDL_Surface* surf = SDL_ConvertSurface(surface->m_surface, SDL_PIXELFORMAT_RGBA32);
if (!surf) { if (!surf) {
return NO_TEXTURE_ID; return NO_TEXTURE_ID;
} }
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, surf->w, surf->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, surf->pixels); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, surf->w, surf->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, surf->pixels);
SDL_DestroySurface(surf); SDL_DestroySurface(surf);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
for (Uint32 i = 0; i < m_textures.size(); ++i) { for (Uint32 i = 0; i < m_textures.size(); ++i) {
auto& tex = m_textures[i]; auto& tex = m_textures[i];
@ -260,7 +232,7 @@ GLMeshCacheEntry GLUploadMesh(const MeshGroup& meshGroup, bool useVBOs)
glBindBuffer(GL_ARRAY_BUFFER, cache.vboNormals); glBindBuffer(GL_ARRAY_BUFFER, cache.vboNormals);
glBufferData(GL_ARRAY_BUFFER, cache.normals.size() * sizeof(D3DVECTOR), cache.normals.data(), GL_STATIC_DRAW); glBufferData(GL_ARRAY_BUFFER, cache.normals.size() * sizeof(D3DVECTOR), cache.normals.data(), GL_STATIC_DRAW);
if (meshGroup.texture != nullptr) { if (meshGroup.texture) {
glGenBuffers(1, &cache.vboTexcoords); glGenBuffers(1, &cache.vboTexcoords);
glBindBuffer(GL_ARRAY_BUFFER, cache.vboTexcoords); glBindBuffer(GL_ARRAY_BUFFER, cache.vboTexcoords);
glBufferData( glBufferData(
@ -337,16 +309,6 @@ Uint32 OpenGL1Renderer::GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* meshGr
return (Uint32) (m_meshs.size() - 1); return (Uint32) (m_meshs.size() - 1);
} }
DWORD OpenGL1Renderer::GetWidth()
{
return m_width;
}
DWORD OpenGL1Renderer::GetHeight()
{
return m_height;
}
void OpenGL1Renderer::GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc) void OpenGL1Renderer::GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc)
{ {
halDesc->dcmColorModel = D3DCOLORMODEL::RGB; halDesc->dcmColorModel = D3DCOLORMODEL::RGB;
@ -362,14 +324,12 @@ void OpenGL1Renderer::GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc)
const char* OpenGL1Renderer::GetName() const char* OpenGL1Renderer::GetName()
{ {
return "OpenGL 1.2 HAL"; return "OpenGL 1.1 HAL";
} }
HRESULT OpenGL1Renderer::BeginFrame() HRESULT OpenGL1Renderer::BeginFrame()
{ {
SDL_GL_MakeCurrent(DDWindow, m_context); m_dirty = true;
glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
glViewport(0, 0, m_width, m_height);
glDisable(GL_BLEND); glDisable(GL_BLEND);
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
@ -378,16 +338,12 @@ HRESULT OpenGL1Renderer::BeginFrame()
glEnable(GL_COLOR_MATERIAL); glEnable(GL_COLOR_MATERIAL);
glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE); glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Disable all lights and reset global ambient // Disable all lights and reset global ambient
for (int i = 0; i < 8; ++i) { for (int i = 0; i < 8; ++i) {
glDisable(GL_LIGHT0 + i); glDisable(GL_LIGHT0 + i);
} }
const GLfloat zeroAmbient[4] = {0.f, 0.f, 0.f, 1.f}; const GLfloat zeroAmbient[4] = {0.f, 0.f, 0.f, 1.f};
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, zeroAmbient); glLightModelfv(GL_LIGHT_MODEL_AMBIENT, zeroAmbient);
glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE); glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
// Setup lights // Setup lights
@ -462,15 +418,14 @@ void OpenGL1Renderer::EnableTransparency()
void OpenGL1Renderer::SubmitDraw( void OpenGL1Renderer::SubmitDraw(
DWORD meshId, DWORD meshId,
const D3DRMMATRIX4D& modelViewMatrix, const D3DRMMATRIX4D& modelViewMatrix,
const D3DRMMATRIX4D& worldMatrix,
const D3DRMMATRIX4D& viewMatrix,
const Matrix3x3& normalMatrix, const Matrix3x3& normalMatrix,
const Appearance& appearance const Appearance& appearance
) )
{ {
auto& mesh = m_meshs[meshId]; auto& mesh = m_meshs[meshId];
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadMatrixf(&modelViewMatrix[0][0]); glLoadMatrixf(&modelViewMatrix[0][0]);
glEnable(GL_NORMALIZE); glEnable(GL_NORMALIZE);
@ -496,6 +451,8 @@ void OpenGL1Renderer::SubmitDraw(
// Bind texture if present // Bind texture if present
if (appearance.textureId != NO_TEXTURE_ID) { if (appearance.textureId != NO_TEXTURE_ID) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
auto& tex = m_textures[appearance.textureId]; auto& tex = m_textures[appearance.textureId];
glEnable(GL_TEXTURE_2D); glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, tex.glTextureId); glBindTexture(GL_TEXTURE_2D, tex.glTextureId);
@ -542,11 +499,130 @@ void OpenGL1Renderer::SubmitDraw(
HRESULT OpenGL1Renderer::FinalizeFrame() HRESULT OpenGL1Renderer::FinalizeFrame()
{ {
glReadPixels(0, 0, m_width, m_height, GL_RGBA, GL_UNSIGNED_BYTE, m_renderedImage->pixels);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
// Composite onto SDL backbuffer
SDL_BlitSurface(m_renderedImage, nullptr, DDBackBuffer, nullptr);
return DD_OK; return DD_OK;
} }
void OpenGL1Renderer::Resize(int width, int height, const ViewportTransform& viewportTransform)
{
m_width = width;
m_height = height;
m_viewportTransform = viewportTransform;
SDL_DestroySurface(m_renderedImage);
m_renderedImage = SDL_CreateSurface(m_width, m_height, SDL_PIXELFORMAT_RGBA32);
glViewport(0, 0, m_width, m_height);
}
void OpenGL1Renderer::Clear(float r, float g, float b)
{
m_dirty = true;
glEnable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);
glClearColor(r, g, b, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
void OpenGL1Renderer::Flip()
{
if (m_dirty) {
SDL_GL_SwapWindow(DDWindow);
m_dirty = false;
}
}
void OpenGL1Renderer::Draw2DImage(Uint32 textureId, const SDL_Rect& srcRect, const SDL_Rect& dstRect)
{
m_dirty = true;
glDisable(GL_DEPTH_TEST);
glDepthMask(GL_FALSE);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
float left = -m_viewportTransform.offsetX / m_viewportTransform.scale;
float right = (m_width - m_viewportTransform.offsetX) / m_viewportTransform.scale;
float top = -m_viewportTransform.offsetY / m_viewportTransform.scale;
float bottom = (m_height - m_viewportTransform.offsetY) / m_viewportTransform.scale;
glOrtho(left, right, bottom, top, -1, 1);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glDisable(GL_LIGHTING);
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, m_textures[textureId].glTextureId);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
GLint boundTexture = 0;
glGetIntegerv(GL_TEXTURE_BINDING_2D, &boundTexture);
GLfloat texW, texH;
glGetTexLevelParameterfv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &texW);
glGetTexLevelParameterfv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &texH);
float u1 = srcRect.x / texW;
float v1 = srcRect.y / texH;
float u2 = (srcRect.x + srcRect.w) / texW;
float v2 = (srcRect.y + srcRect.h) / texH;
float x1 = (float) dstRect.x;
float y1 = (float) dstRect.y;
float x2 = x1 + dstRect.w;
float y2 = y1 + dstRect.h;
glBegin(GL_QUADS);
glTexCoord2f(u1, v1);
glVertex2f(x1, y1);
glTexCoord2f(u2, v1);
glVertex2f(x2, y1);
glTexCoord2f(u2, v2);
glVertex2f(x2, y2);
glTexCoord2f(u1, v2);
glVertex2f(x1, y2);
glEnd();
// Restore state
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
}
void OpenGL1Renderer::Download(SDL_Surface* target)
{
glFinish();
glReadPixels(0, 0, m_width, m_height, GL_RGBA, GL_UNSIGNED_BYTE, m_renderedImage->pixels);
SDL_Rect srcRect = {
static_cast<int>(m_viewportTransform.offsetX),
static_cast<int>(m_viewportTransform.offsetY),
static_cast<int>(target->w * m_viewportTransform.scale),
static_cast<int>(target->h * m_viewportTransform.scale),
};
SDL_Surface* bufferClone = SDL_CreateSurface(target->w, target->h, SDL_PIXELFORMAT_RGBA32);
if (!bufferClone) {
SDL_Log("SDL_CreateSurface: %s", SDL_GetError());
return;
}
SDL_BlitSurfaceScaled(m_renderedImage, &srcRect, bufferClone, nullptr, SDL_SCALEMODE_NEAREST);
// Flip image vertically into target
SDL_Rect rowSrc = {0, 0, bufferClone->w, 1};
SDL_Rect rowDst = {0, 0, bufferClone->w, 1};
for (int y = 0; y < bufferClone->h; ++y) {
rowSrc.y = y;
rowDst.y = bufferClone->h - 1 - y;
SDL_BlitSurface(bufferClone, &rowSrc, target, &rowDst);
}
SDL_DestroySurface(bufferClone);
}

View File

@ -41,6 +41,8 @@ Direct3DRMRenderer* OpenGLES2Renderer::Create(DWORD width, DWORD height)
testWindow = true; testWindow = true;
} }
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
SDL_GLContext context = SDL_GL_CreateContext(window); SDL_GLContext context = SDL_GL_CreateContext(window);
if (!context) { if (!context) {
if (testWindow) { if (testWindow) {
@ -50,51 +52,16 @@ Direct3DRMRenderer* OpenGLES2Renderer::Create(DWORD width, DWORD height)
} }
if (!SDL_GL_MakeCurrent(window, context)) { if (!SDL_GL_MakeCurrent(window, context)) {
if (testWindow) {
SDL_DestroyWindow(window);
}
return nullptr; return nullptr;
} }
glDepthFunc(GL_LEQUAL); glDepthFunc(GL_LEQUAL);
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE); glEnable(GL_CULL_FACE);
glCullFace(GL_BACK); glCullFace(GL_BACK);
glFrontFace(GL_CCW); glFrontFace(GL_CW);
// Setup FBO
GLuint fbo;
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
// Create color texture
GLuint colorTex;
glGenTextures(1, &colorTex);
glBindTexture(GL_TEXTURE_2D, colorTex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTex, 0);
// Create depth renderbuffer
GLuint depthRb;
glGenRenderbuffers(1, &depthRb);
glBindRenderbuffer(GL_RENDERBUFFER, depthRb);
const char* extensions = (const char*) glGetString(GL_EXTENSIONS);
if (extensions) {
if (strstr(extensions, "GL_OES_depth24")) {
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24_OES, width, height);
}
else if (strstr(extensions, "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, depthRb);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
return nullptr;
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);
const char* vertexShaderSource = R"( const char* vertexShaderSource = R"(
attribute vec3 a_position; attribute vec3 a_position;
@ -183,6 +150,7 @@ Direct3DRMRenderer* OpenGLES2Renderer::Create(DWORD width, DWORD height)
if (u_useTexture != 0) { if (u_useTexture != 0) {
vec4 texel = texture2D(u_texture, v_texCoord); vec4 texel = texture2D(u_texture, v_texCoord);
finalColor.rgb = clamp(texel.rgb * finalColor.rgb, 0.0, 1.0); finalColor.rgb = clamp(texel.rgb * finalColor.rgb, 0.0, 1.0);
finalColor.a = texel.a;
} }
gl_FragColor = finalColor; gl_FragColor = finalColor;
@ -206,31 +174,23 @@ Direct3DRMRenderer* OpenGLES2Renderer::Create(DWORD width, DWORD height)
SDL_DestroyWindow(window); SDL_DestroyWindow(window);
} }
return new OpenGLES2Renderer(width, height, context, fbo, colorTex, depthRb, shaderProgram); return new OpenGLES2Renderer(width, height, context, shaderProgram);
} }
OpenGLES2Renderer::OpenGLES2Renderer( OpenGLES2Renderer::OpenGLES2Renderer(DWORD width, DWORD height, SDL_GLContext context, GLuint shaderProgram)
DWORD width, : m_context(context), m_shaderProgram(shaderProgram)
DWORD height,
SDL_GLContext context,
GLuint fbo,
GLuint colorTex,
GLuint depthRb,
GLuint shaderProgram
)
: m_width(width), m_height(height), m_context(context), m_fbo(fbo), m_colorTex(colorTex), m_depthRb(depthRb),
m_shaderProgram(shaderProgram)
{ {
m_renderedImage = SDL_CreateSurface(m_width, m_height, SDL_PIXELFORMAT_ABGR8888); m_width = width;
m_height = height;
m_virtualWidth = width;
m_virtualHeight = height;
m_renderedImage = SDL_CreateSurface(m_width, m_height, SDL_PIXELFORMAT_RGBA32);
} }
OpenGLES2Renderer::~OpenGLES2Renderer() OpenGLES2Renderer::~OpenGLES2Renderer()
{ {
SDL_DestroySurface(m_renderedImage); SDL_DestroySurface(m_renderedImage);
glDeleteFramebuffers(1, &m_fbo);
glDeleteRenderbuffers(1, &m_depthRb);
glDeleteProgram(m_shaderProgram); glDeleteProgram(m_shaderProgram);
glDeleteTextures(1, &m_colorTex);
} }
void OpenGLES2Renderer::PushLights(const SceneLight* lightsArray, size_t count) void OpenGLES2Renderer::PushLights(const SceneLight* lightsArray, size_t count)
@ -250,7 +210,6 @@ void OpenGLES2Renderer::SetFrustumPlanes(const Plane* frustumPlanes)
void OpenGLES2Renderer::SetProjection(const D3DRMMATRIX4D& projection, D3DVALUE front, D3DVALUE back) void OpenGLES2Renderer::SetProjection(const D3DRMMATRIX4D& projection, D3DVALUE front, D3DVALUE back)
{ {
memcpy(&m_projection, projection, sizeof(D3DRMMATRIX4D)); memcpy(&m_projection, projection, sizeof(D3DRMMATRIX4D));
m_projection[1][1] *= -1.0f; // OpenGL is upside down
} }
struct TextureDestroyContextGLS2 { struct TextureDestroyContextGLS2 {
@ -289,14 +248,12 @@ Uint32 OpenGLES2Renderer::GetTextureId(IDirect3DRMTexture* iTexture)
glGenTextures(1, &tex.glTextureId); glGenTextures(1, &tex.glTextureId);
glBindTexture(GL_TEXTURE_2D, tex.glTextureId); glBindTexture(GL_TEXTURE_2D, tex.glTextureId);
SDL_Surface* surf = SDL_ConvertSurface(surface->m_surface, SDL_PIXELFORMAT_ABGR8888); SDL_Surface* surf = SDL_ConvertSurface(surface->m_surface, SDL_PIXELFORMAT_RGBA32);
if (!surf) { if (!surf) {
return NO_TEXTURE_ID; return NO_TEXTURE_ID;
} }
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, surf->w, surf->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, surf->pixels); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, surf->w, surf->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, surf->pixels);
SDL_DestroySurface(surf); SDL_DestroySurface(surf);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
tex.version = texture->m_version; tex.version = texture->m_version;
} }
@ -308,14 +265,11 @@ Uint32 OpenGLES2Renderer::GetTextureId(IDirect3DRMTexture* iTexture)
glGenTextures(1, &texId); glGenTextures(1, &texId);
glBindTexture(GL_TEXTURE_2D, texId); glBindTexture(GL_TEXTURE_2D, texId);
SDL_Surface* surf = SDL_ConvertSurface(surface->m_surface, SDL_PIXELFORMAT_ABGR8888); SDL_Surface* surf = SDL_ConvertSurface(surface->m_surface, SDL_PIXELFORMAT_RGBA32);
if (!surf) { if (!surf) {
return NO_TEXTURE_ID; return NO_TEXTURE_ID;
} }
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, surf->w, surf->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, surf->pixels); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, surf->w, surf->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, surf->pixels);
SDL_DestroySurface(surf);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
for (Uint32 i = 0; i < m_textures.size(); ++i) { for (Uint32 i = 0; i < m_textures.size(); ++i) {
auto& tex = m_textures[i]; auto& tex = m_textures[i];
@ -323,12 +277,15 @@ Uint32 OpenGLES2Renderer::GetTextureId(IDirect3DRMTexture* iTexture)
tex.texture = texture; tex.texture = texture;
tex.version = texture->m_version; tex.version = texture->m_version;
tex.glTextureId = texId; tex.glTextureId = texId;
tex.width = surf->w;
tex.height = surf->h;
AddTextureDestroyCallback(i, texture); AddTextureDestroyCallback(i, texture);
return i; return i;
} }
} }
m_textures.push_back({texture, texture->m_version, texId}); m_textures.push_back({texture, texture->m_version, texId, (uint16_t) surf->w, (uint16_t) surf->h});
SDL_DestroySurface(surf);
AddTextureDestroyCallback((Uint32) (m_textures.size() - 1), texture); AddTextureDestroyCallback((Uint32) (m_textures.size() - 1), texture);
return (Uint32) (m_textures.size() - 1); return (Uint32) (m_textures.size() - 1);
} }
@ -366,7 +323,6 @@ GLES2MeshCacheEntry GLES2UploadMesh(const MeshGroup& meshGroup)
return v.texCoord; return v.texCoord;
}); });
} }
std::vector<D3DVECTOR> positions(vertices.size()); std::vector<D3DVECTOR> positions(vertices.size());
std::transform(vertices.begin(), vertices.end(), positions.begin(), [](const D3DRMVERTEX& v) { std::transform(vertices.begin(), vertices.end(), positions.begin(), [](const D3DRMVERTEX& v) {
return v.position; return v.position;
@ -451,16 +407,6 @@ Uint32 OpenGLES2Renderer::GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* mesh
return (Uint32) (m_meshs.size() - 1); return (Uint32) (m_meshs.size() - 1);
} }
DWORD OpenGLES2Renderer::GetWidth()
{
return m_width;
}
DWORD OpenGLES2Renderer::GetHeight()
{
return m_height;
}
void OpenGLES2Renderer::GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc) void OpenGLES2Renderer::GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc)
{ {
halDesc->dcmColorModel = D3DCOLORMODEL::RGB; halDesc->dcmColorModel = D3DCOLORMODEL::RGB;
@ -490,9 +436,7 @@ const char* OpenGLES2Renderer::GetName()
HRESULT OpenGLES2Renderer::BeginFrame() HRESULT OpenGLES2Renderer::BeginFrame()
{ {
SDL_GL_MakeCurrent(DDWindow, m_context); m_dirty = true;
glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
glViewport(0, 0, m_width, m_height);
glDisable(GL_BLEND); glDisable(GL_BLEND);
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
@ -500,9 +444,6 @@ HRESULT OpenGLES2Renderer::BeginFrame()
glUseProgram(m_shaderProgram); glUseProgram(m_shaderProgram);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
SceneLightGLES2 lightData[3]; SceneLightGLES2 lightData[3];
int lightCount = std::min(static_cast<int>(m_lights.size()), 3); int lightCount = std::min(static_cast<int>(m_lights.size()), 3);
@ -531,7 +472,6 @@ HRESULT OpenGLES2Renderer::BeginFrame()
glUniform4fv(glGetUniformLocation(m_shaderProgram, (base + ".direction").c_str()), 1, lightData[i].direction); glUniform4fv(glGetUniformLocation(m_shaderProgram, (base + ".direction").c_str()), 1, lightData[i].direction);
} }
glUniform1i(glGetUniformLocation(m_shaderProgram, "u_lightCount"), lightCount); glUniform1i(glGetUniformLocation(m_shaderProgram, "u_lightCount"), lightCount);
return DD_OK; return DD_OK;
} }
@ -545,6 +485,8 @@ void OpenGLES2Renderer::EnableTransparency()
void OpenGLES2Renderer::SubmitDraw( void OpenGLES2Renderer::SubmitDraw(
DWORD meshId, DWORD meshId,
const D3DRMMATRIX4D& modelViewMatrix, const D3DRMMATRIX4D& modelViewMatrix,
const D3DRMMATRIX4D& worldMatrix,
const D3DRMMATRIX4D& viewMatrix,
const Matrix3x3& normalMatrix, const Matrix3x3& normalMatrix,
const Appearance& appearance const Appearance& appearance
) )
@ -570,6 +512,8 @@ void OpenGLES2Renderer::SubmitDraw(
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, m_textures[appearance.textureId].glTextureId); glBindTexture(GL_TEXTURE_2D, m_textures[appearance.textureId].glTextureId);
glUniform1i(glGetUniformLocation(m_shaderProgram, "u_texture"), 0); glUniform1i(glGetUniformLocation(m_shaderProgram, "u_texture"), 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
} }
else { else {
glUniform1i(glGetUniformLocation(m_shaderProgram, "u_useTexture"), 0); glUniform1i(glGetUniformLocation(m_shaderProgram, "u_useTexture"), 0);
@ -606,11 +550,168 @@ HRESULT OpenGLES2Renderer::FinalizeFrame()
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glUseProgram(0); glUseProgram(0);
glReadPixels(0, 0, m_width, m_height, GL_RGBA, GL_UNSIGNED_BYTE, m_renderedImage->pixels);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
// Composite onto SDL backbuffer
SDL_BlitSurface(m_renderedImage, nullptr, DDBackBuffer, nullptr);
return DD_OK; return DD_OK;
} }
void OpenGLES2Renderer::Resize(int width, int height, const ViewportTransform& viewportTransform)
{
m_width = width;
m_height = height;
m_viewportTransform = viewportTransform;
SDL_DestroySurface(m_renderedImage);
m_renderedImage = SDL_CreateSurface(m_width, m_height, SDL_PIXELFORMAT_RGBA32);
glViewport(0, 0, m_width, m_height);
}
void OpenGLES2Renderer::Clear(float r, float g, float b)
{
m_dirty = true;
glEnable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);
glClearColor(r, g, b, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
void OpenGLES2Renderer::Flip()
{
if (m_dirty) {
SDL_GL_SwapWindow(DDWindow);
m_dirty = false;
}
}
void CreateOrthoMatrix(float left, float right, float bottom, float top, D3DRMMATRIX4D& outMatrix)
{
float near = -1.0f;
float far = 1.0f;
float rl = right - left;
float tb = top - bottom;
float fn = far - near;
outMatrix[0][0] = 2.0f / rl;
outMatrix[0][1] = 0.0f;
outMatrix[0][2] = 0.0f;
outMatrix[0][3] = 0.0f;
outMatrix[1][0] = 0.0f;
outMatrix[1][1] = 2.0f / tb;
outMatrix[1][2] = 0.0f;
outMatrix[1][3] = 0.0f;
outMatrix[2][0] = 0.0f;
outMatrix[2][1] = 0.0f;
outMatrix[2][2] = -2.0f / fn;
outMatrix[2][3] = 0.0f;
outMatrix[3][0] = -(right + left) / rl;
outMatrix[3][1] = -(top + bottom) / tb;
outMatrix[3][2] = -(far + near) / fn;
outMatrix[3][3] = 1.0f;
}
void OpenGLES2Renderer::Draw2DImage(Uint32 textureId, const SDL_Rect& srcRect, const SDL_Rect& dstRect)
{
m_dirty = true;
glDisable(GL_DEPTH_TEST);
glDepthMask(GL_FALSE);
glUseProgram(m_shaderProgram);
float color[] = {1.0f, 1.0f, 1.0f, 1.0f};
float blank[] = {0.0f, 0.0f, 0.0f, 0.0f};
glUniform4fv(glGetUniformLocation(m_shaderProgram, "u_lights[0].color"), 1, color);
glUniform4fv(glGetUniformLocation(m_shaderProgram, "u_lights[0].position"), 1, blank);
glUniform4fv(glGetUniformLocation(m_shaderProgram, "u_lights[0].direction"), 1, blank);
glUniform1i(glGetUniformLocation(m_shaderProgram, "u_lightCount"), 1);
glUniform4f(glGetUniformLocation(m_shaderProgram, "u_color"), 1.0f, 1.0f, 1.0f, 1.0f);
glUniform1f(glGetUniformLocation(m_shaderProgram, "u_shininess"), 0.0f);
float left = -m_viewportTransform.offsetX / m_viewportTransform.scale;
float right = (m_width - m_viewportTransform.offsetX) / m_viewportTransform.scale;
float top = -m_viewportTransform.offsetY / m_viewportTransform.scale;
float bottom = (m_height - m_viewportTransform.offsetY) / m_viewportTransform.scale;
D3DRMMATRIX4D projection;
CreateOrthoMatrix(left, right, bottom, top, projection);
D3DRMMATRIX4D identity = {{1.f, 0.f, 0.f, 0.f}, {0.f, 1.f, 0.f, 0.f}, {0.f, 0.f, 1.f, 0.f}, {0.f, 0.f, 0.f, 1.f}};
glUniformMatrix4fv(glGetUniformLocation(m_shaderProgram, "u_modelViewMatrix"), 1, GL_FALSE, &identity[0][0]);
glUniformMatrix3fv(glGetUniformLocation(m_shaderProgram, "u_normalMatrix"), 1, GL_FALSE, &identity[0][0]);
glUniformMatrix4fv(glGetUniformLocation(m_shaderProgram, "u_projectionMatrix"), 1, GL_FALSE, &projection[0][0]);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glActiveTexture(GL_TEXTURE0);
glUniform1i(glGetUniformLocation(m_shaderProgram, "u_useTexture"), 1);
const GLES2TextureCacheEntry& texture = m_textures[textureId];
glBindTexture(GL_TEXTURE_2D, texture.glTextureId);
glUniform1i(glGetUniformLocation(m_shaderProgram, "u_texture"), 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
float texW = texture.width;
float texH = texture.height;
float u1 = srcRect.x / texW;
float v1 = srcRect.y / texH;
float u2 = (srcRect.x + srcRect.w) / texW;
float v2 = (srcRect.y + srcRect.h) / texH;
float x1 = static_cast<float>(dstRect.x);
float y1 = static_cast<float>(dstRect.y);
float x2 = x1 + dstRect.w;
float y2 = y1 + dstRect.h;
GLfloat vertices[] = {x1, y1, u1, v1, x2, y1, u2, v1, x1, y2, u1, v2, x2, y2, u2, v2};
GLint posLoc = glGetAttribLocation(m_shaderProgram, "a_position");
GLint texLoc = glGetAttribLocation(m_shaderProgram, "a_texCoord");
glEnableVertexAttribArray(posLoc);
glEnableVertexAttribArray(texLoc);
glVertexAttribPointer(posLoc, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), vertices);
glVertexAttribPointer(texLoc, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), vertices + 2);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glDisableVertexAttribArray(posLoc);
glDisableVertexAttribArray(texLoc);
glBindTexture(GL_TEXTURE_2D, 0);
glUseProgram(0);
}
void OpenGLES2Renderer::Download(SDL_Surface* target)
{
glFinish();
glReadPixels(0, 0, m_width, m_height, GL_RGBA, GL_UNSIGNED_BYTE, m_renderedImage->pixels);
SDL_Rect srcRect = {
static_cast<int>(m_viewportTransform.offsetX),
static_cast<int>(m_viewportTransform.offsetY),
static_cast<int>(target->w * m_viewportTransform.scale),
static_cast<int>(target->h * m_viewportTransform.scale),
};
SDL_Surface* bufferClone = SDL_CreateSurface(target->w, target->h, SDL_PIXELFORMAT_RGBA32);
if (!bufferClone) {
SDL_Log("SDL_CreateSurface: %s", SDL_GetError());
return;
}
SDL_BlitSurfaceScaled(m_renderedImage, &srcRect, bufferClone, nullptr, SDL_SCALEMODE_NEAREST);
// Flip image vertically into target
SDL_Rect rowSrc = {0, 0, bufferClone->w, 1};
SDL_Rect rowDst = {0, 0, bufferClone->w, 1};
for (int y = 0; y < bufferClone->h; ++y) {
rowSrc.y = y;
rowDst.y = bufferClone->h - 1 - y;
SDL_BlitSurface(bufferClone, &rowSrc, target, &rowDst);
}
SDL_DestroySurface(bufferClone);
}

View File

@ -7,6 +7,7 @@
#include "miniwin.h" #include "miniwin.h"
#include <SDL3/SDL.h> #include <SDL3/SDL.h>
#include <cmath>
#include <cstddef> #include <cstddef>
struct ScopedSurface { struct ScopedSurface {
@ -91,7 +92,12 @@ struct ScopedShader {
void release() { ptr = nullptr; } void release() { ptr = nullptr; }
}; };
static SDL_GPUGraphicsPipeline* InitializeGraphicsPipeline(SDL_GPUDevice* device, bool depthWrite) static SDL_GPUGraphicsPipeline* InitializeGraphicsPipeline(
SDL_GPUDevice* device,
SDL_Window* window,
bool depthTest,
bool depthWrite
)
{ {
const SDL_GPUShaderCreateInfo* vertexCreateInfo = const SDL_GPUShaderCreateInfo* vertexCreateInfo =
GetVertexShaderCode(VertexShaderId::PositionColor, SDL_GetGPUShaderFormats(device)); GetVertexShaderCode(VertexShaderId::PositionColor, SDL_GetGPUShaderFormats(device));
@ -141,8 +147,8 @@ static SDL_GPUGraphicsPipeline* InitializeGraphicsPipeline(SDL_GPUDevice* device
vertexInputState.num_vertex_attributes = SDL_arraysize(vertexAttrs); vertexInputState.num_vertex_attributes = SDL_arraysize(vertexAttrs);
SDL_GPUColorTargetDescription colorTargets = {}; SDL_GPUColorTargetDescription colorTargets = {};
colorTargets.format = SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM; colorTargets.format = SDL_GetGPUSwapchainTextureFormat(device, window);
if (depthWrite) { if (depthTest && depthWrite) {
colorTargets.blend_state.enable_blend = false; colorTargets.blend_state.enable_blend = false;
} }
else { else {
@ -170,7 +176,7 @@ static SDL_GPUGraphicsPipeline* InitializeGraphicsPipeline(SDL_GPUDevice* device
pipelineCreateInfo.rasterizer_state = rasterizerState; pipelineCreateInfo.rasterizer_state = rasterizerState;
pipelineCreateInfo.depth_stencil_state.compare_op = SDL_GPU_COMPAREOP_GREATER; pipelineCreateInfo.depth_stencil_state.compare_op = SDL_GPU_COMPAREOP_GREATER;
pipelineCreateInfo.depth_stencil_state.write_mask = 0xff; pipelineCreateInfo.depth_stencil_state.write_mask = 0xff;
pipelineCreateInfo.depth_stencil_state.enable_depth_test = true; pipelineCreateInfo.depth_stencil_state.enable_depth_test = depthTest;
pipelineCreateInfo.depth_stencil_state.enable_depth_write = depthWrite; pipelineCreateInfo.depth_stencil_state.enable_depth_write = depthWrite;
pipelineCreateInfo.depth_stencil_state.enable_stencil_test = false; pipelineCreateInfo.depth_stencil_state.enable_stencil_test = false;
pipelineCreateInfo.target_info.color_target_descriptions = &colorTargets; pipelineCreateInfo.target_info.color_target_descriptions = &colorTargets;
@ -178,16 +184,18 @@ static SDL_GPUGraphicsPipeline* InitializeGraphicsPipeline(SDL_GPUDevice* device
pipelineCreateInfo.target_info.depth_stencil_format = SDL_GPU_TEXTUREFORMAT_D32_FLOAT; pipelineCreateInfo.target_info.depth_stencil_format = SDL_GPU_TEXTUREFORMAT_D32_FLOAT;
pipelineCreateInfo.target_info.has_depth_stencil_target = true; pipelineCreateInfo.target_info.has_depth_stencil_target = true;
SDL_GPUGraphicsPipeline* pipeline = SDL_CreateGPUGraphicsPipeline(device, &pipelineCreateInfo); return SDL_CreateGPUGraphicsPipeline(device, &pipelineCreateInfo);
return pipeline;
} }
Direct3DRMRenderer* Direct3DRMSDL3GPURenderer::Create(DWORD width, DWORD height) Direct3DRMRenderer* Direct3DRMSDL3GPURenderer::Create(DWORD width, DWORD height)
{ {
ScopedDevice device{SDL_CreateGPUDevice( ScopedDevice device{SDL_CreateGPUDevice(
SDL_GPU_SHADERFORMAT_SPIRV | SDL_GPU_SHADERFORMAT_DXIL | SDL_GPU_SHADERFORMAT_MSL, SDL_GPU_SHADERFORMAT_SPIRV | SDL_GPU_SHADERFORMAT_DXIL | SDL_GPU_SHADERFORMAT_MSL,
#ifdef DEBUG
true, true,
#else
false,
#endif
nullptr nullptr
)}; )};
if (!device.ptr) { if (!device.ptr) {
@ -195,63 +203,63 @@ Direct3DRMRenderer* Direct3DRMSDL3GPURenderer::Create(DWORD width, DWORD height)
return nullptr; return nullptr;
} }
ScopedPipeline opaquePipeline{device.ptr, InitializeGraphicsPipeline(device.ptr, true)}; SDL_Window* window = DDWindow;
bool testWindow = false;
if (!window) {
window = SDL_CreateWindow("SDL_GPU test", width, height, SDL_WINDOW_HIDDEN);
if (!window) {
SDL_Log("SDL_CreateWindow: %s", SDL_GetError());
return nullptr;
}
testWindow = true;
}
if (!SDL_ClaimWindowForGPUDevice(device.ptr, window)) {
SDL_LogError(LOG_CATEGORY_MINIWIN, "SDL_ClaimWindowForGPUDevice: %s", SDL_GetError());
if (testWindow) {
SDL_DestroyWindow(window);
}
return nullptr;
}
ScopedPipeline opaquePipeline{device.ptr, InitializeGraphicsPipeline(device.ptr, window, true, true)};
if (!opaquePipeline.ptr) { if (!opaquePipeline.ptr) {
SDL_LogError(LOG_CATEGORY_MINIWIN, "InitializeGraphicsPipeline for opaquePipeline"); SDL_LogError(LOG_CATEGORY_MINIWIN, "InitializeGraphicsPipeline for opaquePipeline");
if (testWindow) {
SDL_DestroyWindow(window);
}
return nullptr; return nullptr;
} }
ScopedPipeline transparentPipeline{device.ptr, InitializeGraphicsPipeline(device.ptr, false)}; ScopedPipeline transparentPipeline{device.ptr, InitializeGraphicsPipeline(device.ptr, window, true, false)};
if (!transparentPipeline.ptr) { if (!transparentPipeline.ptr) {
SDL_LogError(LOG_CATEGORY_MINIWIN, "InitializeGraphicsPipeline for transparentPipeline"); SDL_LogError(LOG_CATEGORY_MINIWIN, "InitializeGraphicsPipeline for transparentPipeline");
if (testWindow) {
SDL_DestroyWindow(window);
}
return nullptr; return nullptr;
} }
SDL_GPUTextureCreateInfo textureInfo = {}; ScopedPipeline uiPipeline{device.ptr, InitializeGraphicsPipeline(device.ptr, window, false, false)};
textureInfo.type = SDL_GPU_TEXTURETYPE_2D; if (!uiPipeline.ptr) {
textureInfo.format = SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM; SDL_LogError(LOG_CATEGORY_MINIWIN, "InitializeGraphicsPipeline for uiPipeline");
textureInfo.usage = SDL_GPU_TEXTUREUSAGE_COLOR_TARGET; if (testWindow) {
textureInfo.width = width; SDL_DestroyWindow(window);
textureInfo.height = height; }
textureInfo.layer_count_or_depth = 1;
textureInfo.num_levels = 1;
textureInfo.sample_count = SDL_GPU_SAMPLECOUNT_1;
ScopedTexture transferTexture{device.ptr, SDL_CreateGPUTexture(device.ptr, &textureInfo)};
if (!transferTexture.ptr) {
SDL_LogError(LOG_CATEGORY_MINIWIN, "SDL_CreateGPUTexture for backbuffer failed (%s)", SDL_GetError());
return nullptr;
}
SDL_GPUTextureCreateInfo depthTexInfo = textureInfo;
depthTexInfo.format = SDL_GPU_TEXTUREFORMAT_D32_FLOAT;
depthTexInfo.usage = SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET;
ScopedTexture depthTexture{device.ptr, SDL_CreateGPUTexture(device.ptr, &depthTexInfo)};
if (!depthTexture.ptr) {
SDL_LogError(LOG_CATEGORY_MINIWIN, "SDL_CreateGPUTexture for depth buffer (%s)", SDL_GetError());
return nullptr;
}
// Setup texture GPU-to-CPU transfer
SDL_GPUTransferBufferCreateInfo downloadBufferInfo = {};
downloadBufferInfo.usage = SDL_GPU_TRANSFERBUFFERUSAGE_DOWNLOAD;
downloadBufferInfo.size = width * height * 4;
ScopedTransferBuffer downloadBuffer{device.ptr, SDL_CreateGPUTransferBuffer(device.ptr, &downloadBufferInfo)};
if (!downloadBuffer.ptr) {
SDL_LogError(
LOG_CATEGORY_MINIWIN,
"SDL_CreateGPUTransferBuffer filed for download buffer (%s)",
SDL_GetError()
);
return nullptr; return nullptr;
} }
// Setup texture CPU-to-GPU transfer // Setup texture CPU-to-GPU transfer
SDL_GPUTransferBufferCreateInfo uploadBufferInfo = {}; SDL_GPUTransferBufferCreateInfo uploadBufferInfo = {};
uploadBufferInfo.usage = SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD; uploadBufferInfo.usage = SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD;
uploadBufferInfo.size = 256 * 256 * 4; // Largest known game texture int uploadBufferSize = 640 * 480 * 4; // Largest known game texture
uploadBufferInfo.size = uploadBufferSize;
ScopedTransferBuffer uploadBuffer{device.ptr, SDL_CreateGPUTransferBuffer(device.ptr, &uploadBufferInfo)}; ScopedTransferBuffer uploadBuffer{device.ptr, SDL_CreateGPUTransferBuffer(device.ptr, &uploadBufferInfo)};
if (!uploadBuffer.ptr) { if (!uploadBuffer.ptr) {
SDL_LogError(LOG_CATEGORY_MINIWIN, "SDL_CreateGPUTransferBuffer filed for upload buffer (%s)", SDL_GetError()); SDL_LogError(LOG_CATEGORY_MINIWIN, "SDL_CreateGPUTransferBuffer filed for upload buffer (%s)", SDL_GetError());
if (testWindow) {
SDL_DestroyWindow(window);
}
return nullptr; return nullptr;
} }
@ -265,31 +273,54 @@ Direct3DRMRenderer* Direct3DRMSDL3GPURenderer::Create(DWORD width, DWORD height)
ScopedSampler sampler{device.ptr, SDL_CreateGPUSampler(device.ptr, &samplerInfo)}; ScopedSampler sampler{device.ptr, SDL_CreateGPUSampler(device.ptr, &samplerInfo)};
if (!sampler.ptr) { if (!sampler.ptr) {
SDL_LogError(LOG_CATEGORY_MINIWIN, "Failed to create sampler: %s", SDL_GetError()); SDL_LogError(LOG_CATEGORY_MINIWIN, "Failed to create sampler: %s", SDL_GetError());
if (testWindow) {
SDL_DestroyWindow(window);
}
return nullptr; return nullptr;
} }
SDL_GPUSamplerCreateInfo uiSamplerInfo = {};
uiSamplerInfo.min_filter = SDL_GPU_FILTER_LINEAR;
uiSamplerInfo.mag_filter = SDL_GPU_FILTER_NEAREST;
uiSamplerInfo.mipmap_mode = SDL_GPU_SAMPLERMIPMAPMODE_LINEAR;
uiSamplerInfo.address_mode_u = SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE;
uiSamplerInfo.address_mode_v = SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE;
uiSamplerInfo.address_mode_w = SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE;
ScopedSampler uiSampler{device.ptr, SDL_CreateGPUSampler(device.ptr, &uiSamplerInfo)};
if (!uiSampler.ptr) {
SDL_LogError(LOG_CATEGORY_MINIWIN, "Failed to create sampler: %s", SDL_GetError());
if (testWindow) {
SDL_DestroyWindow(window);
}
return nullptr;
}
if (testWindow) {
SDL_ReleaseWindowFromGPUDevice(device.ptr, window);
SDL_DestroyWindow(window);
}
auto renderer = new Direct3DRMSDL3GPURenderer( auto renderer = new Direct3DRMSDL3GPURenderer(
width, width,
height, height,
device.ptr, device.ptr,
opaquePipeline.ptr, opaquePipeline.ptr,
transparentPipeline.ptr, transparentPipeline.ptr,
transferTexture.ptr, uiPipeline.ptr,
depthTexture.ptr,
sampler.ptr, sampler.ptr,
uiSampler.ptr,
uploadBuffer.ptr, uploadBuffer.ptr,
downloadBuffer.ptr uploadBufferSize
); );
// Release resources so they don't get cleaned up // Release resources so they don't get cleaned up
device.release(); device.release();
opaquePipeline.release(); opaquePipeline.release();
transparentPipeline.release(); transparentPipeline.release();
transferTexture.release(); uiPipeline.release();
depthTexture.release();
sampler.release(); sampler.release();
uiSampler.release();
uploadBuffer.release(); uploadBuffer.release();
downloadBuffer.release();
return renderer; return renderer;
} }
@ -300,17 +331,21 @@ Direct3DRMSDL3GPURenderer::Direct3DRMSDL3GPURenderer(
SDL_GPUDevice* device, SDL_GPUDevice* device,
SDL_GPUGraphicsPipeline* opaquePipeline, SDL_GPUGraphicsPipeline* opaquePipeline,
SDL_GPUGraphicsPipeline* transparentPipeline, SDL_GPUGraphicsPipeline* transparentPipeline,
SDL_GPUTexture* transferTexture, SDL_GPUGraphicsPipeline* uiPipeline,
SDL_GPUTexture* depthTexture,
SDL_GPUSampler* sampler, SDL_GPUSampler* sampler,
SDL_GPUSampler* uiSampler,
SDL_GPUTransferBuffer* uploadBuffer, SDL_GPUTransferBuffer* uploadBuffer,
SDL_GPUTransferBuffer* downloadBuffer int uploadBufferSize
) )
: m_width(width), m_height(height), m_device(device), m_opaquePipeline(opaquePipeline), : m_device(device), m_opaquePipeline(opaquePipeline), m_transparentPipeline(transparentPipeline),
m_transparentPipeline(transparentPipeline), m_transferTexture(transferTexture), m_depthTexture(depthTexture), m_uiPipeline(uiPipeline), m_sampler(sampler), m_uiSampler(uiSampler), m_uploadBuffer(uploadBuffer),
m_sampler(sampler), m_uploadBuffer(uploadBuffer), m_downloadBuffer(downloadBuffer) m_uploadBufferSize(uploadBufferSize)
{ {
SDL_Surface* dummySurface = SDL_CreateSurface(1, 1, SDL_PIXELFORMAT_ABGR8888); m_width = width;
m_height = height;
m_virtualWidth = width;
m_virtualHeight = height;
SDL_Surface* dummySurface = SDL_CreateSurface(1, 1, SDL_PIXELFORMAT_RGBA32);
if (!dummySurface) { if (!dummySurface) {
SDL_LogError(LOG_CATEGORY_MINIWIN, "Failed to create surface: %s", SDL_GetError()); SDL_LogError(LOG_CATEGORY_MINIWIN, "Failed to create surface: %s", SDL_GetError());
return; return;
@ -324,35 +359,67 @@ Direct3DRMSDL3GPURenderer::Direct3DRMSDL3GPURenderer(
SDL_UnlockSurface(dummySurface); SDL_UnlockSurface(dummySurface);
m_dummyTexture = CreateTextureFromSurface(dummySurface); m_dummyTexture = CreateTextureFromSurface(dummySurface);
if (!m_dummyTexture) {
SDL_DestroySurface(dummySurface);
SDL_LogError(LOG_CATEGORY_MINIWIN, "Failed to create surface: %s", SDL_GetError());
return;
}
SDL_DestroySurface(dummySurface); SDL_DestroySurface(dummySurface);
ViewportTransform viewportTransform = {1.0f, 0.0f, 0.0f};
Resize(m_width, m_height, viewportTransform);
m_uiMesh.vertices = {
{{0.0f, 0.0f, 0.0f}, {0, 0, -1}, {0.0f, 0.0f}},
{{1.0f, 0.0f, 0.0f}, {0, 0, -1}, {1.0f, 0.0f}},
{{1.0f, 1.0f, 0.0f}, {0, 0, -1}, {1.0f, 1.0f}},
{{0.0f, 1.0f, 0.0f}, {0, 0, -1}, {0.0f, 1.0f}}
};
m_uiMesh.indices = {0, 1, 2, 0, 2, 3};
m_uiMeshCache = UploadMesh(m_uiMesh);
} }
Direct3DRMSDL3GPURenderer::~Direct3DRMSDL3GPURenderer() Direct3DRMSDL3GPURenderer::~Direct3DRMSDL3GPURenderer()
{ {
SDL_ReleaseGPUTransferBuffer(m_device, m_downloadBuffer); SDL_ReleaseGPUBuffer(m_device, m_uiMeshCache.vertexBuffer);
SDL_ReleaseGPUBuffer(m_device, m_uiMeshCache.indexBuffer);
if (DDWindow) {
SDL_ReleaseWindowFromGPUDevice(m_device, DDWindow);
}
if (m_downloadBuffer) {
SDL_ReleaseGPUTransferBuffer(m_device, m_downloadBuffer);
}
if (m_uploadBuffer) { if (m_uploadBuffer) {
SDL_ReleaseGPUTransferBuffer(m_device, m_uploadBuffer); SDL_ReleaseGPUTransferBuffer(m_device, m_uploadBuffer);
} }
SDL_ReleaseGPUSampler(m_device, m_sampler); SDL_ReleaseGPUSampler(m_device, m_sampler);
SDL_ReleaseGPUTexture(m_device, m_dummyTexture); SDL_ReleaseGPUSampler(m_device, m_uiSampler);
SDL_ReleaseGPUTexture(m_device, m_depthTexture); if (m_dummyTexture) {
SDL_ReleaseGPUTexture(m_device, m_transferTexture); SDL_ReleaseGPUTexture(m_device, m_dummyTexture);
}
if (m_depthTexture) {
SDL_ReleaseGPUTexture(m_device, m_depthTexture);
}
if (m_transferTexture) {
SDL_ReleaseGPUTexture(m_device, m_transferTexture);
}
SDL_ReleaseGPUGraphicsPipeline(m_device, m_opaquePipeline); SDL_ReleaseGPUGraphicsPipeline(m_device, m_opaquePipeline);
SDL_ReleaseGPUGraphicsPipeline(m_device, m_transparentPipeline); SDL_ReleaseGPUGraphicsPipeline(m_device, m_transparentPipeline);
SDL_ReleaseGPUGraphicsPipeline(m_device, m_uiPipeline);
if (m_uploadFence) { if (m_uploadFence) {
SDL_ReleaseGPUFence(m_device, m_uploadFence); SDL_ReleaseGPUFence(m_device, m_uploadFence);
} }
SDL_DestroyGPUDevice(m_device); SDL_DestroyGPUDevice(m_device);
} }
void Direct3DRMSDL3GPURenderer::PushLights(const SceneLight* vertices, size_t count) void Direct3DRMSDL3GPURenderer::PushLights(const SceneLight* lights, size_t count)
{ {
if (count > 3) { if (count > 3) {
SDL_LogError(LOG_CATEGORY_MINIWIN, "Unsupported number of lights (%d)", static_cast<int>(count)); SDL_LogError(LOG_CATEGORY_MINIWIN, "Unsupported number of lights (%d)", static_cast<int>(count));
count = 3; count = 3;
} }
int lightCount = std::min(static_cast<int>(count), 3); int lightCount = std::min(static_cast<int>(count), 3);
memcpy(&m_fragmentShadingData.lights, vertices, sizeof(SceneLight) * lightCount); memcpy(&m_fragmentShadingData.lights, lights, sizeof(SceneLight) * lightCount);
m_fragmentShadingData.lightCount = lightCount; m_fragmentShadingData.lightCount = lightCount;
} }
@ -364,7 +431,7 @@ void Direct3DRMSDL3GPURenderer::SetProjection(const D3DRMMATRIX4D& projection, D
{ {
m_front = front; m_front = front;
m_back = back; m_back = back;
memcpy(&m_uniforms.projection, projection, sizeof(D3DRMMATRIX4D)); memcpy(&m_projection, projection, sizeof(D3DRMMATRIX4D));
} }
void Direct3DRMSDL3GPURenderer::WaitForPendingUpload() void Direct3DRMSDL3GPURenderer::WaitForPendingUpload()
@ -405,7 +472,7 @@ void Direct3DRMSDL3GPURenderer::AddTextureDestroyCallback(Uint32 id, IDirect3DRM
SDL_GPUTexture* Direct3DRMSDL3GPURenderer::CreateTextureFromSurface(SDL_Surface* surface) SDL_GPUTexture* Direct3DRMSDL3GPURenderer::CreateTextureFromSurface(SDL_Surface* surface)
{ {
ScopedSurface surf{SDL_ConvertSurface(surface, SDL_PIXELFORMAT_ABGR8888)}; ScopedSurface surf{SDL_ConvertSurface(surface, SDL_PIXELFORMAT_RGBA32)};
if (!surf.ptr) { if (!surf.ptr) {
SDL_LogError(LOG_CATEGORY_MINIWIN, "SDL_ConvertSurface (%s)", SDL_GetError()); SDL_LogError(LOG_CATEGORY_MINIWIN, "SDL_ConvertSurface (%s)", SDL_GetError());
return nullptr; return nullptr;
@ -607,6 +674,7 @@ void Direct3DRMSDL3GPURenderer::AddMeshDestroyCallback(Uint32 id, IDirect3DRMMes
auto* ctx = static_cast<SDLMeshDestroyContext*>(arg); auto* ctx = static_cast<SDLMeshDestroyContext*>(arg);
auto& cache = ctx->renderer->m_meshs[ctx->id]; auto& cache = ctx->renderer->m_meshs[ctx->id];
SDL_ReleaseGPUBuffer(ctx->renderer->m_device, cache.vertexBuffer); SDL_ReleaseGPUBuffer(ctx->renderer->m_device, cache.vertexBuffer);
SDL_ReleaseGPUBuffer(ctx->renderer->m_device, cache.indexBuffer);
cache.meshGroup = nullptr; cache.meshGroup = nullptr;
delete ctx; delete ctx;
}, },
@ -621,6 +689,7 @@ Uint32 Direct3DRMSDL3GPURenderer::GetMeshId(IDirect3DRMMesh* mesh, const MeshGro
if (cache.meshGroup == meshGroup) { if (cache.meshGroup == meshGroup) {
if (cache.version != meshGroup->version) { if (cache.version != meshGroup->version) {
SDL_ReleaseGPUBuffer(m_device, cache.vertexBuffer); SDL_ReleaseGPUBuffer(m_device, cache.vertexBuffer);
SDL_ReleaseGPUBuffer(m_device, cache.indexBuffer);
cache = std::move(UploadMesh(*meshGroup)); cache = std::move(UploadMesh(*meshGroup));
} }
return i; return i;
@ -643,16 +712,6 @@ Uint32 Direct3DRMSDL3GPURenderer::GetMeshId(IDirect3DRMMesh* mesh, const MeshGro
return (Uint32) (m_meshs.size() - 1); return (Uint32) (m_meshs.size() - 1);
} }
DWORD Direct3DRMSDL3GPURenderer::GetWidth()
{
return m_width;
}
DWORD Direct3DRMSDL3GPURenderer::GetHeight()
{
return m_height;
}
void Direct3DRMSDL3GPURenderer::GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc) void Direct3DRMSDL3GPURenderer::GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc)
{ {
halDesc->dcmColorModel = D3DCOLORMODEL::RGB; halDesc->dcmColorModel = D3DCOLORMODEL::RGB;
@ -708,32 +767,45 @@ SDL_GPUTransferBuffer* Direct3DRMSDL3GPURenderer::GetUploadBuffer(size_t size)
return m_uploadBuffer; return m_uploadBuffer;
} }
HRESULT Direct3DRMSDL3GPURenderer::BeginFrame() void Direct3DRMSDL3GPURenderer::StartRenderPass(float r, float g, float b, bool clear)
{ {
if (!DDBackBuffer) { m_cmdbuf = SDL_AcquireGPUCommandBuffer(m_device);
return DDERR_GENERIC; if (!m_cmdbuf) {
SDL_LogError(
LOG_CATEGORY_MINIWIN,
"SDL_AcquireGPUCommandBuffer in StartRenderPass failed (%s)",
SDL_GetError()
);
return;
} }
// Clear color and depth targets // Clear color and depth targets
SDL_GPUColorTargetInfo colorTargetInfo = {}; SDL_GPUColorTargetInfo colorTargetInfo = {};
colorTargetInfo.texture = m_transferTexture; colorTargetInfo.texture = m_transferTexture;
colorTargetInfo.clear_color = {0, 0, 0, 0}; colorTargetInfo.clear_color = {r, g, b, 1.0f};
colorTargetInfo.load_op = SDL_GPU_LOADOP_CLEAR; colorTargetInfo.load_op = clear ? SDL_GPU_LOADOP_CLEAR : SDL_GPU_LOADOP_DONT_CARE;
SDL_GPUDepthStencilTargetInfo depthStencilTargetInfo = {}; SDL_GPUDepthStencilTargetInfo depthStencilTargetInfo = {};
depthStencilTargetInfo.texture = m_depthTexture; depthStencilTargetInfo.texture = m_depthTexture;
depthStencilTargetInfo.clear_depth = 0.0f; depthStencilTargetInfo.clear_depth = 0.0f;
depthStencilTargetInfo.load_op = SDL_GPU_LOADOP_CLEAR; depthStencilTargetInfo.load_op = clear ? SDL_GPU_LOADOP_CLEAR : SDL_GPU_LOADOP_DONT_CARE;
depthStencilTargetInfo.store_op = SDL_GPU_STOREOP_STORE; depthStencilTargetInfo.store_op = SDL_GPU_STOREOP_STORE;
m_cmdbuf = SDL_AcquireGPUCommandBuffer(m_device);
if (!m_cmdbuf) {
SDL_LogError(LOG_CATEGORY_MINIWIN, "SDL_AcquireGPUCommandBuffer in BeginFrame failed (%s)", SDL_GetError());
return DDERR_GENERIC;
}
m_renderPass = SDL_BeginGPURenderPass(m_cmdbuf, &colorTargetInfo, 1, &depthStencilTargetInfo); m_renderPass = SDL_BeginGPURenderPass(m_cmdbuf, &colorTargetInfo, 1, &depthStencilTargetInfo);
}
void Direct3DRMSDL3GPURenderer::Clear(float r, float g, float b)
{
StartRenderPass(r, g, b, true);
}
HRESULT Direct3DRMSDL3GPURenderer::BeginFrame()
{
if (!m_renderPass) {
StartRenderPass(0, 0, 0, false);
}
SDL_BindGPUGraphicsPipeline(m_renderPass, m_opaquePipeline); SDL_BindGPUGraphicsPipeline(m_renderPass, m_opaquePipeline);
memcpy(&m_uniforms.projection, m_projection, sizeof(D3DRMMATRIX4D));
return DD_OK; return DD_OK;
} }
@ -746,6 +818,8 @@ void Direct3DRMSDL3GPURenderer::EnableTransparency()
void Direct3DRMSDL3GPURenderer::SubmitDraw( void Direct3DRMSDL3GPURenderer::SubmitDraw(
DWORD meshId, DWORD meshId,
const D3DRMMATRIX4D& modelViewMatrix, const D3DRMMATRIX4D& modelViewMatrix,
const D3DRMMATRIX4D& worldMatrix,
const D3DRMMATRIX4D& viewMatrix,
const Matrix3x3& normalMatrix, const Matrix3x3& normalMatrix,
const Appearance& appearance const Appearance& appearance
) )
@ -774,15 +848,210 @@ void Direct3DRMSDL3GPURenderer::SubmitDraw(
HRESULT Direct3DRMSDL3GPURenderer::FinalizeFrame() HRESULT Direct3DRMSDL3GPURenderer::FinalizeFrame()
{ {
SDL_EndGPURenderPass(m_renderPass); return DD_OK;
m_renderPass = nullptr; }
void Direct3DRMSDL3GPURenderer::Resize(int width, int height, const ViewportTransform& viewportTransform)
{
m_width = width;
m_height = height;
m_viewportTransform = viewportTransform;
if (!DDWindow) {
return;
}
if (m_transferTexture) {
SDL_ReleaseGPUTexture(m_device, m_transferTexture);
}
SDL_GPUTextureCreateInfo textureInfo = {};
textureInfo.type = SDL_GPU_TEXTURETYPE_2D;
textureInfo.format = SDL_GetGPUSwapchainTextureFormat(m_device, DDWindow);
textureInfo.usage = SDL_GPU_TEXTUREUSAGE_COLOR_TARGET | SDL_GPU_TEXTUREUSAGE_SAMPLER;
textureInfo.width = m_width;
textureInfo.height = m_height;
textureInfo.layer_count_or_depth = 1;
textureInfo.num_levels = 1;
textureInfo.sample_count = SDL_GPU_SAMPLECOUNT_1;
m_transferTexture = SDL_CreateGPUTexture(m_device, &textureInfo);
if (!m_transferTexture) {
SDL_LogError(LOG_CATEGORY_MINIWIN, "SDL_CreateGPUTexture for backbuffer failed (%s)", SDL_GetError());
return;
}
if (m_depthTexture) {
SDL_ReleaseGPUTexture(m_device, m_depthTexture);
}
SDL_GPUTextureCreateInfo depthTexInfo = textureInfo;
depthTexInfo.format = SDL_GPU_TEXTUREFORMAT_D32_FLOAT;
depthTexInfo.usage = SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET;
m_depthTexture = SDL_CreateGPUTexture(m_device, &depthTexInfo);
if (!m_depthTexture) {
SDL_LogError(LOG_CATEGORY_MINIWIN, "SDL_CreateGPUTexture for depth buffer (%s)", SDL_GetError());
return;
}
// Setup texture GPU-to-CPU transfer
SDL_GPUTransferBufferCreateInfo downloadBufferInfo = {};
downloadBufferInfo.usage = SDL_GPU_TRANSFERBUFFERUSAGE_DOWNLOAD;
downloadBufferInfo.size =
((m_width - (m_viewportTransform.offsetX * 2)) * (m_height - (m_viewportTransform.offsetY * 2))) * 4;
m_downloadBuffer = SDL_CreateGPUTransferBuffer(m_device, &downloadBufferInfo);
if (!m_downloadBuffer) {
SDL_LogError(
LOG_CATEGORY_MINIWIN,
"SDL_CreateGPUTransferBuffer filed for download buffer (%s)",
SDL_GetError()
);
return;
}
}
void Direct3DRMSDL3GPURenderer::Flip()
{
if (!m_cmdbuf) {
return;
}
if (m_renderPass) {
SDL_EndGPURenderPass(m_renderPass);
m_renderPass = nullptr;
}
SDL_GPUTexture* swapchainTexture;
if (!SDL_WaitAndAcquireGPUSwapchainTexture(m_cmdbuf, DDWindow, &swapchainTexture, nullptr, nullptr) ||
!swapchainTexture) {
SDL_Log("SDL_WaitAndAcquireGPUSwapchainTexture: %s", SDL_GetError());
return;
}
SDL_GPUBlitInfo blit = {};
blit.source.texture = m_transferTexture;
blit.source.w = m_width;
blit.source.h = m_height;
blit.destination.texture = swapchainTexture;
blit.destination.w = m_width;
blit.destination.h = m_height;
blit.load_op = SDL_GPU_LOADOP_DONT_CARE;
blit.flip_mode = SDL_FLIP_NONE;
blit.filter = SDL_GPU_FILTER_NEAREST;
blit.cycle = false;
SDL_BlitGPUTexture(m_cmdbuf, &blit);
SDL_SubmitGPUCommandBuffer(m_cmdbuf);
m_cmdbuf = nullptr;
}
// TODO use SDL_SetGPUScissor(SDL_GPURenderPass *render_pass, const SDL_Rect *scissor) when srcRect isn't 100% of
// texture
void Create2DTransformMatrix(
const SDL_Rect& dstRect,
float scale,
float offsetX,
float offsetY,
D3DRMMATRIX4D& outMatrix
)
{
float x = static_cast<float>(dstRect.x) * scale + offsetX;
float y = static_cast<float>(dstRect.y) * scale + offsetY;
float w = static_cast<float>(dstRect.w) * scale;
float h = static_cast<float>(dstRect.h) * scale;
D3DVALUE tmp[4][4] = {{w, 0, 0, 0}, {0, h, 0, 0}, {0, 0, 1, 0}, {x, y, 0, 1}};
memcpy(outMatrix, tmp, sizeof(tmp));
}
void CreateOrthographicProjection(float width, float height, D3DRMMATRIX4D& outProj)
{
D3DVALUE tmp[4][4] = {
{2.0f / width, 0.0f, 0.0f, 0.0f},
{0.0f, -2.0f / height, 0.0f, 0.0f},
{0.0f, 0.0f, 1.0f, 0.0f},
{-1.0f, 1.0f, 0.0f, 1.0f}
};
memcpy(outProj, tmp, sizeof(tmp));
}
void Direct3DRMSDL3GPURenderer::Draw2DImage(Uint32 textureId, const SDL_Rect& srcRect, const SDL_Rect& dstRect)
{
if (!m_renderPass) {
StartRenderPass(0, 0, 0, false);
}
SDL_BindGPUGraphicsPipeline(m_renderPass, m_uiPipeline);
const SDL3TextureCache& tex = m_textures[textureId];
auto surface = static_cast<DirectDrawSurfaceImpl*>(tex.texture->m_surface);
float scaleX = static_cast<float>(dstRect.w) / srcRect.w;
float scaleY = static_cast<float>(dstRect.h) / srcRect.h;
SDL_Rect expandedDstRect = {
static_cast<int>(std::round(dstRect.x - srcRect.x * scaleX)),
static_cast<int>(std::round(dstRect.y - srcRect.y * scaleY)),
static_cast<int>(std::round(static_cast<float>(surface->m_surface->w) * scaleX)),
static_cast<int>(std::round(static_cast<float>(surface->m_surface->h) * scaleY)),
};
Create2DTransformMatrix(
expandedDstRect,
m_viewportTransform.scale,
m_viewportTransform.offsetX,
m_viewportTransform.offsetY,
m_uniforms.worldViewMatrix
);
CreateOrthographicProjection((float) m_width, (float) m_height, m_uniforms.projection);
SceneLight fullBright = {{1, 1, 1, 1}, {0, 0, 0}, 0, {0, 0, 0}, 0};
memcpy(&m_fragmentShadingData.lights, &fullBright, sizeof(SceneLight));
m_fragmentShadingData.lightCount = 1;
m_fragmentShadingData.color = {0xff, 0xff, 0xff, 0xff};
m_fragmentShadingData.shininess = 0.0f;
m_fragmentShadingData.useTexture = 1;
SDL_GPUTextureSamplerBinding samplerBinding = {tex.gpuTexture, m_uiSampler};
SDL_BindGPUFragmentSamplers(m_renderPass, 0, &samplerBinding, 1);
SDL_PushGPUVertexUniformData(m_cmdbuf, 0, &m_uniforms, sizeof(m_uniforms));
SDL_PushGPUFragmentUniformData(m_cmdbuf, 0, &m_fragmentShadingData, sizeof(m_fragmentShadingData));
SDL_GPUBufferBinding vertexBufferBinding = {m_uiMeshCache.vertexBuffer};
SDL_BindGPUVertexBuffers(m_renderPass, 0, &vertexBufferBinding, 1);
SDL_GPUBufferBinding indexBufferBinding = {m_uiMeshCache.indexBuffer};
SDL_BindGPUIndexBuffer(m_renderPass, &indexBufferBinding, SDL_GPU_INDEXELEMENTSIZE_16BIT);
SDL_Rect scissor;
scissor.x = static_cast<int>(std::round(dstRect.x * m_viewportTransform.scale + m_viewportTransform.offsetX));
scissor.y = static_cast<int>(std::round(dstRect.y * m_viewportTransform.scale + m_viewportTransform.offsetY));
scissor.w = static_cast<int>(std::round(dstRect.w * m_viewportTransform.scale));
scissor.h = static_cast<int>(std::round(dstRect.h * m_viewportTransform.scale));
SDL_SetGPUScissor(m_renderPass, &scissor);
SDL_DrawGPUIndexedPrimitives(m_renderPass, m_uiMeshCache.indexCount, 1, 0, 0, 0);
SDL_Rect fullViewport = {0, 0, m_width, m_height};
SDL_SetGPUScissor(m_renderPass, &fullViewport);
}
void Direct3DRMSDL3GPURenderer::Download(SDL_Surface* target)
{
if (!m_cmdbuf) {
StartRenderPass(0, 0, 0, false);
}
if (m_renderPass) {
SDL_EndGPURenderPass(m_renderPass);
m_renderPass = nullptr;
}
const int offsetX = static_cast<int>(m_viewportTransform.offsetX);
const int offsetY = static_cast<int>(m_viewportTransform.offsetY);
const int width = m_width - offsetX * 2;
const int height = m_height - offsetY * 2;
// Download rendered image
SDL_GPUTextureRegion region = {}; SDL_GPUTextureRegion region = {};
region.texture = m_transferTexture; region.texture = m_transferTexture;
region.w = m_width; region.x = offsetX;
region.h = m_height; region.y = offsetY;
region.w = width;
region.h = height;
region.d = 1; region.d = 1;
SDL_GPUTextureTransferInfo transferInfo = {}; SDL_GPUTextureTransferInfo transferInfo = {};
transferInfo.transfer_buffer = m_downloadBuffer; transferInfo.transfer_buffer = m_downloadBuffer;
@ -792,27 +1061,24 @@ HRESULT Direct3DRMSDL3GPURenderer::FinalizeFrame()
WaitForPendingUpload(); WaitForPendingUpload();
// Render the frame
SDL_GPUFence* fence = SDL_SubmitGPUCommandBufferAndAcquireFence(m_cmdbuf); SDL_GPUFence* fence = SDL_SubmitGPUCommandBufferAndAcquireFence(m_cmdbuf);
m_cmdbuf = nullptr; m_cmdbuf = nullptr;
if (!fence) {
return DDERR_GENERIC; if (!fence || !SDL_WaitForGPUFences(m_device, true, &fence, 1)) {
SDL_ReleaseGPUFence(m_device, fence);
return;
} }
bool success = SDL_WaitForGPUFences(m_device, true, &fence, 1);
SDL_ReleaseGPUFence(m_device, fence); SDL_ReleaseGPUFence(m_device, fence);
if (!success) {
return DDERR_GENERIC;
}
void* downloadedData = SDL_MapGPUTransferBuffer(m_device, m_downloadBuffer, false); void* downloadedData = SDL_MapGPUTransferBuffer(m_device, m_downloadBuffer, false);
if (!downloadedData) { if (!downloadedData) {
return DDERR_GENERIC; return;
} }
SDL_Surface* renderedImage = SDL_Surface* renderedImage =
SDL_CreateSurfaceFrom(m_width, m_height, SDL_PIXELFORMAT_ABGR8888, downloadedData, m_width * 4); SDL_CreateSurfaceFrom(width, height, SDL_PIXELFORMAT_ARGB8888, downloadedData, width * 4);
SDL_BlitSurface(renderedImage, nullptr, DDBackBuffer, nullptr);
SDL_BlitSurfaceScaled(renderedImage, nullptr, target, nullptr, SDL_SCALEMODE_NEAREST);
SDL_DestroySurface(renderedImage); SDL_DestroySurface(renderedImage);
SDL_UnmapGPUTransferBuffer(m_device, m_downloadBuffer); SDL_UnmapGPUTransferBuffer(m_device, m_downloadBuffer);
return DD_OK;
} }

View File

@ -10,9 +10,9 @@
// DXIL only makes sense on Windows platforms // DXIL only makes sense on Windows platforms
#if defined(SDL_PLATFORM_WINDOWS) #if defined(SDL_PLATFORM_WINDOWS)
static const Uint8 SolidColor_frag_dxil[6640] = { static const Uint8 SolidColor_frag_dxil[6648] = {
0x44, 0x58, 0x42, 0x43, 0x91, 0x24, 0xbe, 0xd8, 0x43, 0x8d, 0x7f, 0xf4, 0x71, 0x2b, 0x59, 0x98, 0x44, 0x58, 0x42, 0x43, 0xd8, 0xfe, 0x4c, 0xec, 0x17, 0x1b, 0x52, 0xee, 0xf7, 0xc8, 0x8d, 0xcf,
0x2d, 0x7f, 0x8d, 0xac, 0x01, 0x00, 0x00, 0x00, 0xf0, 0x19, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x47, 0x0e, 0xfe, 0xb7, 0x01, 0x00, 0x00, 0x00, 0xf8, 0x19, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
0x3c, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0xf4, 0x00, 0x00, 0x00, 0x58, 0x01, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0xf4, 0x00, 0x00, 0x00, 0x58, 0x01, 0x00, 0x00,
0xc4, 0x02, 0x00, 0x00, 0x94, 0x0c, 0x00, 0x00, 0xb0, 0x0c, 0x00, 0x00, 0x53, 0x46, 0x49, 0x30, 0xc4, 0x02, 0x00, 0x00, 0x94, 0x0c, 0x00, 0x00, 0xb0, 0x0c, 0x00, 0x00, 0x53, 0x46, 0x49, 0x30,
0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x53, 0x47, 0x31, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x53, 0x47, 0x31,
@ -52,7 +52,7 @@ static const Uint8 SolidColor_frag_dxil[6640] = {
0x03, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x44, 0x10, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x44, 0x10,
0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x11, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x11,
0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x53, 0x54, 0x41, 0x54, 0xc8, 0x09, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x53, 0x54, 0x41, 0x54, 0xc8, 0x09, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00,
@ -113,9 +113,9 @@ static const Uint8 SolidColor_frag_dxil[6640] = {
0x8c, 0x09, 0x26, 0x47, 0xc6, 0x04, 0x43, 0x22, 0x4a, 0x60, 0x04, 0xa0, 0x18, 0x8a, 0xa0, 0x24, 0x8c, 0x09, 0x26, 0x47, 0xc6, 0x04, 0x43, 0x22, 0x4a, 0x60, 0x04, 0xa0, 0x18, 0x8a, 0xa0, 0x24,
0xca, 0xa0, 0x80, 0x05, 0x0a, 0xac, 0x1c, 0x4a, 0xa3, 0x10, 0x0a, 0xa4, 0x80, 0x0a, 0x54, 0xa0, 0xca, 0xa0, 0x80, 0x05, 0x0a, 0xac, 0x1c, 0x4a, 0xa3, 0x10, 0x0a, 0xa4, 0x80, 0x0a, 0x54, 0xa0,
0x50, 0x05, 0x0a, 0x56, 0xa0, 0x14, 0x0a, 0x57, 0xa0, 0x20, 0xca, 0xa3, 0x06, 0xca, 0x34, 0xa0, 0x50, 0x05, 0x0a, 0x56, 0xa0, 0x14, 0x0a, 0x57, 0xa0, 0x20, 0xca, 0xa3, 0x06, 0xca, 0x34, 0xa0,
0x24, 0x07, 0xa8, 0x28, 0x89, 0x11, 0x80, 0x22, 0x28, 0x83, 0x42, 0x28, 0x90, 0x12, 0x29, 0x81, 0x2c, 0x07, 0xa8, 0x28, 0x89, 0x11, 0x80, 0x22, 0x28, 0x83, 0x42, 0x28, 0x90, 0x12, 0x29, 0x81,
0x1a, 0xa0, 0xad, 0x06, 0x48, 0x9c, 0x01, 0xa0, 0x71, 0x06, 0x80, 0xca, 0x19, 0x00, 0x32, 0x67, 0x1a, 0xa0, 0xad, 0x06, 0x48, 0x9c, 0x01, 0xa0, 0x71, 0x06, 0x80, 0xca, 0x19, 0x00, 0x32, 0x67,
0x00, 0x08, 0x9d, 0x01, 0xa0, 0x74, 0x2c, 0x09, 0x22, 0x8e, 0xe3, 0x00, 0x8e, 0x03, 0x00, 0x8e, 0x00, 0x08, 0x9d, 0x01, 0xa0, 0x74, 0x2c, 0x09, 0x22, 0x8e, 0xe3, 0x00, 0x9e, 0x07, 0x00, 0x8e,
0xe3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0xe3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
0x1a, 0x03, 0x4c, 0x90, 0x46, 0x02, 0x13, 0xc4, 0x31, 0x20, 0xc3, 0x1b, 0x43, 0x81, 0x93, 0x4b, 0x1a, 0x03, 0x4c, 0x90, 0x46, 0x02, 0x13, 0xc4, 0x31, 0x20, 0xc3, 0x1b, 0x43, 0x81, 0x93, 0x4b,
0xb3, 0x0b, 0xa3, 0x2b, 0x4b, 0x01, 0x89, 0x71, 0xc1, 0x71, 0x81, 0x71, 0xa1, 0xb9, 0xc1, 0xc9, 0xb3, 0x0b, 0xa3, 0x2b, 0x4b, 0x01, 0x89, 0x71, 0xc1, 0x71, 0x81, 0x71, 0xa1, 0xb9, 0xc1, 0xc9,
@ -213,10 +213,10 @@ static const Uint8 SolidColor_frag_dxil[6640] = {
0xe3, 0x4b, 0x93, 0x13, 0x11, 0x28, 0x35, 0x3d, 0xd4, 0xe4, 0x17, 0xb7, 0x6d, 0x04, 0xcf, 0x70, 0xe3, 0x4b, 0x93, 0x13, 0x11, 0x28, 0x35, 0x3d, 0xd4, 0xe4, 0x17, 0xb7, 0x6d, 0x04, 0xcf, 0x70,
0xf9, 0xce, 0xe3, 0x53, 0x0d, 0x10, 0x61, 0x7e, 0x71, 0xdb, 0x06, 0x40, 0x30, 0x00, 0xd2, 0x00, 0xf9, 0xce, 0xe3, 0x53, 0x0d, 0x10, 0x61, 0x7e, 0x71, 0xdb, 0x06, 0x40, 0x30, 0x00, 0xd2, 0x00,
0x00, 0x00, 0x00, 0x00, 0x48, 0x41, 0x53, 0x48, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x41, 0x53, 0x48, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x58, 0x63, 0x6a, 0xf1, 0xca, 0xdc, 0xf6, 0x75, 0x3d, 0x1e, 0x21, 0x9a, 0xb8, 0xa2, 0x91, 0xc3, 0xeb, 0x0f, 0x40, 0x5f, 0x0e, 0x75, 0xec, 0xd9, 0x61, 0x1b, 0x68, 0x81, 0x54, 0xd3, 0xf4, 0x48,
0x44, 0x58, 0x49, 0x4c, 0x38, 0x0d, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x4e, 0x03, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4c, 0x40, 0x0d, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x50, 0x03, 0x00, 0x00,
0x44, 0x58, 0x49, 0x4c, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x20, 0x0d, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4c, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x28, 0x0d, 0x00, 0x00,
0x42, 0x43, 0xc0, 0xde, 0x21, 0x0c, 0x00, 0x00, 0x45, 0x03, 0x00, 0x00, 0x0b, 0x82, 0x20, 0x00, 0x42, 0x43, 0xc0, 0xde, 0x21, 0x0c, 0x00, 0x00, 0x47, 0x03, 0x00, 0x00, 0x0b, 0x82, 0x20, 0x00,
0x02, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x07, 0x81, 0x23, 0x91, 0x41, 0xc8, 0x04, 0x49, 0x02, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x07, 0x81, 0x23, 0x91, 0x41, 0xc8, 0x04, 0x49,
0x06, 0x10, 0x32, 0x39, 0x92, 0x01, 0x84, 0x0c, 0x25, 0x05, 0x08, 0x19, 0x1e, 0x04, 0x8b, 0x62, 0x06, 0x10, 0x32, 0x39, 0x92, 0x01, 0x84, 0x0c, 0x25, 0x05, 0x08, 0x19, 0x1e, 0x04, 0x8b, 0x62,
0x80, 0x18, 0x45, 0x02, 0x42, 0x92, 0x0b, 0x42, 0xc4, 0x10, 0x32, 0x14, 0x38, 0x08, 0x18, 0x4b, 0x80, 0x18, 0x45, 0x02, 0x42, 0x92, 0x0b, 0x42, 0xc4, 0x10, 0x32, 0x14, 0x38, 0x08, 0x18, 0x4b,
@ -272,7 +272,7 @@ static const Uint8 SolidColor_frag_dxil[6640] = {
0x8c, 0x09, 0x26, 0x47, 0xc6, 0x04, 0x43, 0x22, 0x4a, 0x60, 0x04, 0xa0, 0x20, 0x8a, 0xa1, 0x08, 0x8c, 0x09, 0x26, 0x47, 0xc6, 0x04, 0x43, 0x22, 0x4a, 0x60, 0x04, 0xa0, 0x20, 0x8a, 0xa1, 0x08,
0x4a, 0xa2, 0x0c, 0x0a, 0x58, 0xa0, 0x1c, 0xca, 0xa3, 0x06, 0xa8, 0x28, 0x89, 0x11, 0x80, 0x22, 0x4a, 0xa2, 0x0c, 0x0a, 0x58, 0xa0, 0x1c, 0xca, 0xa3, 0x06, 0xa8, 0x28, 0x89, 0x11, 0x80, 0x22,
0x28, 0x83, 0x42, 0x28, 0x90, 0x12, 0x29, 0x81, 0x1a, 0x20, 0x71, 0x06, 0x80, 0xcc, 0x19, 0x00, 0x28, 0x83, 0x42, 0x28, 0x90, 0x12, 0x29, 0x81, 0x1a, 0x20, 0x71, 0x06, 0x80, 0xcc, 0x19, 0x00,
0x42, 0x67, 0x00, 0x28, 0x1d, 0x4b, 0x82, 0x88, 0xe3, 0x38, 0x80, 0xe3, 0x00, 0x80, 0xe3, 0x38, 0x42, 0x67, 0x00, 0x28, 0x1d, 0x4b, 0x82, 0x88, 0xe3, 0x38, 0x80, 0xe7, 0x01, 0x80, 0xe3, 0x38,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0x18, 0x00, 0x00, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0x18, 0x00, 0x00, 0x7d, 0x00, 0x00, 0x00,
0x1a, 0x03, 0x4c, 0x90, 0x46, 0x02, 0x13, 0xc4, 0x31, 0x20, 0xc3, 0x1b, 0x43, 0x81, 0x93, 0x4b, 0x1a, 0x03, 0x4c, 0x90, 0x46, 0x02, 0x13, 0xc4, 0x31, 0x20, 0xc3, 0x1b, 0x43, 0x81, 0x93, 0x4b,
0xb3, 0x0b, 0xa3, 0x2b, 0x4b, 0x01, 0x89, 0x71, 0xc1, 0x71, 0x81, 0x71, 0xa1, 0xb9, 0xc1, 0xc9, 0xb3, 0x0b, 0xa3, 0x2b, 0x4b, 0x01, 0x89, 0x71, 0xc1, 0x71, 0x81, 0x71, 0xa1, 0xb9, 0xc1, 0xc9,
@ -336,7 +336,7 @@ static const Uint8 SolidColor_frag_dxil[6640] = {
0x9b, 0x01, 0x34, 0x5c, 0xbe, 0xf3, 0xf8, 0x12, 0xc0, 0x3c, 0x0b, 0xe1, 0x17, 0xb7, 0x6d, 0x02, 0x9b, 0x01, 0x34, 0x5c, 0xbe, 0xf3, 0xf8, 0x12, 0xc0, 0x3c, 0x0b, 0xe1, 0x17, 0xb7, 0x6d, 0x02,
0xd5, 0x70, 0xf9, 0xce, 0xe3, 0x4b, 0x93, 0x13, 0x11, 0x28, 0x35, 0x3d, 0xd4, 0xe4, 0x17, 0xb7, 0xd5, 0x70, 0xf9, 0xce, 0xe3, 0x4b, 0x93, 0x13, 0x11, 0x28, 0x35, 0x3d, 0xd4, 0xe4, 0x17, 0xb7,
0x6d, 0x04, 0xcf, 0x70, 0xf9, 0xce, 0xe3, 0x53, 0x0d, 0x10, 0x61, 0x7e, 0x71, 0xdb, 0x06, 0x40, 0x6d, 0x04, 0xcf, 0x70, 0xf9, 0xce, 0xe3, 0x53, 0x0d, 0x10, 0x61, 0x7e, 0x71, 0xdb, 0x06, 0x40,
0x30, 0x00, 0xd2, 0x00, 0x61, 0x20, 0x00, 0x00, 0x64, 0x01, 0x00, 0x00, 0x13, 0x04, 0x52, 0x2c, 0x30, 0x00, 0xd2, 0x00, 0x61, 0x20, 0x00, 0x00, 0x66, 0x01, 0x00, 0x00, 0x13, 0x04, 0x52, 0x2c,
0x10, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0xb4, 0x8d, 0x00, 0x10, 0x51, 0x78, 0x05, 0x52, 0x10, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0xb4, 0x8d, 0x00, 0x10, 0x51, 0x78, 0x05, 0x52,
0x30, 0xa5, 0x32, 0x03, 0x50, 0x76, 0x85, 0x50, 0x46, 0x85, 0x54, 0x6e, 0xa5, 0x50, 0x72, 0x25, 0x30, 0xa5, 0x32, 0x03, 0x50, 0x76, 0x85, 0x50, 0x46, 0x85, 0x54, 0x6e, 0xa5, 0x50, 0x72, 0x25,
0x53, 0xfe, 0x03, 0xe5, 0x42, 0xc3, 0x0c, 0xc0, 0x18, 0x41, 0x48, 0x82, 0x21, 0xde, 0x8d, 0x11, 0x53, 0xfe, 0x03, 0xe5, 0x42, 0xc3, 0x0c, 0xc0, 0x18, 0x41, 0x48, 0x82, 0x21, 0xde, 0x8d, 0x11,
@ -413,25 +413,26 @@ static const Uint8 SolidColor_frag_dxil[6640] = {
0xc4, 0xe0, 0x00, 0x40, 0x10, 0x0c, 0x9c, 0xd8, 0x58, 0x8b, 0x21, 0x2c, 0x46, 0x13, 0xb8, 0x61, 0xc4, 0xe0, 0x00, 0x40, 0x10, 0x0c, 0x9c, 0xd8, 0x58, 0x8b, 0x21, 0x2c, 0x46, 0x13, 0xb8, 0x61,
0xb8, 0x21, 0x68, 0x0d, 0x30, 0x98, 0x65, 0x88, 0xa0, 0x60, 0xc4, 0xe0, 0x01, 0x40, 0x10, 0x0c, 0xb8, 0x21, 0x68, 0x0d, 0x30, 0x98, 0x65, 0x88, 0xa0, 0x60, 0xc4, 0xe0, 0x01, 0x40, 0x10, 0x0c,
0xa6, 0xd9, 0xb0, 0x0b, 0xb1, 0x08, 0x8b, 0x9d, 0xd0, 0x89, 0xb3, 0x38, 0x0b, 0xd7, 0x70, 0x0d, 0xa6, 0xd9, 0xb0, 0x0b, 0xb1, 0x08, 0x8b, 0x9d, 0xd0, 0x89, 0xb3, 0x38, 0x0b, 0xd7, 0x70, 0x0d,
0xb9, 0x38, 0x8b, 0xd1, 0x84, 0x00, 0x18, 0x4d, 0x10, 0x82, 0xd1, 0x84, 0x41, 0xb0, 0x21, 0x91, 0xb9, 0x38, 0x8b, 0xd1, 0x84, 0x00, 0x18, 0x4d, 0x10, 0x82, 0xd1, 0x84, 0x41, 0x18, 0x4d, 0x20,
0x8f, 0x0d, 0x89, 0x7c, 0x6c, 0x48, 0xe4, 0x33, 0x62, 0x70, 0x00, 0x20, 0x08, 0x06, 0xce, 0x6e, 0x06, 0x23, 0x14, 0xf9, 0x18, 0xa1, 0xc8, 0xc7, 0x08, 0x45, 0x3e, 0x23, 0x06, 0x07, 0x00, 0x82,
0xd8, 0xc5, 0xa0, 0x16, 0x23, 0x06, 0x07, 0x00, 0x82, 0x60, 0xe0, 0xf0, 0xc6, 0x5d, 0x0c, 0x6b, 0x60, 0xe0, 0xf0, 0xc6, 0x5d, 0x0c, 0x6b, 0x31, 0x62, 0x70, 0x00, 0x20, 0x08, 0x06, 0x4e, 0x6f,
0x31, 0x62, 0x70, 0x00, 0x20, 0x08, 0x06, 0x4e, 0x6f, 0xe0, 0xc5, 0xc0, 0x16, 0x23, 0x06, 0x07, 0xe0, 0xc5, 0xc0, 0x16, 0x23, 0x06, 0x07, 0x00, 0x82, 0x60, 0xe0, 0xf8, 0x46, 0x5e, 0x0c, 0x6d,
0x00, 0x82, 0x60, 0xe0, 0xf8, 0x06, 0x5e, 0x0c, 0x6e, 0x31, 0x62, 0x70, 0x00, 0x20, 0x08, 0x06, 0x31, 0x62, 0x70, 0x00, 0x20, 0x08, 0x06, 0xce, 0x6f, 0xe4, 0xc5, 0xf0, 0x16, 0x23, 0x06, 0x07,
0xce, 0x6f, 0xe4, 0xc5, 0xf0, 0x16, 0x23, 0x06, 0x07, 0x00, 0x82, 0x60, 0xe0, 0x80, 0x87, 0x5e, 0x00, 0x82, 0x60, 0xe0, 0x80, 0x87, 0x5e, 0x0c, 0x70, 0x31, 0x62, 0x70, 0x00, 0x20, 0x08, 0x06,
0x0c, 0x70, 0x31, 0x4b, 0x10, 0x0d, 0x54, 0x0c, 0x06, 0x44, 0x06, 0xcf, 0x40, 0xc5, 0x60, 0x40, 0x4e, 0x78, 0xec, 0xc5, 0x10, 0x17, 0xb3, 0x04, 0xd1, 0x40, 0xc5, 0x60, 0x40, 0x66, 0xf0, 0x0c,
0x64, 0xf0, 0x0c, 0x54, 0x0c, 0x06, 0x44, 0x06, 0xcf, 0x88, 0x41, 0x02, 0x80, 0x20, 0x18, 0x20, 0x54, 0x0c, 0x06, 0x64, 0x06, 0xcf, 0x40, 0xc5, 0x60, 0x40, 0x66, 0xf0, 0x0c, 0x54, 0x0c, 0x1a,
0xe7, 0xc1, 0x17, 0xbe, 0xe1, 0x1b, 0xb3, 0x31, 0x8c, 0x18, 0x24, 0x00, 0x08, 0x82, 0x01, 0x72, 0x64, 0x0b, 0xcf, 0x88, 0x41, 0x02, 0x80, 0x20, 0x18, 0x20, 0xe9, 0xe1, 0x17, 0xe0, 0x01, 0x1e,
0x1e, 0x7c, 0xe1, 0x1b, 0xbe, 0xd1, 0x1a, 0xc2, 0x88, 0x41, 0x02, 0x80, 0x20, 0x18, 0x20, 0xe7, 0xb5, 0x41, 0x8c, 0x18, 0x24, 0x00, 0x08, 0x82, 0x01, 0x92, 0x1e, 0x7e, 0x01, 0x1e, 0xe0, 0xf1,
0xc1, 0x17, 0xbe, 0xe1, 0x1b, 0xb2, 0x11, 0x8c, 0x18, 0x24, 0x00, 0x08, 0x82, 0x01, 0x72, 0x1e, 0x1a, 0xc3, 0x88, 0x41, 0x02, 0x80, 0x20, 0x18, 0x20, 0xe9, 0xe1, 0x17, 0xe0, 0x01, 0x1e, 0xb4,
0x7c, 0xe1, 0x1b, 0xbe, 0x11, 0x1b, 0x6a, 0x30, 0x62, 0x90, 0x00, 0x20, 0x08, 0x06, 0xc8, 0x79, 0x21, 0x8c, 0x18, 0x24, 0x00, 0x08, 0x82, 0x01, 0x92, 0x1e, 0x7e, 0x01, 0x1e, 0xe0, 0x31, 0x1b,
0xf0, 0xc5, 0x6f, 0xf8, 0xc6, 0x6c, 0x98, 0x05, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc1, 0x88, 0x41, 0x02, 0x80, 0x20, 0x18, 0x20, 0xe9, 0xe1, 0x17, 0xe1, 0x01, 0x1e, 0xb5, 0x81,
0x16, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
}; };
#endif #endif
// MSL only makes sense on Apple platforms // MSL only makes sense on Apple platforms
#if defined(SDL_PLATFORM_APPLE) #if defined(SDL_PLATFORM_APPLE)
static const Uint8 SolidColor_frag_msl[3333] = { static const Uint8 SolidColor_frag_msl[3377] = {
0x23, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x20, 0x3c, 0x6d, 0x65, 0x74, 0x61, 0x6c, 0x5f, 0x23, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x20, 0x3c, 0x6d, 0x65, 0x74, 0x61, 0x6c, 0x5f,
0x73, 0x74, 0x64, 0x6c, 0x69, 0x62, 0x3e, 0x0a, 0x23, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x73, 0x74, 0x64, 0x6c, 0x69, 0x62, 0x3e, 0x0a, 0x23, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65,
0x20, 0x3c, 0x73, 0x69, 0x6d, 0x64, 0x2f, 0x73, 0x69, 0x6d, 0x64, 0x2e, 0x68, 0x3e, 0x0a, 0x0a, 0x20, 0x3c, 0x73, 0x69, 0x6d, 0x64, 0x2f, 0x73, 0x69, 0x6d, 0x64, 0x2e, 0x68, 0x3e, 0x0a, 0x0a,
@ -620,32 +621,35 @@ static const Uint8 SolidColor_frag_msl[3333] = {
0x78, 0x79, 0x7a, 0x29, 0x20, 0x2b, 0x20, 0x5f, 0x36, 0x32, 0x2c, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x78, 0x79, 0x7a, 0x29, 0x20, 0x2b, 0x20, 0x5f, 0x36, 0x32, 0x2c, 0x20, 0x66, 0x6c, 0x6f, 0x61,
0x74, 0x33, 0x28, 0x30, 0x2e, 0x30, 0x29, 0x2c, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x28, 0x74, 0x33, 0x28, 0x30, 0x2e, 0x30, 0x29, 0x2c, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x28,
0x31, 0x2e, 0x30, 0x29, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x31, 0x2e, 0x30, 0x29, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74,
0x33, 0x20, 0x5f, 0x31, 0x36, 0x34, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x34, 0x20, 0x5f, 0x31, 0x37, 0x34, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28,
0x46, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x53, 0x68, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x44, 0x46, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x53, 0x68, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x44,
0x61, 0x74, 0x61, 0x2e, 0x55, 0x73, 0x65, 0x54, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x20, 0x21, 0x61, 0x74, 0x61, 0x2e, 0x55, 0x73, 0x65, 0x54, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x20, 0x21,
0x3d, 0x20, 0x30, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3d, 0x20, 0x30, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x5f, 0x31, 0x36, 0x34, 0x20, 0x3d, 0x20, 0x66, 0x61, 0x73, 0x74, 0x3a, 0x3a, 0x20, 0x20, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x5f, 0x31, 0x36, 0x31, 0x20, 0x3d,
0x63, 0x6c, 0x61, 0x6d, 0x70, 0x28, 0x54, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x2e, 0x73, 0x61, 0x20, 0x54, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x2e, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x28,
0x6d, 0x70, 0x6c, 0x65, 0x28, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x72, 0x2c, 0x20, 0x69, 0x6e, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x72, 0x2c, 0x20, 0x69, 0x6e, 0x2e, 0x69, 0x6e, 0x5f, 0x76,
0x2e, 0x69, 0x6e, 0x5f, 0x76, 0x61, 0x72, 0x5f, 0x54, 0x45, 0x58, 0x43, 0x4f, 0x4f, 0x52, 0x44, 0x61, 0x72, 0x5f, 0x54, 0x45, 0x58, 0x43, 0x4f, 0x4f, 0x52, 0x44, 0x31, 0x29, 0x3b, 0x0a, 0x20,
0x31, 0x29, 0x2e, 0x78, 0x79, 0x7a, 0x20, 0x2a, 0x20, 0x5f, 0x31, 0x35, 0x31, 0x2c, 0x20, 0x66, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x5f, 0x31, 0x37, 0x34, 0x20, 0x3d, 0x20, 0x66, 0x6c,
0x6c, 0x6f, 0x61, 0x74, 0x33, 0x28, 0x30, 0x2e, 0x30, 0x29, 0x2c, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x6f, 0x61, 0x74, 0x34, 0x28, 0x66, 0x61, 0x73, 0x74, 0x3a, 0x3a, 0x63, 0x6c, 0x61, 0x6d, 0x70,
0x74, 0x33, 0x28, 0x31, 0x2e, 0x30, 0x29, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x28, 0x5f, 0x31, 0x36, 0x31, 0x2e, 0x78, 0x79, 0x7a, 0x20, 0x2a, 0x20, 0x5f, 0x31, 0x35, 0x31,
0x20, 0x20, 0x20, 0x20, 0x65, 0x6c, 0x73, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7b, 0x0a, 0x20, 0x2c, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x28, 0x30, 0x2e, 0x30, 0x29, 0x2c, 0x20, 0x66,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x5f, 0x31, 0x36, 0x34, 0x20, 0x3d, 0x20, 0x5f, 0x31, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x28, 0x31, 0x2e, 0x30, 0x29, 0x29, 0x2c, 0x20, 0x5f, 0x31, 0x36,
0x35, 0x31, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6f, 0x75, 0x31, 0x2e, 0x77, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20,
0x74, 0x2e, 0x6f, 0x75, 0x74, 0x5f, 0x76, 0x61, 0x72, 0x5f, 0x53, 0x56, 0x5f, 0x54, 0x61, 0x72, 0x65, 0x6c, 0x73, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
0x67, 0x65, 0x74, 0x30, 0x20, 0x3d, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x28, 0x5f, 0x31, 0x20, 0x20, 0x20, 0x5f, 0x31, 0x37, 0x34, 0x20, 0x3d, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34,
0x36, 0x34, 0x2c, 0x20, 0x5f, 0x31, 0x34, 0x36, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6f, 0x28, 0x5f, 0x31, 0x35, 0x31, 0x2c, 0x20, 0x5f, 0x31, 0x34, 0x36, 0x29, 0x3b, 0x0a, 0x20, 0x20,
0x75, 0x74, 0x2e, 0x67, 0x6c, 0x5f, 0x46, 0x72, 0x61, 0x67, 0x44, 0x65, 0x70, 0x74, 0x68, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6f, 0x75, 0x74, 0x2e, 0x6f, 0x75, 0x74, 0x5f,
0x3d, 0x20, 0x67, 0x6c, 0x5f, 0x46, 0x72, 0x61, 0x67, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x2e, 0x77, 0x76, 0x61, 0x72, 0x5f, 0x53, 0x56, 0x5f, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x30, 0x20, 0x3d,
0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x5f, 0x31, 0x37, 0x34, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6f, 0x75, 0x74, 0x2e, 0x67,
0x3b, 0x0a, 0x7d, 0x0a, 0x0a, 0x6c, 0x5f, 0x46, 0x72, 0x61, 0x67, 0x44, 0x65, 0x70, 0x74, 0x68, 0x20, 0x3d, 0x20, 0x67, 0x6c,
0x5f, 0x46, 0x72, 0x61, 0x67, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x2e, 0x77, 0x3b, 0x0a, 0x20, 0x20,
0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6f, 0x75, 0x74, 0x3b, 0x0a, 0x7d, 0x0a,
0x0a,
}; };
#endif #endif
static const Uint8 SolidColor_frag_spirv[4492] = { static const Uint8 SolidColor_frag_spirv[4616] = {
0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0e, 0x00, 0xab, 0x00, 0x00, 0x00, 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0e, 0x00, 0xb1, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x06, 0x00,
0x01, 0x00, 0x00, 0x00, 0x47, 0x4c, 0x53, 0x4c, 0x2e, 0x73, 0x74, 0x64, 0x2e, 0x34, 0x35, 0x30, 0x01, 0x00, 0x00, 0x00, 0x47, 0x4c, 0x53, 0x4c, 0x2e, 0x73, 0x74, 0x64, 0x2e, 0x34, 0x35, 0x30,
0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
@ -902,28 +906,36 @@ static const Uint8 SolidColor_frag_spirv[4492] = {
0x16, 0x00, 0x00, 0x00, 0x99, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0xab, 0x00, 0x05, 0x00, 0x16, 0x00, 0x00, 0x00, 0x99, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0xab, 0x00, 0x05, 0x00,
0x1a, 0x00, 0x00, 0x00, 0x9a, 0x00, 0x00, 0x00, 0x99, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x9a, 0x00, 0x00, 0x00, 0x99, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
0xf7, 0x00, 0x03, 0x00, 0x9b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x04, 0x00, 0xf7, 0x00, 0x03, 0x00, 0x9b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x04, 0x00,
0x9a, 0x00, 0x00, 0x00, 0x9c, 0x00, 0x00, 0x00, 0x9b, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x9a, 0x00, 0x00, 0x00, 0x9c, 0x00, 0x00, 0x00, 0x9d, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00,
0x9c, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x9d, 0x00, 0x00, 0x00, 0x9c, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x9e, 0x00, 0x00, 0x00,
0x0d, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x9e, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x9f, 0x00, 0x00, 0x00,
0x0f, 0x00, 0x00, 0x00, 0x56, 0x00, 0x05, 0x00, 0x10, 0x00, 0x00, 0x00, 0x9f, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x56, 0x00, 0x05, 0x00, 0x10, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00,
0x9d, 0x00, 0x00, 0x00, 0x9e, 0x00, 0x00, 0x00, 0x57, 0x00, 0x06, 0x00, 0x27, 0x00, 0x00, 0x00, 0x9e, 0x00, 0x00, 0x00, 0x9f, 0x00, 0x00, 0x00, 0x57, 0x00, 0x06, 0x00, 0x27, 0x00, 0x00, 0x00,
0xa0, 0x00, 0x00, 0x00, 0x9f, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa1, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x4f, 0x00, 0x08, 0x00, 0x14, 0x00, 0x00, 0x00, 0xa1, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x08, 0x00, 0x14, 0x00, 0x00, 0x00, 0xa2, 0x00, 0x00, 0x00, 0xa1, 0x00, 0x00, 0x00,
0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xa1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
0x85, 0x00, 0x05, 0x00, 0x14, 0x00, 0x00, 0x00, 0xa2, 0x00, 0x00, 0x00, 0xa1, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x14, 0x00, 0x00, 0x00, 0xa3, 0x00, 0x00, 0x00, 0xa2, 0x00, 0x00, 0x00,
0x97, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x14, 0x00, 0x00, 0x00, 0xa3, 0x00, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x14, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00, 0xa2, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00, 0xa3, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
0x1e, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0x9b, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x12, 0x00, 0x00, 0x00, 0xa5, 0x00, 0x00, 0x00,
0x9b, 0x00, 0x00, 0x00, 0xf5, 0x00, 0x07, 0x00, 0x14, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00, 0xa1, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x12, 0x00, 0x00, 0x00,
0x97, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0xa3, 0x00, 0x00, 0x00, 0x9c, 0x00, 0x00, 0x00, 0xa6, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00,
0x51, 0x00, 0x05, 0x00, 0x12, 0x00, 0x00, 0x00, 0xa5, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0xa7, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x12, 0x00, 0x00, 0x00, 0xa6, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x12, 0x00, 0x00, 0x00, 0xa8, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00,
0xa4, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x12, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x50, 0x00, 0x07, 0x00, 0x27, 0x00, 0x00, 0x00, 0xa9, 0x00, 0x00, 0x00,
0xa7, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x50, 0x00, 0x07, 0x00, 0xa6, 0x00, 0x00, 0x00, 0xa7, 0x00, 0x00, 0x00, 0xa8, 0x00, 0x00, 0x00, 0xa5, 0x00, 0x00, 0x00,
0x27, 0x00, 0x00, 0x00, 0xa8, 0x00, 0x00, 0x00, 0xa5, 0x00, 0x00, 0x00, 0xa6, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0x9b, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x9d, 0x00, 0x00, 0x00,
0xa7, 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x38, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x12, 0x00, 0x00, 0x00, 0xaa, 0x00, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00,
0xa9, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x12, 0x00, 0x00, 0x00, 0xab, 0x00, 0x00, 0x00,
0x12, 0x00, 0x00, 0x00, 0xaa, 0x00, 0x00, 0x00, 0xa9, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x97, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x12, 0x00, 0x00, 0x00,
0x07, 0x00, 0x00, 0x00, 0xa8, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x08, 0x00, 0x00, 0x00, 0xac, 0x00, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x50, 0x00, 0x07, 0x00,
0xaa, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00, 0x27, 0x00, 0x00, 0x00, 0xad, 0x00, 0x00, 0x00, 0xaa, 0x00, 0x00, 0x00, 0xab, 0x00, 0x00, 0x00,
0xac, 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0x9b, 0x00, 0x00, 0x00,
0xf8, 0x00, 0x02, 0x00, 0x9b, 0x00, 0x00, 0x00, 0xf5, 0x00, 0x07, 0x00, 0x27, 0x00, 0x00, 0x00,
0xae, 0x00, 0x00, 0x00, 0xa9, 0x00, 0x00, 0x00, 0x9c, 0x00, 0x00, 0x00, 0xad, 0x00, 0x00, 0x00,
0x9d, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x38, 0x00, 0x00, 0x00, 0xaf, 0x00, 0x00, 0x00,
0x03, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x12, 0x00, 0x00, 0x00,
0xb0, 0x00, 0x00, 0x00, 0xaf, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x07, 0x00, 0x00, 0x00,
0xae, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x08, 0x00, 0x00, 0x00, 0xb0, 0x00, 0x00, 0x00,
0xfd, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00,
}; };

View File

@ -72,8 +72,11 @@ FS_Output main(FS_Input input)
if (UseTexture != 0) { if (UseTexture != 0) {
float4 texel = Texture.Sample(Sampler, input.TexCoord); float4 texel = Texture.Sample(Sampler, input.TexCoord);
finalColor = saturate(texel.rgb * finalColor); finalColor = saturate(texel.rgb * finalColor);
output.Color = float4(finalColor, texel.a);
}
else {
output.Color = float4(finalColor, Color.a);
} }
output.Color = float4(finalColor, Color.a);
output.Depth = input.Position.w; output.Depth = input.Position.w;
return output; return output;
} }

View File

@ -23,9 +23,22 @@
#include <wasm_simd128.h> #include <wasm_simd128.h>
#endif #endif
Direct3DRMSoftwareRenderer::Direct3DRMSoftwareRenderer(DWORD width, DWORD height) : m_width(width), m_height(height) Direct3DRMSoftwareRenderer::Direct3DRMSoftwareRenderer(DWORD width, DWORD height)
{ {
m_zBuffer.resize(m_width * m_height); m_virtualWidth = width;
m_virtualHeight = height;
m_renderer = SDL_CreateRenderer(DDWindow, NULL);
ViewportTransform viewportTransform = {1.0f, 0.0f, 0.0f};
Resize(width, height, viewportTransform);
}
Direct3DRMSoftwareRenderer::~Direct3DRMSoftwareRenderer()
{
SDL_DestroySurface(m_renderedImage);
SDL_DestroyTexture(m_uploadBuffer);
SDL_DestroyRenderer(m_renderer);
} }
void Direct3DRMSoftwareRenderer::PushLights(const SceneLight* lights, size_t count) void Direct3DRMSoftwareRenderer::PushLights(const SceneLight* lights, size_t count)
@ -354,8 +367,8 @@ void Direct3DRMSoftwareRenderer::DrawTriangleProjected(
c2 = ApplyLighting(v2.position, v2.normal, appearance); c2 = ApplyLighting(v2.position, v2.normal, appearance);
} }
Uint8* pixels = (Uint8*) DDBackBuffer->pixels; Uint8* pixels = (Uint8*) m_renderedImage->pixels;
int pitch = DDBackBuffer->pitch; int pitch = m_renderedImage->pitch;
VertexXY verts[3] = { VertexXY verts[3] = {
{p0.x, p0.y, p0.z, p0.w, c0, v0.texCoord.u, v0.texCoord.v}, {p0.x, p0.y, p0.z, p0.w, c0, v0.texCoord.u, v0.texCoord.v},
@ -553,7 +566,7 @@ Uint32 Direct3DRMSoftwareRenderer::GetTextureId(IDirect3DRMTexture* iTexture)
if (texRef.version != texture->m_version) { if (texRef.version != texture->m_version) {
// Update animated textures // Update animated textures
SDL_DestroySurface(texRef.cached); SDL_DestroySurface(texRef.cached);
texRef.cached = SDL_ConvertSurface(surface->m_surface, DDBackBuffer->format); texRef.cached = SDL_ConvertSurface(surface->m_surface, m_renderedImage->format);
SDL_LockSurface(texRef.cached); SDL_LockSurface(texRef.cached);
texRef.version = texture->m_version; texRef.version = texture->m_version;
} }
@ -561,7 +574,7 @@ Uint32 Direct3DRMSoftwareRenderer::GetTextureId(IDirect3DRMTexture* iTexture)
} }
} }
SDL_Surface* convertedRender = SDL_ConvertSurface(surface->m_surface, DDBackBuffer->format); SDL_Surface* convertedRender = SDL_ConvertSurface(surface->m_surface, m_renderedImage->format);
SDL_LockSurface(convertedRender); SDL_LockSurface(convertedRender);
// Reuse freed slot // Reuse freed slot
@ -651,16 +664,6 @@ Uint32 Direct3DRMSoftwareRenderer::GetMeshId(IDirect3DRMMesh* mesh, const MeshGr
return (Uint32) (m_meshs.size() - 1); return (Uint32) (m_meshs.size() - 1);
} }
DWORD Direct3DRMSoftwareRenderer::GetWidth()
{
return m_width;
}
DWORD Direct3DRMSoftwareRenderer::GetHeight()
{
return m_height;
}
void Direct3DRMSoftwareRenderer::GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc) void Direct3DRMSoftwareRenderer::GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc)
{ {
memset(halDesc, 0, sizeof(D3DDEVICEDESC)); memset(halDesc, 0, sizeof(D3DDEVICEDESC));
@ -681,13 +684,13 @@ const char* Direct3DRMSoftwareRenderer::GetName()
HRESULT Direct3DRMSoftwareRenderer::BeginFrame() HRESULT Direct3DRMSoftwareRenderer::BeginFrame()
{ {
if (!DDBackBuffer || !SDL_LockSurface(DDBackBuffer)) { if (!m_renderedImage || !SDL_LockSurface(m_renderedImage)) {
return DDERR_GENERIC; return DDERR_GENERIC;
} }
ClearZBuffer(); ClearZBuffer();
m_format = SDL_GetPixelFormatDetails(DDBackBuffer->format); m_format = SDL_GetPixelFormatDetails(m_renderedImage->format);
m_palette = SDL_GetSurfacePalette(DDBackBuffer); m_palette = SDL_GetSurfacePalette(m_renderedImage);
m_bytesPerPixel = m_format->bits_per_pixel / 8; m_bytesPerPixel = m_format->bits_per_pixel / 8;
return DD_OK; return DD_OK;
@ -700,6 +703,8 @@ void Direct3DRMSoftwareRenderer::EnableTransparency()
void Direct3DRMSoftwareRenderer::SubmitDraw( void Direct3DRMSoftwareRenderer::SubmitDraw(
DWORD meshId, DWORD meshId,
const D3DRMMATRIX4D& modelViewMatrix, const D3DRMMATRIX4D& modelViewMatrix,
const D3DRMMATRIX4D& worldMatrix,
const D3DRMMATRIX4D& viewMatrix,
const Matrix3x3& normalMatrix, const Matrix3x3& normalMatrix,
const Appearance& appearance const Appearance& appearance
) )
@ -731,7 +736,84 @@ void Direct3DRMSoftwareRenderer::SubmitDraw(
HRESULT Direct3DRMSoftwareRenderer::FinalizeFrame() HRESULT Direct3DRMSoftwareRenderer::FinalizeFrame()
{ {
SDL_UnlockSurface(DDBackBuffer); SDL_UnlockSurface(m_renderedImage);
return DD_OK; return DD_OK;
} }
void Direct3DRMSoftwareRenderer::Resize(int width, int height, const ViewportTransform& viewportTransform)
{
m_viewportTransform = viewportTransform;
float aspect = static_cast<float>(width) / height;
float virtualAspect = static_cast<float>(m_virtualWidth) / m_virtualHeight;
// Cap to virtual canvase for performance
if (aspect > virtualAspect) {
m_height = std::min(height, m_virtualHeight);
m_width = static_cast<int>(m_height * aspect);
}
else {
m_width = std::min(width, m_virtualWidth);
m_height = static_cast<int>(m_width / aspect);
}
m_viewportTransform.scale =
std::min(static_cast<float>(m_width) / m_virtualWidth, static_cast<float>(m_height) / m_virtualHeight);
m_viewportTransform.offsetX = (m_width - (m_virtualWidth * m_viewportTransform.scale)) / 2.0f;
m_viewportTransform.offsetY = (m_height - (m_virtualHeight * m_viewportTransform.scale)) / 2.0f;
if (m_renderedImage) {
SDL_DestroySurface(m_renderedImage);
}
m_renderedImage = SDL_CreateSurface(m_width, m_height, SDL_PIXELFORMAT_RGBA32);
if (m_uploadBuffer) {
SDL_DestroyTexture(m_uploadBuffer);
}
m_uploadBuffer =
SDL_CreateTexture(m_renderer, SDL_PIXELFORMAT_RGBA32, SDL_TEXTUREACCESS_STREAMING, m_width, m_height);
m_zBuffer.resize(m_width * m_height);
}
void Direct3DRMSoftwareRenderer::Clear(float r, float g, float b)
{
SDL_Rect rect = {0, 0, m_renderedImage->w, m_renderedImage->h};
const SDL_PixelFormatDetails* details = SDL_GetPixelFormatDetails(m_renderedImage->format);
Uint32 color = SDL_MapRGB(details, m_palette, r * 255, g * 255, b * 255);
SDL_FillSurfaceRect(m_renderedImage, &rect, color);
}
void Direct3DRMSoftwareRenderer::Flip()
{
SDL_UpdateTexture(m_uploadBuffer, nullptr, m_renderedImage->pixels, m_renderedImage->pitch);
SDL_RenderTexture(m_renderer, m_uploadBuffer, nullptr, nullptr);
SDL_RenderPresent(m_renderer);
}
void Direct3DRMSoftwareRenderer::Draw2DImage(Uint32 textureId, const SDL_Rect& srcRect, const SDL_Rect& dstRect)
{
SDL_Surface* surface = m_textures[textureId].cached;
SDL_UnlockSurface(surface);
SDL_Rect centeredRect = {
static_cast<int>(dstRect.x * m_viewportTransform.scale + m_viewportTransform.offsetX),
static_cast<int>(dstRect.y * m_viewportTransform.scale + m_viewportTransform.offsetY),
static_cast<int>(dstRect.w * m_viewportTransform.scale),
static_cast<int>(dstRect.h * m_viewportTransform.scale),
};
SDL_BlitSurfaceScaled(surface, &srcRect, m_renderedImage, &centeredRect, SDL_SCALEMODE_LINEAR);
SDL_LockSurface(surface);
}
void Direct3DRMSoftwareRenderer::Download(SDL_Surface* target)
{
SDL_Rect srcRect = {
static_cast<int>(m_viewportTransform.offsetX),
static_cast<int>(m_viewportTransform.offsetY),
static_cast<int>(m_virtualWidth * m_viewportTransform.scale),
static_cast<int>(m_virtualHeight * m_viewportTransform.scale),
};
SDL_BlitSurfaceScaled(m_renderedImage, &srcRect, target, nullptr, SDL_SCALEMODE_LINEAR);
}

View File

@ -127,7 +127,7 @@ HRESULT Direct3DRMImpl::CreateDeviceFromD3D(
{ {
auto renderer = static_cast<Direct3DRMRenderer*>(d3dDevice); auto renderer = static_cast<Direct3DRMRenderer*>(d3dDevice);
*outDevice = static_cast<IDirect3DRMDevice2*>( *outDevice = static_cast<IDirect3DRMDevice2*>(
new Direct3DRMDevice2Impl(renderer->GetWidth(), renderer->GetHeight(), renderer) new Direct3DRMDevice2Impl(renderer->GetVirtualWidth(), renderer->GetVirtualHeight(), renderer)
); );
return DD_OK; return DD_OK;
} }
@ -143,26 +143,25 @@ HRESULT Direct3DRMImpl::CreateDeviceFromSurface(
DDSDesc.dwSize = sizeof(DDSURFACEDESC); DDSDesc.dwSize = sizeof(DDSURFACEDESC);
surface->GetSurfaceDesc(&DDSDesc); surface->GetSurfaceDesc(&DDSDesc);
Direct3DRMRenderer* renderer;
if (SDL_memcmp(&guid, &SDL3_GPU_GUID, sizeof(GUID)) == 0) { if (SDL_memcmp(&guid, &SDL3_GPU_GUID, sizeof(GUID)) == 0) {
renderer = Direct3DRMSDL3GPURenderer::Create(DDSDesc.dwWidth, DDSDesc.dwHeight); DDRenderer = Direct3DRMSDL3GPURenderer::Create(DDSDesc.dwWidth, DDSDesc.dwHeight);
} }
else if (SDL_memcmp(&guid, &SOFTWARE_GUID, sizeof(GUID)) == 0) { else if (SDL_memcmp(&guid, &SOFTWARE_GUID, sizeof(GUID)) == 0) {
renderer = new Direct3DRMSoftwareRenderer(DDSDesc.dwWidth, DDSDesc.dwHeight); DDRenderer = new Direct3DRMSoftwareRenderer(DDSDesc.dwWidth, DDSDesc.dwHeight);
} }
#ifdef USE_OPENGLES2 #ifdef USE_OPENGLES2
else if (SDL_memcmp(&guid, &OpenGLES2_GUID, sizeof(GUID)) == 0) { else if (SDL_memcmp(&guid, &OpenGLES2_GUID, sizeof(GUID)) == 0) {
renderer = OpenGLES2Renderer::Create(DDSDesc.dwWidth, DDSDesc.dwHeight); DDRenderer = OpenGLES2Renderer::Create(DDSDesc.dwWidth, DDSDesc.dwHeight);
} }
#endif #endif
#ifdef USE_OPENGL1 #ifdef USE_OPENGL1
else if (SDL_memcmp(&guid, &OpenGL1_GUID, sizeof(GUID)) == 0) { else if (SDL_memcmp(&guid, &OpenGL1_GUID, sizeof(GUID)) == 0) {
renderer = OpenGL1Renderer::Create(DDSDesc.dwWidth, DDSDesc.dwHeight); DDRenderer = OpenGL1Renderer::Create(DDSDesc.dwWidth, DDSDesc.dwHeight);
} }
#endif #endif
#ifdef _WIN32 #ifdef _WIN32
else if (SDL_memcmp(&guid, &DirectX9_GUID, sizeof(GUID)) == 0) { else if (SDL_memcmp(&guid, &DirectX9_GUID, sizeof(GUID)) == 0) {
renderer = DirectX9Renderer::Create(DDSDesc.dwWidth, DDSDesc.dwHeight); DDRenderer = DirectX9Renderer::Create(DDSDesc.dwWidth, DDSDesc.dwHeight);
} }
#endif #endif
else { else {
@ -170,7 +169,7 @@ HRESULT Direct3DRMImpl::CreateDeviceFromSurface(
return E_NOINTERFACE; return E_NOINTERFACE;
} }
*outDevice = *outDevice =
static_cast<IDirect3DRMDevice2*>(new Direct3DRMDevice2Impl(DDSDesc.dwWidth, DDSDesc.dwHeight, renderer)); static_cast<IDirect3DRMDevice2*>(new Direct3DRMDevice2Impl(DDSDesc.dwWidth, DDSDesc.dwHeight, DDRenderer));
return DD_OK; return DD_OK;
} }
@ -181,9 +180,8 @@ HRESULT Direct3DRMImpl::CreateTexture(D3DRMIMAGE* image, IDirect3DRMTexture2** o
} }
HRESULT Direct3DRMImpl::CreateTextureFromSurface(LPDIRECTDRAWSURFACE surface, IDirect3DRMTexture2** outTexture) HRESULT Direct3DRMImpl::CreateTextureFromSurface(LPDIRECTDRAWSURFACE surface, IDirect3DRMTexture2** outTexture)
{ {
*outTexture = static_cast<IDirect3DRMTexture2*>(new Direct3DRMTextureImpl(surface)); *outTexture = static_cast<IDirect3DRMTexture2*>(new Direct3DRMTextureImpl(surface, true));
return DD_OK; return DD_OK;
} }

View File

@ -11,8 +11,9 @@
#include <SDL3/SDL.h> #include <SDL3/SDL.h>
Direct3DRMDevice2Impl::Direct3DRMDevice2Impl(DWORD width, DWORD height, Direct3DRMRenderer* renderer) Direct3DRMDevice2Impl::Direct3DRMDevice2Impl(DWORD width, DWORD height, Direct3DRMRenderer* renderer)
: m_width(width), m_height(height), m_renderer(renderer), m_viewports(new Direct3DRMViewportArrayImpl) : m_virtualWidth(width), m_virtualHeight(height), m_renderer(renderer), m_viewports(new Direct3DRMViewportArrayImpl)
{ {
Resize();
} }
Direct3DRMDevice2Impl::~Direct3DRMDevice2Impl() Direct3DRMDevice2Impl::~Direct3DRMDevice2Impl()
@ -43,16 +44,6 @@ HRESULT Direct3DRMDevice2Impl::QueryInterface(const GUID& riid, void** ppvObject
return E_NOINTERFACE; return E_NOINTERFACE;
} }
DWORD Direct3DRMDevice2Impl::GetWidth()
{
return m_width;
}
DWORD Direct3DRMDevice2Impl::GetHeight()
{
return m_height;
}
HRESULT Direct3DRMDevice2Impl::SetBufferCount(int count) HRESULT Direct3DRMDevice2Impl::SetBufferCount(int count)
{ {
MINIWIN_NOT_IMPLEMENTED(); MINIWIN_NOT_IMPLEMENTED();
@ -133,7 +124,9 @@ HRESULT Direct3DRMDevice2Impl::Update()
HRESULT Direct3DRMDevice2Impl::AddViewport(IDirect3DRMViewport* viewport) HRESULT Direct3DRMDevice2Impl::AddViewport(IDirect3DRMViewport* viewport)
{ {
return m_viewports->AddElement(viewport); HRESULT status = m_viewports->AddElement(viewport);
Resize();
return status;
} }
HRESULT Direct3DRMDevice2Impl::GetViewports(IDirect3DRMViewportArray** ppViewportArray) HRESULT Direct3DRMDevice2Impl::GetViewports(IDirect3DRMViewportArray** ppViewportArray)
@ -143,7 +136,53 @@ HRESULT Direct3DRMDevice2Impl::GetViewports(IDirect3DRMViewportArray** ppViewpor
return DD_OK; return DD_OK;
} }
ViewportTransform CalculateViewportTransform(int virtualW, int virtualH, int windowW, int windowH)
{
float scaleX = (float) windowW / virtualW;
float scaleY = (float) windowH / virtualH;
float scale = (scaleX < scaleY) ? scaleX : scaleY;
float viewportW = virtualW * scale;
float viewportH = virtualH * scale;
float offsetX = (windowW - viewportW) * 0.5f;
float offsetY = (windowH - viewportH) * 0.5f;
return {scale, offsetX, offsetY};
}
void Direct3DRMDevice2Impl::Resize()
{
int width, height;
SDL_GetWindowSizeInPixels(DDWindow, &width, &height);
m_viewportTransform = CalculateViewportTransform(m_virtualWidth, m_virtualHeight, width, height);
m_renderer->Resize(width, height, m_viewportTransform);
for (int i = 0; i < m_viewports->GetSize(); i++) {
IDirect3DRMViewport* viewport;
m_viewports->GetElement(i, &viewport);
static_cast<Direct3DRMViewportImpl*>(viewport)->UpdateProjectionMatrix();
}
}
bool Direct3DRMDevice2Impl::ConvertEventToRenderCoordinates(SDL_Event* event) bool Direct3DRMDevice2Impl::ConvertEventToRenderCoordinates(SDL_Event* event)
{ {
return m_renderer->ConvertEventToRenderCoordinates(event); switch (event->type) {
case SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED: {
Resize();
break;
}
case SDL_EVENT_MOUSE_MOTION:
case SDL_EVENT_MOUSE_BUTTON_DOWN:
case SDL_EVENT_MOUSE_BUTTON_UP: {
int rawX = event->motion.x;
int rawY = event->motion.y;
float x = (rawX - m_viewportTransform.offsetX) / m_viewportTransform.scale;
float y = (rawY - m_viewportTransform.offsetY) / m_viewportTransform.scale;
event->motion.x = static_cast<Sint32>(x);
event->motion.y = static_cast<Sint32>(y);
break;
} break;
}
return true;
} }

View File

@ -59,7 +59,7 @@ HRESULT Direct3DRMMeshImpl::AddGroup(
MeshGroup group; MeshGroup group;
group.vertexPerFace = vertexPerFace; group.vertexPerFace = vertexPerFace;
DWORD* src = faceBuffer; unsigned int* src = faceBuffer;
group.indices.assign(src, src + faceCount * vertexPerFace); group.indices.assign(src, src + faceCount * vertexPerFace);
m_groups.push_back(std::move(group)); m_groups.push_back(std::move(group));

View File

@ -6,8 +6,19 @@ Direct3DRMTextureImpl::Direct3DRMTextureImpl(D3DRMIMAGE* image)
MINIWIN_NOT_IMPLEMENTED(); MINIWIN_NOT_IMPLEMENTED();
} }
Direct3DRMTextureImpl::Direct3DRMTextureImpl(IDirectDrawSurface* surface) : m_surface(surface) Direct3DRMTextureImpl::Direct3DRMTextureImpl(IDirectDrawSurface* surface, bool holdsRef)
: m_surface(surface), m_holdsRef(holdsRef)
{ {
if (holdsRef && m_surface) {
m_surface->AddRef();
}
}
Direct3DRMTextureImpl::~Direct3DRMTextureImpl()
{
if (m_holdsRef && m_surface) {
m_surface->Release();
}
} }
HRESULT Direct3DRMTextureImpl::QueryInterface(const GUID& riid, void** ppvObject) HRESULT Direct3DRMTextureImpl::QueryInterface(const GUID& riid, void** ppvObject)

View File

@ -15,7 +15,7 @@
#include <math.h> #include <math.h>
Direct3DRMViewportImpl::Direct3DRMViewportImpl(DWORD width, DWORD height, Direct3DRMRenderer* renderer) Direct3DRMViewportImpl::Direct3DRMViewportImpl(DWORD width, DWORD height, Direct3DRMRenderer* renderer)
: m_width(width), m_height(height), m_renderer(renderer) : m_virtualWidth(width), m_virtualHeight(height), m_renderer(renderer)
{ {
} }
@ -151,7 +151,7 @@ void Direct3DRMViewportImpl::CollectLightsFromFrame(
void Direct3DRMViewportImpl::BuildViewFrustumPlanes() void Direct3DRMViewportImpl::BuildViewFrustumPlanes()
{ {
float aspect = (float) m_width / (float) m_height; float aspect = (float) m_renderer->GetWidth() / (float) m_renderer->GetHeight();
float tanFovX = m_field; float tanFovX = m_field;
float tanFovY = m_field / aspect; float tanFovY = m_field / aspect;
@ -268,18 +268,22 @@ void Direct3DRMViewportImpl::CollectMeshesFromFrame(IDirect3DRMFrame* frame, D3D
if (appearance.color.a != 255) { if (appearance.color.a != 255) {
m_deferredDraws.push_back( m_deferredDraws.push_back(
{m_renderer->GetMeshId(mesh, &meshGroup), {m_renderer->GetMeshId(mesh, &meshGroup),
{},
{}, {},
{}, {},
appearance, appearance,
CalculateDepth(m_viewProjectionwMatrix, worldMatrix)} CalculateDepth(m_viewProjectionwMatrix, worldMatrix)}
); );
memcpy(m_deferredDraws.back().modelViewMatrix, modelViewMatrix, sizeof(D3DRMMATRIX4D)); memcpy(m_deferredDraws.back().modelViewMatrix, modelViewMatrix, sizeof(D3DRMMATRIX4D));
memcpy(m_deferredDraws.back().worldMatrix, worldMatrix, sizeof(D3DRMMATRIX4D));
memcpy(m_deferredDraws.back().normalMatrix, worldMatrixInvert, sizeof(Matrix3x3)); memcpy(m_deferredDraws.back().normalMatrix, worldMatrixInvert, sizeof(Matrix3x3));
} }
else { else {
m_renderer->SubmitDraw( m_renderer->SubmitDraw(
m_renderer->GetMeshId(mesh, &meshGroup), m_renderer->GetMeshId(mesh, &meshGroup),
modelViewMatrix, modelViewMatrix,
worldMatrix,
m_viewMatrix,
worldMatrixInvert, worldMatrixInvert,
appearance appearance
); );
@ -325,7 +329,14 @@ HRESULT Direct3DRMViewportImpl::RenderScene()
); );
m_renderer->EnableTransparency(); m_renderer->EnableTransparency();
for (const DeferredDrawCommand& cmd : m_deferredDraws) { for (const DeferredDrawCommand& cmd : m_deferredDraws) {
m_renderer->SubmitDraw(cmd.meshId, cmd.modelViewMatrix, cmd.normalMatrix, cmd.appearance); m_renderer->SubmitDraw(
cmd.meshId,
cmd.modelViewMatrix,
cmd.worldMatrix,
m_viewMatrix,
cmd.normalMatrix,
cmd.appearance
);
} }
m_deferredDraws.clear(); m_deferredDraws.clear();
@ -349,16 +360,14 @@ HRESULT Direct3DRMViewportImpl::ForceUpdate(int x, int y, int w, int h)
HRESULT Direct3DRMViewportImpl::Clear() HRESULT Direct3DRMViewportImpl::Clear()
{ {
if (!DDBackBuffer) { if (!m_renderer) {
return DDERR_GENERIC; return DDERR_GENERIC;
} }
uint8_t r = (m_backgroundColor >> 16) & 0xFF; uint8_t r = (m_backgroundColor >> 16) & 0xFF;
uint8_t g = (m_backgroundColor >> 8) & 0xFF; uint8_t g = (m_backgroundColor >> 8) & 0xFF;
uint8_t b = m_backgroundColor & 0xFF; uint8_t b = m_backgroundColor & 0xFF;
m_renderer->Clear(r / 255.0f, g / 255.0f, b / 255.0f);
Uint32 color = SDL_MapRGB(SDL_GetPixelFormatDetails(DDBackBuffer->format), nullptr, r, g, b);
SDL_FillSurfaceRect(DDBackBuffer, nullptr, color);
return DD_OK; return DD_OK;
} }
@ -427,13 +436,24 @@ HRESULT Direct3DRMViewportImpl::SetField(D3DVALUE field)
void Direct3DRMViewportImpl::UpdateProjectionMatrix() void Direct3DRMViewportImpl::UpdateProjectionMatrix()
{ {
float aspect = (float) m_width / (float) m_height; float virtualAspect = (float) m_virtualWidth / (float) m_virtualHeight;
float f = m_front / m_field; float windowAspect = (float) m_renderer->GetWidth() / (float) m_renderer->GetHeight();
float base_f = m_front / m_field;
float f_v = base_f * virtualAspect;
float f_h = base_f;
if (windowAspect >= virtualAspect) {
f_h *= virtualAspect / windowAspect;
}
else {
f_v *= windowAspect / virtualAspect;
}
float depth = m_back - m_front; float depth = m_back - m_front;
D3DRMMATRIX4D projection = { D3DRMMATRIX4D projection = {
{f, 0, 0, 0}, {f_h, 0, 0, 0},
{0, f * aspect, 0, 0}, {0, f_v, 0, 0},
{0, 0, m_back / depth, 1}, {0, 0, m_back / depth, 1},
{0, 0, (-m_front * m_back) / depth, 0}, {0, 0, (-m_front * m_back) / depth, 0},
}; };
@ -442,8 +462,8 @@ void Direct3DRMViewportImpl::UpdateProjectionMatrix()
m_renderer->SetProjection(projection, m_front, m_back); m_renderer->SetProjection(projection, m_front, m_back);
D3DRMMATRIX4D inverseProjectionMatrix = { D3DRMMATRIX4D inverseProjectionMatrix = {
{1.0f / f, 0, 0, 0}, {1.0f / f_h, 0, 0, 0},
{0, 1.0f / (f * aspect), 0, 0}, {0, 1.0f / f_v, 0, 0},
{0, 0, 0, depth / (-m_front * m_back)}, {0, 0, 0, depth / (-m_front * m_back)},
{0, 0, 1, -(m_back / depth) * depth / (-m_front * m_back)}, {0, 0, 1, -(m_back / depth) * depth / (-m_front * m_back)},
}; };
@ -455,16 +475,6 @@ D3DVALUE Direct3DRMViewportImpl::GetField()
return m_field; return m_field;
} }
DWORD Direct3DRMViewportImpl::GetWidth()
{
return m_width;
}
DWORD Direct3DRMViewportImpl::GetHeight()
{
return m_height;
}
inline float FromNDC(float ndcCoord, float dim) inline float FromNDC(float ndcCoord, float dim)
{ {
return (ndcCoord * 0.5f + 0.5f) * dim; return (ndcCoord * 0.5f + 0.5f) * dim;
@ -492,8 +502,8 @@ HRESULT Direct3DRMViewportImpl::Transform(D3DRMVECTOR4D* screen, D3DVECTOR* worl
float ndcX = projVec.x * invW; float ndcX = projVec.x * invW;
float ndcY = projVec.y * invW; float ndcY = projVec.y * invW;
screen->x = FromNDC(ndcX, m_width); screen->x = FromNDC(ndcX, m_virtualWidth);
screen->y = FromNDC(-ndcY, m_height); // Y-flip screen->y = FromNDC(-ndcY, m_virtualHeight); // Y-flip
// Undo perspective divide for screen-space coords // Undo perspective divide for screen-space coords
screen->x *= projVec.z; screen->x *= projVec.z;
@ -509,8 +519,8 @@ HRESULT Direct3DRMViewportImpl::InverseTransform(D3DVECTOR* world, D3DRMVECTOR4D
float screenY = screen->y / screen->w; float screenY = screen->y / screen->w;
// Convert screen coordinates to NDC // Convert screen coordinates to NDC
float ndcX = screenX / m_width * 2.0f - 1.0f; float ndcX = screenX / m_virtualWidth * 2.0f - 1.0f;
float ndcY = 1.0f - (screenY / m_height) * 2.0f; float ndcY = 1.0f - (screenY / m_virtualHeight) * 2.0f;
D3DRMVECTOR4D clipVec = {ndcX * screen->w, ndcY * screen->w, screen->z, screen->w}; D3DRMVECTOR4D clipVec = {ndcX * screen->w, ndcY * screen->w, screen->z, screen->w};
@ -753,13 +763,13 @@ HRESULT Direct3DRMViewportImpl::Pick(float x, float y, LPDIRECT3DRMPICKEDARRAY*
Ray pickRay = BuildPickingRay( Ray pickRay = BuildPickingRay(
x, x,
y, y,
m_width, m_virtualWidth,
m_height, m_virtualHeight,
m_camera, m_camera,
m_front, m_front,
m_back, m_back,
m_field, m_field,
(float) m_width / (float) m_height (float) m_virtualWidth / (float) m_virtualHeight
); );
std::function<void(IDirect3DRMFrame*, std::vector<IDirect3DRMFrame*>&)> recurse; std::function<void(IDirect3DRMFrame*, std::vector<IDirect3DRMFrame*>&)> recurse;

View File

@ -23,9 +23,7 @@
#include <cstring> #include <cstring>
SDL_Window* DDWindow; SDL_Window* DDWindow;
SDL_Surface* DDBackBuffer; Direct3DRMRenderer* DDRenderer;
FrameBufferImpl* DDFrameBuffer;
SDL_Renderer* DDRenderer;
HRESULT DirectDrawImpl::QueryInterface(const GUID& riid, void** ppvObject) HRESULT DirectDrawImpl::QueryInterface(const GUID& riid, void** ppvObject)
{ {
@ -82,13 +80,13 @@ HRESULT DirectDrawImpl::CreateSurface(
return DD_OK; return DD_OK;
} }
if ((lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) == DDSCAPS_PRIMARYSURFACE) { if ((lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) == DDSCAPS_PRIMARYSURFACE) {
DDFrameBuffer = new FrameBufferImpl(); m_frameBuffer = new FrameBufferImpl(m_virtualWidth, m_virtualHeight);
*lplpDDSurface = static_cast<IDirectDrawSurface*>(DDFrameBuffer); *lplpDDSurface = static_cast<IDirectDrawSurface*>(m_frameBuffer);
return DD_OK; return DD_OK;
} }
if ((lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_3DDEVICE) == DDSCAPS_3DDEVICE) { if ((lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_3DDEVICE) == DDSCAPS_3DDEVICE) {
DDFrameBuffer->AddRef(); m_frameBuffer->AddRef();
*lplpDDSurface = static_cast<IDirectDrawSurface*>(DDFrameBuffer); *lplpDDSurface = static_cast<IDirectDrawSurface*>(m_frameBuffer);
return DD_OK; return DD_OK;
} }
if ((lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_TEXTURE) == DDSCAPS_TEXTURE) { if ((lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_TEXTURE) == DDSCAPS_TEXTURE) {
@ -100,7 +98,7 @@ HRESULT DirectDrawImpl::CreateSurface(
#ifdef MINIWIN_PIXELFORMAT #ifdef MINIWIN_PIXELFORMAT
format = MINIWIN_PIXELFORMAT; format = MINIWIN_PIXELFORMAT;
#else #else
format = SDL_PIXELFORMAT_RGBA8888; format = SDL_PIXELFORMAT_RGBA32;
#endif #endif
if ((lpDDSurfaceDesc->dwFlags & DDSD_PIXELFORMAT) == DDSD_PIXELFORMAT) { if ((lpDDSurfaceDesc->dwFlags & DDSD_PIXELFORMAT) == DDSD_PIXELFORMAT) {
if ((lpDDSurfaceDesc->ddpfPixelFormat.dwFlags & DDPF_RGB) == DDPF_RGB) { if ((lpDDSurfaceDesc->ddpfPixelFormat.dwFlags & DDPF_RGB) == DDPF_RGB) {
@ -284,6 +282,12 @@ HRESULT DirectDrawImpl::SetCooperativeLevel(HWND hWnd, DDSCLFlags dwFlags)
{ {
SDL_Window* sdlWindow = reinterpret_cast<SDL_Window*>(hWnd); SDL_Window* sdlWindow = reinterpret_cast<SDL_Window*>(hWnd);
if (m_virtualWidth == 0 || m_virtualHeight == 0) {
if (!SDL_GetWindowSize(sdlWindow, &m_virtualWidth, &m_virtualHeight)) {
SDL_LogError(LOG_CATEGORY_MINIWIN, "SDL_GetWindowSizeInPixels: %s", SDL_GetError());
}
}
if (sdlWindow) { if (sdlWindow) {
bool fullscreen; bool fullscreen;
if ((dwFlags & DDSCL_NORMAL) == DDSCL_NORMAL) { if ((dwFlags & DDSCL_NORMAL) == DDSCL_NORMAL) {
@ -302,15 +306,14 @@ HRESULT DirectDrawImpl::SetCooperativeLevel(HWND hWnd, DDSCLFlags dwFlags)
#endif #endif
} }
DDWindow = sdlWindow; DDWindow = sdlWindow;
DDRenderer = SDL_CreateRenderer(DDWindow, NULL);
SDL_PropertiesID prop = SDL_GetRendererProperties(DDRenderer);
SDL_SetRenderLogicalPresentation(DDRenderer, 640, 480, SDL_LOGICAL_PRESENTATION_LETTERBOX);
} }
return DD_OK; return DD_OK;
} }
HRESULT DirectDrawImpl::SetDisplayMode(DWORD dwWidth, DWORD dwHeight, DWORD dwBPP) HRESULT DirectDrawImpl::SetDisplayMode(DWORD dwWidth, DWORD dwHeight, DWORD dwBPP)
{ {
m_virtualWidth = dwWidth;
m_virtualHeight = dwHeight;
return DD_OK; return DD_OK;
} }
@ -325,33 +328,32 @@ HRESULT DirectDrawImpl::CreateDevice(
DDSDesc.dwSize = sizeof(DDSURFACEDESC); DDSDesc.dwSize = sizeof(DDSURFACEDESC);
pBackBuffer->GetSurfaceDesc(&DDSDesc); pBackBuffer->GetSurfaceDesc(&DDSDesc);
Direct3DRMRenderer* renderer;
if (SDL_memcmp(&guid, &SDL3_GPU_GUID, sizeof(GUID)) == 0) { if (SDL_memcmp(&guid, &SDL3_GPU_GUID, sizeof(GUID)) == 0) {
renderer = Direct3DRMSDL3GPURenderer::Create(DDSDesc.dwWidth, DDSDesc.dwHeight); DDRenderer = Direct3DRMSDL3GPURenderer::Create(DDSDesc.dwWidth, DDSDesc.dwHeight);
} }
#ifdef USE_OPENGLES2 #ifdef USE_OPENGLES2
else if (SDL_memcmp(&guid, &OpenGLES2_GUID, sizeof(GUID)) == 0) { else if (SDL_memcmp(&guid, &OpenGLES2_GUID, sizeof(GUID)) == 0) {
renderer = OpenGLES2Renderer::Create(DDSDesc.dwWidth, DDSDesc.dwHeight); DDRenderer = OpenGLES2Renderer::Create(DDSDesc.dwWidth, DDSDesc.dwHeight);
} }
#endif #endif
#ifdef USE_OPENGL1 #ifdef USE_OPENGL1
else if (SDL_memcmp(&guid, &OpenGL1_GUID, sizeof(GUID)) == 0) { else if (SDL_memcmp(&guid, &OpenGL1_GUID, sizeof(GUID)) == 0) {
renderer = OpenGL1Renderer::Create(DDSDesc.dwWidth, DDSDesc.dwHeight); DDRenderer = OpenGL1Renderer::Create(DDSDesc.dwWidth, DDSDesc.dwHeight);
} }
#endif #endif
#ifdef _WIN32 #ifdef _WIN32
else if (SDL_memcmp(&guid, &DirectX9_GUID, sizeof(GUID)) == 0) { else if (SDL_memcmp(&guid, &DirectX9_GUID, sizeof(GUID)) == 0) {
renderer = DirectX9Renderer::Create(DDSDesc.dwWidth, DDSDesc.dwHeight); DDRenderer = DirectX9Renderer::Create(DDSDesc.dwWidth, DDSDesc.dwHeight);
} }
#endif #endif
else if (SDL_memcmp(&guid, &SOFTWARE_GUID, sizeof(GUID)) == 0) { else if (SDL_memcmp(&guid, &SOFTWARE_GUID, sizeof(GUID)) == 0) {
renderer = new Direct3DRMSoftwareRenderer(DDSDesc.dwWidth, DDSDesc.dwHeight); DDRenderer = new Direct3DRMSoftwareRenderer(DDSDesc.dwWidth, DDSDesc.dwHeight);
} }
else { else {
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;
} }
*ppDirect3DDevice = static_cast<IDirect3DDevice2*>(renderer); *ppDirect3DDevice = static_cast<IDirect3DDevice2*>(DDRenderer);
return DD_OK; return DD_OK;
} }

View File

@ -1,3 +1,4 @@
#include "d3drmtexture_impl.h"
#include "ddpalette_impl.h" #include "ddpalette_impl.h"
#include "ddraw_impl.h" #include "ddraw_impl.h"
#include "ddsurface_impl.h" #include "ddsurface_impl.h"
@ -19,6 +20,9 @@ DirectDrawSurfaceImpl::~DirectDrawSurfaceImpl()
if (m_palette) { if (m_palette) {
m_palette->Release(); m_palette->Release();
} }
if (m_texture) {
m_texture->Release();
}
} }
// IUnknown interface // IUnknown interface
@ -69,6 +73,9 @@ HRESULT DirectDrawSurfaceImpl::Blt(
if (blitSource != other->m_surface) { if (blitSource != other->m_surface) {
SDL_DestroySurface(blitSource); SDL_DestroySurface(blitSource);
} }
if (m_texture) {
m_texture->Changed(TRUE, FALSE);
}
return DD_OK; return DD_OK;
} }
@ -203,6 +210,10 @@ HRESULT DirectDrawSurfaceImpl::SetPalette(LPDIRECTDRAWPALETTE lpDDPalette)
MINIWIN_NOT_IMPLEMENTED(); MINIWIN_NOT_IMPLEMENTED();
} }
if (m_texture) {
m_texture->Changed(FALSE, TRUE);
}
if (m_palette) { if (m_palette) {
m_palette->Release(); m_palette->Release();
} }
@ -216,5 +227,16 @@ HRESULT DirectDrawSurfaceImpl::SetPalette(LPDIRECTDRAWPALETTE lpDDPalette)
HRESULT DirectDrawSurfaceImpl::Unlock(LPVOID lpSurfaceData) HRESULT DirectDrawSurfaceImpl::Unlock(LPVOID lpSurfaceData)
{ {
SDL_UnlockSurface(m_surface); SDL_UnlockSurface(m_surface);
if (m_texture) {
m_texture->Changed(TRUE, FALSE);
}
return DD_OK; return DD_OK;
} }
IDirect3DRMTexture2* DirectDrawSurfaceImpl::ToTexture()
{
if (!m_texture) {
m_texture = new Direct3DRMTextureImpl(this, false);
}
return m_texture;
}

View File

@ -6,21 +6,15 @@
#include <assert.h> #include <assert.h>
FrameBufferImpl::FrameBufferImpl() FrameBufferImpl::FrameBufferImpl(DWORD virtualWidth, DWORD virtualHeight)
: m_virtualWidth(virtualWidth), m_virtualHeight(virtualHeight)
{ {
int width, height; m_transferBuffer = new DirectDrawSurfaceImpl(m_virtualWidth, m_virtualHeight, SDL_PIXELFORMAT_RGBA32);
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() FrameBufferImpl::~FrameBufferImpl()
{ {
SDL_DestroySurface(DDBackBuffer); m_transferBuffer->Release();
if (m_palette) { if (m_palette) {
m_palette->Release(); m_palette->Release();
} }
@ -51,44 +45,30 @@ HRESULT FrameBufferImpl::Blt(
LPDDBLTFX lpDDBltFx LPDDBLTFX lpDDBltFx
) )
{ {
if (!DDRenderer) {
return DDERR_GENERIC;
}
if (dynamic_cast<FrameBufferImpl*>(lpDDSrcSurface) == this) { if (dynamic_cast<FrameBufferImpl*>(lpDDSrcSurface) == this) {
return Flip(nullptr, DDFLIP_WAIT); return Flip(nullptr, DDFLIP_WAIT);
} }
if ((dwFlags & DDBLT_COLORFILL) == DDBLT_COLORFILL) { 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 r = (lpDDBltFx->dwFillColor >> 16) & 0xFF;
Uint8 g = (lpDDBltFx->dwFillColor >> 8) & 0xFF; Uint8 g = (lpDDBltFx->dwFillColor >> 8) & 0xFF;
Uint8 b = lpDDBltFx->dwFillColor & 0xFF; Uint8 b = lpDDBltFx->dwFillColor & 0xFF;
DirectDrawPaletteImpl* ddPal = static_cast<DirectDrawPaletteImpl*>(m_palette); DDRenderer->Clear(r / 255.0f, g / 255.0f, b / 255.0f);
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; return DD_OK;
} }
auto other = static_cast<DirectDrawSurfaceImpl*>(lpDDSrcSurface); auto surface = static_cast<DirectDrawSurfaceImpl*>(lpDDSrcSurface);
if (!other) { if (!surface) {
return DDERR_GENERIC; return DDERR_GENERIC;
} }
SDL_Rect srcRect = lpSrcRect ? ConvertRect(lpSrcRect) : SDL_Rect{0, 0, other->m_surface->w, other->m_surface->h}; Uint32 textureId = DDRenderer->GetTextureId(surface->ToTexture());
SDL_Rect dstRect = lpDestRect ? ConvertRect(lpDestRect) : SDL_Rect{0, 0, DDBackBuffer->w, DDBackBuffer->h}; SDL_Rect srcRect =
lpSrcRect ? ConvertRect(lpSrcRect) : SDL_Rect{0, 0, surface->m_surface->w, surface->m_surface->h};
SDL_Rect dstRect =
lpDestRect ? ConvertRect(lpDestRect) : SDL_Rect{0, 0, (int) m_virtualWidth, (int) m_virtualHeight};
DDRenderer->Draw2DImage(textureId, srcRect, dstRect);
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; return DD_OK;
} }
@ -100,20 +80,20 @@ HRESULT FrameBufferImpl::BltFast(
DDBltFastFlags dwTrans DDBltFastFlags dwTrans
) )
{ {
RECT destRect = { auto surface = static_cast<DirectDrawSurfaceImpl*>(lpDDSrcSurface);
(int) dwX, int width = lpSrcRect ? (lpSrcRect->right - lpSrcRect->left) : surface->m_surface->w;
(int) dwY, int height = lpSrcRect ? (lpSrcRect->bottom - lpSrcRect->top) : surface->m_surface->h;
(int) (lpSrcRect->right - lpSrcRect->left + dwX), RECT destRect = {(int) dwX, (int) dwY, (int) (dwX + width), (int) (dwY + height)};
(int) (lpSrcRect->bottom - lpSrcRect->top + dwY)
};
return Blt(&destRect, lpDDSrcSurface, lpSrcRect, DDBLT_NONE, nullptr); return Blt(&destRect, lpDDSrcSurface, lpSrcRect, DDBLT_NONE, nullptr);
} }
HRESULT FrameBufferImpl::Flip(LPDIRECTDRAWSURFACE lpDDSurfaceTargetOverride, DDFlipFlags dwFlags) HRESULT FrameBufferImpl::Flip(LPDIRECTDRAWSURFACE lpDDSurfaceTargetOverride, DDFlipFlags dwFlags)
{ {
SDL_UpdateTexture(m_uploadBuffer, nullptr, DDBackBuffer->pixels, DDBackBuffer->pitch); if (!DDRenderer) {
SDL_RenderTexture(DDRenderer, m_uploadBuffer, nullptr, nullptr); return DDERR_GENERIC;
SDL_RenderPresent(DDRenderer); }
DDRenderer->Flip();
return DD_OK; return DD_OK;
} }
@ -146,7 +126,7 @@ HRESULT FrameBufferImpl::GetPixelFormat(LPDDPIXELFORMAT lpDDPixelFormat)
{ {
memset(lpDDPixelFormat, 0, sizeof(*lpDDPixelFormat)); memset(lpDDPixelFormat, 0, sizeof(*lpDDPixelFormat));
lpDDPixelFormat->dwFlags = DDPF_RGB; lpDDPixelFormat->dwFlags = DDPF_RGB;
const SDL_PixelFormatDetails* details = SDL_GetPixelFormatDetails(DDBackBuffer->format); const SDL_PixelFormatDetails* details = SDL_GetPixelFormatDetails(m_transferBuffer->m_surface->format);
if (details->bits_per_pixel == 8) { if (details->bits_per_pixel == 8) {
lpDDPixelFormat->dwFlags |= DDPF_PALETTEINDEXED8; lpDDPixelFormat->dwFlags |= DDPF_PALETTEINDEXED8;
} }
@ -163,25 +143,28 @@ HRESULT FrameBufferImpl::GetSurfaceDesc(LPDDSURFACEDESC lpDDSurfaceDesc)
lpDDSurfaceDesc->dwFlags = DDSD_PIXELFORMAT; lpDDSurfaceDesc->dwFlags = DDSD_PIXELFORMAT;
GetPixelFormat(&lpDDSurfaceDesc->ddpfPixelFormat); GetPixelFormat(&lpDDSurfaceDesc->ddpfPixelFormat);
lpDDSurfaceDesc->dwFlags |= DDSD_WIDTH | DDSD_HEIGHT; lpDDSurfaceDesc->dwFlags |= DDSD_WIDTH | DDSD_HEIGHT;
lpDDSurfaceDesc->dwWidth = DDBackBuffer->w; lpDDSurfaceDesc->dwWidth = m_transferBuffer->m_surface->w;
lpDDSurfaceDesc->dwHeight = DDBackBuffer->h; lpDDSurfaceDesc->dwHeight = m_transferBuffer->m_surface->h;
return DD_OK;
}
HRESULT FrameBufferImpl::IsLost()
{
return DD_OK; return DD_OK;
} }
HRESULT FrameBufferImpl::Lock(LPRECT lpDestRect, DDSURFACEDESC* lpDDSurfaceDesc, DDLockFlags dwFlags, HANDLE hEvent) HRESULT FrameBufferImpl::Lock(LPRECT lpDestRect, DDSURFACEDESC* lpDDSurfaceDesc, DDLockFlags dwFlags, HANDLE hEvent)
{ {
if (!SDL_LockSurface(DDBackBuffer)) { if (!DDRenderer) {
return DDERR_GENERIC; return DDERR_GENERIC;
} }
if ((dwFlags & DDLOCK_WRITEONLY) == DDLOCK_WRITEONLY) {
SDL_Rect rect = {0, 0, m_transferBuffer->m_surface->w, m_transferBuffer->m_surface->h};
const SDL_PixelFormatDetails* details = SDL_GetPixelFormatDetails(m_transferBuffer->m_surface->format);
SDL_Palette* palette = m_palette ? static_cast<DirectDrawPaletteImpl*>(m_palette)->m_palette : nullptr;
Uint32 color = SDL_MapRGBA(details, palette, 0, 0, 0, 0);
SDL_FillSurfaceRect(m_transferBuffer->m_surface, &rect, color);
}
else {
DDRenderer->Download(m_transferBuffer->m_surface);
}
GetSurfaceDesc(lpDDSurfaceDesc); m_transferBuffer->Lock(lpDestRect, lpDDSurfaceDesc, dwFlags, hEvent);
lpDDSurfaceDesc->lpSurface = DDBackBuffer->pixels;
lpDDSurfaceDesc->lPitch = DDBackBuffer->pitch;
return DD_OK; return DD_OK;
} }
@ -198,11 +181,6 @@ HRESULT FrameBufferImpl::Restore()
return DD_OK; return DD_OK;
} }
HRESULT FrameBufferImpl::SetClipper(LPDIRECTDRAWCLIPPER lpDDClipper)
{
return DD_OK;
}
HRESULT FrameBufferImpl::SetColorKey(DDColorKeyFlags dwFlags, LPDDCOLORKEY lpDDColorKey) HRESULT FrameBufferImpl::SetColorKey(DDColorKeyFlags dwFlags, LPDDCOLORKEY lpDDColorKey)
{ {
MINIWIN_NOT_IMPLEMENTED(); MINIWIN_NOT_IMPLEMENTED();
@ -211,7 +189,7 @@ HRESULT FrameBufferImpl::SetColorKey(DDColorKeyFlags dwFlags, LPDDCOLORKEY lpDDC
HRESULT FrameBufferImpl::SetPalette(LPDIRECTDRAWPALETTE lpDDPalette) HRESULT FrameBufferImpl::SetPalette(LPDIRECTDRAWPALETTE lpDDPalette)
{ {
if (DDBackBuffer->format != SDL_PIXELFORMAT_INDEX8) { if (m_transferBuffer->m_surface->format != SDL_PIXELFORMAT_INDEX8) {
MINIWIN_NOT_IMPLEMENTED(); MINIWIN_NOT_IMPLEMENTED();
} }
@ -220,13 +198,15 @@ HRESULT FrameBufferImpl::SetPalette(LPDIRECTDRAWPALETTE lpDDPalette)
} }
m_palette = lpDDPalette; m_palette = lpDDPalette;
SDL_SetSurfacePalette(DDBackBuffer, ((DirectDrawPaletteImpl*) m_palette)->m_palette); SDL_SetSurfacePalette(m_transferBuffer->m_surface, ((DirectDrawPaletteImpl*) m_palette)->m_palette);
m_palette->AddRef(); m_palette->AddRef();
return DD_OK; return DD_OK;
} }
HRESULT FrameBufferImpl::Unlock(LPVOID lpSurfaceData) HRESULT FrameBufferImpl::Unlock(LPVOID lpSurfaceData)
{ {
SDL_UnlockSurface(DDBackBuffer); m_transferBuffer->Unlock(lpSurfaceData);
BltFast(0, 0, m_transferBuffer, nullptr, DDBLTFAST_WAIT);
return DD_OK; return DD_OK;
} }

View File

@ -11,8 +11,8 @@ struct Direct3DRMDevice2Impl : public Direct3DRMObjectBaseImpl<IDirect3DRMDevice
Direct3DRMDevice2Impl(DWORD width, DWORD height, Direct3DRMRenderer* renderer); Direct3DRMDevice2Impl(DWORD width, DWORD height, Direct3DRMRenderer* renderer);
~Direct3DRMDevice2Impl() override; ~Direct3DRMDevice2Impl() override;
HRESULT QueryInterface(const GUID& riid, void** ppvObject) override; HRESULT QueryInterface(const GUID& riid, void** ppvObject) override;
DWORD GetWidth() override; DWORD GetWidth() override { return m_virtualWidth; }
DWORD GetHeight() override; DWORD GetHeight() override { return m_virtualHeight; }
HRESULT SetBufferCount(int count) override; HRESULT SetBufferCount(int count) override;
DWORD GetBufferCount() override; DWORD GetBufferCount() override;
HRESULT SetShades(DWORD shadeCount) override; HRESULT SetShades(DWORD shadeCount) override;
@ -38,7 +38,10 @@ struct Direct3DRMDevice2Impl : public Direct3DRMObjectBaseImpl<IDirect3DRMDevice
Direct3DRMRenderer* m_renderer; Direct3DRMRenderer* m_renderer;
private: private:
DWORD m_width; void Resize();
DWORD m_height;
uint32_t m_virtualWidth;
uint32_t m_virtualHeight;
ViewportTransform m_viewportTransform;
IDirect3DRMViewportArray* m_viewports; IDirect3DRMViewportArray* m_viewports;
}; };

View File

@ -10,7 +10,7 @@ struct MeshGroup {
IDirect3DRMTexture* texture = nullptr; IDirect3DRMTexture* texture = nullptr;
IDirect3DRMMaterial* material = nullptr; IDirect3DRMMaterial* material = nullptr;
D3DRMRENDERQUALITY quality = D3DRMRENDER_GOURAUD; D3DRMRENDERQUALITY quality = D3DRMRENDER_GOURAUD;
int vertexPerFace = 0; int vertexPerFace = 3;
int version = 0; int version = 0;
std::vector<D3DRMVERTEX> vertices; std::vector<D3DRMVERTEX> vertices;
std::vector<DWORD> indices; std::vector<DWORD> indices;

View File

@ -26,8 +26,6 @@ struct Plane {
float d; float d;
}; };
extern SDL_Renderer* DDRenderer;
class Direct3DRMRenderer : public IDirect3DDevice2 { class Direct3DRMRenderer : public IDirect3DDevice2 {
public: public:
virtual void PushLights(const SceneLight* vertices, size_t count) = 0; virtual void PushLights(const SceneLight* vertices, size_t count) = 0;
@ -35,8 +33,10 @@ class Direct3DRMRenderer : public IDirect3DDevice2 {
virtual void SetFrustumPlanes(const Plane* frustumPlanes) = 0; virtual void SetFrustumPlanes(const Plane* frustumPlanes) = 0;
virtual Uint32 GetTextureId(IDirect3DRMTexture* texture) = 0; virtual Uint32 GetTextureId(IDirect3DRMTexture* texture) = 0;
virtual Uint32 GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* meshGroup) = 0; virtual Uint32 GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* meshGroup) = 0;
virtual DWORD GetWidth() = 0; int GetWidth() { return m_width; }
virtual DWORD GetHeight() = 0; int GetHeight() { return m_height; }
int GetVirtualWidth() { return m_virtualWidth; }
int GetVirtualHeight() { return m_virtualHeight; }
virtual void GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc) = 0; virtual void GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc) = 0;
virtual const char* GetName() = 0; virtual const char* GetName() = 0;
virtual HRESULT BeginFrame() = 0; virtual HRESULT BeginFrame() = 0;
@ -44,13 +44,20 @@ class Direct3DRMRenderer : public IDirect3DDevice2 {
virtual void SubmitDraw( virtual void SubmitDraw(
DWORD meshId, DWORD meshId,
const D3DRMMATRIX4D& modelViewMatrix, const D3DRMMATRIX4D& modelViewMatrix,
const D3DRMMATRIX4D& worldMatrix,
const D3DRMMATRIX4D& viewMatrix,
const Matrix3x3& normalMatrix, const Matrix3x3& normalMatrix,
const Appearance& appearance const Appearance& appearance
) = 0; ) = 0;
virtual HRESULT FinalizeFrame() = 0; virtual HRESULT FinalizeFrame() = 0;
virtual void Resize(int width, int height, const ViewportTransform& viewportTransform) = 0;
virtual void Clear(float r, float g, float b) = 0;
virtual void Flip() = 0;
virtual void Draw2DImage(Uint32 textureId, const SDL_Rect& srcRect, const SDL_Rect& dstRect) = 0;
virtual void Download(SDL_Surface* target) = 0;
bool ConvertEventToRenderCoordinates(SDL_Event* event) protected:
{ int m_width, m_height;
return SDL_ConvertEventToRenderCoordinates(DDRenderer, event); int m_virtualWidth, m_virtualHeight;
} ViewportTransform m_viewportTransform;
}; };

View File

@ -20,8 +20,6 @@ class DirectX9Renderer : public Direct3DRMRenderer {
void SetFrustumPlanes(const Plane* frustumPlanes) override; void SetFrustumPlanes(const Plane* frustumPlanes) override;
Uint32 GetTextureId(IDirect3DRMTexture* texture) override; Uint32 GetTextureId(IDirect3DRMTexture* texture) override;
Uint32 GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* meshGroup) override; Uint32 GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* meshGroup) override;
DWORD GetWidth() override;
DWORD GetHeight() override;
void GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc) override; void GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc) override;
const char* GetName() override; const char* GetName() override;
HRESULT BeginFrame() override; HRESULT BeginFrame() override;
@ -29,17 +27,23 @@ class DirectX9Renderer : public Direct3DRMRenderer {
void SubmitDraw( void SubmitDraw(
DWORD meshId, DWORD meshId,
const D3DRMMATRIX4D& modelViewMatrix, const D3DRMMATRIX4D& modelViewMatrix,
const D3DRMMATRIX4D& worldMatrix,
const D3DRMMATRIX4D& viewMatrix,
const Matrix3x3& normalMatrix, const Matrix3x3& normalMatrix,
const Appearance& appearance const Appearance& appearance
) override; ) override;
HRESULT FinalizeFrame() override; HRESULT FinalizeFrame() override;
void Resize(int width, int height, const ViewportTransform& viewportTransform) override;
void Clear(float r, float g, float b) override;
void Flip() override;
void Draw2DImage(Uint32 textureId, const SDL_Rect& srcRect, const SDL_Rect& dstRect) override;
void Download(SDL_Surface* target) override;
private: private:
void AddTextureDestroyCallback(Uint32 id, IDirect3DRMTexture* texture); void AddTextureDestroyCallback(Uint32 id, IDirect3DRMTexture* texture);
void AddMeshDestroyCallback(Uint32 id, IDirect3DRMMesh* mesh); void AddMeshDestroyCallback(Uint32 id, IDirect3DRMMesh* mesh);
SDL_Surface* m_renderedImage; SDL_Surface* m_renderedImage;
DWORD m_width, m_height;
std::vector<SceneLight> m_lights; std::vector<SceneLight> m_lights;
std::vector<D3D9MeshCacheEntry> m_meshs; std::vector<D3D9MeshCacheEntry> m_meshs;
std::vector<D3D9TextureCacheEntry> m_textures; std::vector<D3D9TextureCacheEntry> m_textures;

View File

@ -42,7 +42,7 @@ struct GLMeshCacheEntry {
class OpenGL1Renderer : public Direct3DRMRenderer { class OpenGL1Renderer : public Direct3DRMRenderer {
public: public:
static Direct3DRMRenderer* Create(DWORD width, DWORD height); static Direct3DRMRenderer* Create(DWORD width, DWORD height);
OpenGL1Renderer(DWORD width, DWORD height, SDL_GLContext context, GLuint fbo, GLuint colorTex, GLuint depthRb); OpenGL1Renderer(DWORD width, DWORD height, SDL_GLContext context);
~OpenGL1Renderer() override; ~OpenGL1Renderer() override;
void PushLights(const SceneLight* lightsArray, size_t count) override; void PushLights(const SceneLight* lightsArray, size_t count) override;
@ -50,8 +50,6 @@ class OpenGL1Renderer : public Direct3DRMRenderer {
void SetFrustumPlanes(const Plane* frustumPlanes) override; void SetFrustumPlanes(const Plane* frustumPlanes) override;
Uint32 GetTextureId(IDirect3DRMTexture* texture) override; Uint32 GetTextureId(IDirect3DRMTexture* texture) override;
Uint32 GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* meshGroup) override; Uint32 GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* meshGroup) override;
DWORD GetWidth() override;
DWORD GetHeight() override;
void GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc) override; void GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc) override;
const char* GetName() override; const char* GetName() override;
HRESULT BeginFrame() override; HRESULT BeginFrame() override;
@ -59,10 +57,17 @@ class OpenGL1Renderer : public Direct3DRMRenderer {
void SubmitDraw( void SubmitDraw(
DWORD meshId, DWORD meshId,
const D3DRMMATRIX4D& modelViewMatrix, const D3DRMMATRIX4D& modelViewMatrix,
const D3DRMMATRIX4D& worldMatrix,
const D3DRMMATRIX4D& viewMatrix,
const Matrix3x3& normalMatrix, const Matrix3x3& normalMatrix,
const Appearance& appearance const Appearance& appearance
) override; ) override;
HRESULT FinalizeFrame() override; HRESULT FinalizeFrame() override;
void Resize(int width, int height, const ViewportTransform& viewportTransform) override;
void Clear(float r, float g, float b) override;
void Flip() override;
void Draw2DImage(Uint32 textureId, const SDL_Rect& srcRect, const SDL_Rect& dstRect) override;
void Download(SDL_Surface* target) override;
private: private:
void AddTextureDestroyCallback(Uint32 id, IDirect3DRMTexture* texture); void AddTextureDestroyCallback(Uint32 id, IDirect3DRMTexture* texture);
@ -72,13 +77,11 @@ class OpenGL1Renderer : public Direct3DRMRenderer {
std::vector<GLMeshCacheEntry> m_meshs; std::vector<GLMeshCacheEntry> m_meshs;
D3DRMMATRIX4D m_projection; D3DRMMATRIX4D m_projection;
SDL_Surface* m_renderedImage; SDL_Surface* m_renderedImage;
DWORD m_width, m_height;
bool m_useVBOs; bool m_useVBOs;
bool m_dirty = false;
std::vector<SceneLight> m_lights; std::vector<SceneLight> m_lights;
SDL_GLContext m_context; SDL_GLContext m_context;
GLuint m_fbo; ViewportTransform m_viewportTransform;
GLuint m_colorTex;
GLuint m_depthRb;
}; };
inline static void OpenGL1Renderer_EnumDevice(LPD3DENUMDEVICESCALLBACK cb, void* ctx) inline static void OpenGL1Renderer_EnumDevice(LPD3DENUMDEVICESCALLBACK cb, void* ctx)

View File

@ -14,6 +14,8 @@ struct GLES2TextureCacheEntry {
IDirect3DRMTexture* texture; IDirect3DRMTexture* texture;
Uint32 version; Uint32 version;
GLuint glTextureId; GLuint glTextureId;
uint16_t width;
uint16_t height;
}; };
struct GLES2MeshCacheEntry { struct GLES2MeshCacheEntry {
@ -31,15 +33,7 @@ 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);
OpenGLES2Renderer( OpenGLES2Renderer(DWORD width, DWORD height, SDL_GLContext context, GLuint shaderProgram);
DWORD width,
DWORD height,
SDL_GLContext context,
GLuint fbo,
GLuint colorTex,
GLuint vertexBuffer,
GLuint shaderProgram
);
~OpenGLES2Renderer() override; ~OpenGLES2Renderer() override;
void PushLights(const SceneLight* lightsArray, size_t count) override; void PushLights(const SceneLight* lightsArray, size_t count) override;
@ -47,8 +41,6 @@ class OpenGLES2Renderer : public Direct3DRMRenderer {
void SetFrustumPlanes(const Plane* frustumPlanes) override; void SetFrustumPlanes(const Plane* frustumPlanes) override;
Uint32 GetTextureId(IDirect3DRMTexture* texture) override; Uint32 GetTextureId(IDirect3DRMTexture* texture) override;
Uint32 GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* meshGroup) override; Uint32 GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* meshGroup) override;
DWORD GetWidth() override;
DWORD GetHeight() override;
void GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc) override; void GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc) override;
const char* GetName() override; const char* GetName() override;
HRESULT BeginFrame() override; HRESULT BeginFrame() override;
@ -56,10 +48,17 @@ class OpenGLES2Renderer : public Direct3DRMRenderer {
void SubmitDraw( void SubmitDraw(
DWORD meshId, DWORD meshId,
const D3DRMMATRIX4D& modelViewMatrix, const D3DRMMATRIX4D& modelViewMatrix,
const D3DRMMATRIX4D& worldMatrix,
const D3DRMMATRIX4D& viewMatrix,
const Matrix3x3& normalMatrix, const Matrix3x3& normalMatrix,
const Appearance& appearance const Appearance& appearance
) override; ) override;
HRESULT FinalizeFrame() override; HRESULT FinalizeFrame() override;
void Resize(int width, int height, const ViewportTransform& viewportTransform) override;
void Clear(float r, float g, float b) override;
void Flip() override;
void Draw2DImage(Uint32 textureId, const SDL_Rect& srcRect, const SDL_Rect& dstRect) override;
void Download(SDL_Surface* target) override;
private: private:
void AddTextureDestroyCallback(Uint32 id, IDirect3DRMTexture* texture); void AddTextureDestroyCallback(Uint32 id, IDirect3DRMTexture* texture);
@ -69,13 +68,11 @@ class OpenGLES2Renderer : public Direct3DRMRenderer {
std::vector<GLES2MeshCacheEntry> m_meshs; std::vector<GLES2MeshCacheEntry> m_meshs;
D3DRMMATRIX4D m_projection; D3DRMMATRIX4D m_projection;
SDL_Surface* m_renderedImage; SDL_Surface* m_renderedImage;
DWORD m_width, m_height; bool m_dirty = false;
std::vector<SceneLight> m_lights; std::vector<SceneLight> m_lights;
SDL_GLContext m_context; SDL_GLContext m_context;
GLuint m_fbo;
GLuint m_colorTex;
GLuint m_depthRb;
GLuint m_shaderProgram; GLuint m_shaderProgram;
ViewportTransform m_viewportTransform;
}; };
inline static void OpenGLES2Renderer_EnumDevice(LPD3DENUMDEVICESCALLBACK cb, void* ctx) inline static void OpenGLES2Renderer_EnumDevice(LPD3DENUMDEVICESCALLBACK cb, void* ctx)

View File

@ -51,8 +51,6 @@ class Direct3DRMSDL3GPURenderer : public Direct3DRMRenderer {
Uint32 GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* meshGroup) override; Uint32 GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* meshGroup) override;
void SetProjection(const D3DRMMATRIX4D& projection, D3DVALUE front, D3DVALUE back) override; void SetProjection(const D3DRMMATRIX4D& projection, D3DVALUE front, D3DVALUE back) override;
void SetFrustumPlanes(const Plane* frustumPlanes) override; void SetFrustumPlanes(const Plane* frustumPlanes) override;
DWORD GetWidth() override;
DWORD GetHeight() override;
void GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc) override; void GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc) override;
const char* GetName() override; const char* GetName() override;
HRESULT BeginFrame() override; HRESULT BeginFrame() override;
@ -60,10 +58,17 @@ class Direct3DRMSDL3GPURenderer : public Direct3DRMRenderer {
void SubmitDraw( void SubmitDraw(
DWORD meshId, DWORD meshId,
const D3DRMMATRIX4D& modelViewMatrix, const D3DRMMATRIX4D& modelViewMatrix,
const D3DRMMATRIX4D& worldMatrix,
const D3DRMMATRIX4D& viewMatrix,
const Matrix3x3& normalMatrix, const Matrix3x3& normalMatrix,
const Appearance& appearance const Appearance& appearance
) override; ) override;
HRESULT FinalizeFrame() override; HRESULT FinalizeFrame() override;
void Resize(int width, int height, const ViewportTransform& viewportTransform) override;
void Clear(float r, float g, float b) override;
void Flip() override;
void Draw2DImage(Uint32 textureId, const SDL_Rect& srcRect, const SDL_Rect& dstRect) override;
void Download(SDL_Surface* target) override;
private: private:
Direct3DRMSDL3GPURenderer( Direct3DRMSDL3GPURenderer(
@ -72,12 +77,13 @@ class Direct3DRMSDL3GPURenderer : public Direct3DRMRenderer {
SDL_GPUDevice* device, SDL_GPUDevice* device,
SDL_GPUGraphicsPipeline* opaquePipeline, SDL_GPUGraphicsPipeline* opaquePipeline,
SDL_GPUGraphicsPipeline* transparentPipeline, SDL_GPUGraphicsPipeline* transparentPipeline,
SDL_GPUTexture* transferTexture, SDL_GPUGraphicsPipeline* uiPipeline,
SDL_GPUTexture* depthTexture,
SDL_GPUSampler* sampler, SDL_GPUSampler* sampler,
SDL_GPUSampler* uiSampler,
SDL_GPUTransferBuffer* uploadBuffer, SDL_GPUTransferBuffer* uploadBuffer,
SDL_GPUTransferBuffer* downloadBuffer int uploadBufferSize
); );
void StartRenderPass(float r, float g, float b, bool clear);
void WaitForPendingUpload(); void WaitForPendingUpload();
void AddTextureDestroyCallback(Uint32 id, IDirect3DRMTexture* texture); void AddTextureDestroyCallback(Uint32 id, IDirect3DRMTexture* texture);
SDL_GPUTransferBuffer* GetUploadBuffer(size_t size); SDL_GPUTransferBuffer* GetUploadBuffer(size_t size);
@ -85,26 +91,29 @@ class Direct3DRMSDL3GPURenderer : public Direct3DRMRenderer {
void AddMeshDestroyCallback(Uint32 id, IDirect3DRMMesh* mesh); void AddMeshDestroyCallback(Uint32 id, IDirect3DRMMesh* mesh);
SDL3MeshCache UploadMesh(const MeshGroup& meshGroup); SDL3MeshCache UploadMesh(const MeshGroup& meshGroup);
DWORD m_width; MeshGroup m_uiMesh;
DWORD m_height; SDL3MeshCache m_uiMeshCache;
D3DVALUE m_front; D3DVALUE m_front;
D3DVALUE m_back; D3DVALUE m_back;
ViewportUniforms m_uniforms; ViewportUniforms m_uniforms;
FragmentShadingData m_fragmentShadingData; FragmentShadingData m_fragmentShadingData;
D3DDEVICEDESC m_desc; D3DDEVICEDESC m_desc;
D3DRMMATRIX4D m_projection;
std::vector<SDL3TextureCache> m_textures; std::vector<SDL3TextureCache> m_textures;
std::vector<SDL3MeshCache> m_meshs; std::vector<SDL3MeshCache> m_meshs;
SDL_GPUDevice* m_device; SDL_GPUDevice* m_device;
SDL_GPUGraphicsPipeline* m_opaquePipeline; SDL_GPUGraphicsPipeline* m_opaquePipeline;
SDL_GPUGraphicsPipeline* m_transparentPipeline; SDL_GPUGraphicsPipeline* m_transparentPipeline;
SDL_GPUTexture* m_transferTexture; SDL_GPUGraphicsPipeline* m_uiPipeline;
SDL_GPUTexture* m_depthTexture; SDL_GPUTexture* m_transferTexture = nullptr;
SDL_GPUTexture* m_depthTexture = nullptr;
SDL_GPUTexture* m_dummyTexture; SDL_GPUTexture* m_dummyTexture;
int m_uploadBufferSize; int m_uploadBufferSize;
SDL_GPUTransferBuffer* m_uploadBuffer; SDL_GPUTransferBuffer* m_uploadBuffer;
SDL_GPUTransferBuffer* m_downloadBuffer; SDL_GPUTransferBuffer* m_downloadBuffer = nullptr;
SDL_GPUBuffer* m_vertexBuffer = nullptr; SDL_GPUBuffer* m_vertexBuffer = nullptr;
SDL_GPUSampler* m_sampler; SDL_GPUSampler* m_sampler;
SDL_GPUSampler* m_uiSampler;
SDL_GPUCommandBuffer* m_cmdbuf = nullptr; SDL_GPUCommandBuffer* m_cmdbuf = nullptr;
SDL_GPURenderPass* m_renderPass = nullptr; SDL_GPURenderPass* m_renderPass = nullptr;
SDL_GPUFence* m_uploadFence = nullptr; SDL_GPUFence* m_uploadFence = nullptr;

View File

@ -27,13 +27,12 @@ struct MeshCache {
class Direct3DRMSoftwareRenderer : public Direct3DRMRenderer { class Direct3DRMSoftwareRenderer : public Direct3DRMRenderer {
public: public:
Direct3DRMSoftwareRenderer(DWORD width, DWORD height); Direct3DRMSoftwareRenderer(DWORD width, DWORD height);
~Direct3DRMSoftwareRenderer() override;
void PushLights(const SceneLight* vertices, size_t count) override; void PushLights(const SceneLight* vertices, size_t count) override;
Uint32 GetTextureId(IDirect3DRMTexture* texture) override; Uint32 GetTextureId(IDirect3DRMTexture* texture) override;
Uint32 GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* meshGroup) override; Uint32 GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* meshGroup) override;
void SetProjection(const D3DRMMATRIX4D& projection, D3DVALUE front, D3DVALUE back) override; void SetProjection(const D3DRMMATRIX4D& projection, D3DVALUE front, D3DVALUE back) override;
void SetFrustumPlanes(const Plane* frustumPlanes) override; void SetFrustumPlanes(const Plane* frustumPlanes) override;
DWORD GetWidth() override;
DWORD GetHeight() override;
void GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc) override; void GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc) override;
const char* GetName() override; const char* GetName() override;
HRESULT BeginFrame() override; HRESULT BeginFrame() override;
@ -41,10 +40,17 @@ class Direct3DRMSoftwareRenderer : public Direct3DRMRenderer {
void SubmitDraw( void SubmitDraw(
DWORD meshId, DWORD meshId,
const D3DRMMATRIX4D& modelViewMatrix, const D3DRMMATRIX4D& modelViewMatrix,
const D3DRMMATRIX4D& worldMatrix,
const D3DRMMATRIX4D& viewMatrix,
const Matrix3x3& normalMatrix, const Matrix3x3& normalMatrix,
const Appearance& appearance const Appearance& appearance
) override; ) override;
HRESULT FinalizeFrame() override; HRESULT FinalizeFrame() override;
void Resize(int width, int height, const ViewportTransform& viewportTransform) override;
void Clear(float r, float g, float b) override;
void Flip() override;
void Draw2DImage(Uint32 textureId, const SDL_Rect& srcRect, const SDL_Rect& dstRect) override;
void Download(SDL_Surface* target) override;
private: private:
void ClearZBuffer(); void ClearZBuffer();
@ -61,9 +67,10 @@ class Direct3DRMSoftwareRenderer : public Direct3DRMRenderer {
void AddTextureDestroyCallback(Uint32 id, IDirect3DRMTexture* texture); void AddTextureDestroyCallback(Uint32 id, IDirect3DRMTexture* texture);
void AddMeshDestroyCallback(Uint32 id, IDirect3DRMMesh* mesh); void AddMeshDestroyCallback(Uint32 id, IDirect3DRMMesh* mesh);
DWORD m_width; SDL_Surface* m_renderedImage = nullptr;
DWORD m_height;
SDL_Palette* m_palette; SDL_Palette* m_palette;
SDL_Texture* m_uploadBuffer = nullptr;
SDL_Renderer* m_renderer;
const SDL_PixelFormatDetails* m_format; const SDL_PixelFormatDetails* m_format;
int m_bytesPerPixel; int m_bytesPerPixel;
std::vector<SceneLight> m_lights; std::vector<SceneLight> m_lights;

View File

@ -4,10 +4,12 @@
struct Direct3DRMTextureImpl : public Direct3DRMObjectBaseImpl<IDirect3DRMTexture2> { struct Direct3DRMTextureImpl : public Direct3DRMObjectBaseImpl<IDirect3DRMTexture2> {
Direct3DRMTextureImpl(D3DRMIMAGE* image); Direct3DRMTextureImpl(D3DRMIMAGE* image);
Direct3DRMTextureImpl(IDirectDrawSurface* surface); Direct3DRMTextureImpl(IDirectDrawSurface* surface, bool holdsRef);
~Direct3DRMTextureImpl() override;
HRESULT QueryInterface(const GUID& riid, void** ppvObject) override; HRESULT QueryInterface(const GUID& riid, void** ppvObject) override;
HRESULT Changed(BOOL pixels, BOOL palette) override; HRESULT Changed(BOOL pixels, BOOL palette) override;
IDirectDrawSurface* m_surface = nullptr; IDirectDrawSurface* m_surface = nullptr;
Uint8 m_version = 0; Uint8 m_version = 0;
bool m_holdsRef;
}; };

View File

@ -10,6 +10,7 @@
struct DeferredDrawCommand { struct DeferredDrawCommand {
DWORD meshId; DWORD meshId;
D3DRMMATRIX4D modelViewMatrix; D3DRMMATRIX4D modelViewMatrix;
D3DRMMATRIX4D worldMatrix;
Matrix3x3 normalMatrix; Matrix3x3 normalMatrix;
Appearance appearance; Appearance appearance;
float depth; float depth;
@ -36,24 +37,24 @@ struct Direct3DRMViewportImpl : public Direct3DRMObjectBaseImpl<IDirect3DRMViewp
D3DVALUE GetBack() override; D3DVALUE GetBack() override;
HRESULT SetField(D3DVALUE field) override; HRESULT SetField(D3DVALUE field) override;
D3DVALUE GetField() override; D3DVALUE GetField() override;
DWORD GetWidth() override; DWORD GetWidth() override { return m_virtualWidth; }
DWORD GetHeight() override; DWORD GetHeight() override { return m_virtualHeight; }
HRESULT Transform(D3DRMVECTOR4D* screen, D3DVECTOR* world) override; HRESULT Transform(D3DRMVECTOR4D* screen, D3DVECTOR* world) override;
HRESULT InverseTransform(D3DVECTOR* world, D3DRMVECTOR4D* screen) override; HRESULT InverseTransform(D3DVECTOR* world, D3DRMVECTOR4D* screen) override;
HRESULT Pick(float x, float y, LPDIRECT3DRMPICKEDARRAY* pickedArray) override; HRESULT Pick(float x, float y, LPDIRECT3DRMPICKEDARRAY* pickedArray) override;
void CloseDevice(); void CloseDevice();
void UpdateProjectionMatrix();
private: private:
HRESULT RenderScene(); HRESULT RenderScene();
void CollectLightsFromFrame(IDirect3DRMFrame* frame, D3DRMMATRIX4D parentMatrix, std::vector<SceneLight>& lights); void CollectLightsFromFrame(IDirect3DRMFrame* frame, D3DRMMATRIX4D parentMatrix, std::vector<SceneLight>& lights);
void CollectMeshesFromFrame(IDirect3DRMFrame* frame, D3DRMMATRIX4D parentMatrix); void CollectMeshesFromFrame(IDirect3DRMFrame* frame, D3DRMMATRIX4D parentMatrix);
void BuildViewFrustumPlanes(); void BuildViewFrustumPlanes();
void UpdateProjectionMatrix();
Direct3DRMRenderer* m_renderer; Direct3DRMRenderer* m_renderer;
std::vector<DeferredDrawCommand> m_deferredDraws; std::vector<DeferredDrawCommand> m_deferredDraws;
D3DCOLOR m_backgroundColor = 0xFF000000; D3DCOLOR m_backgroundColor = 0xFF000000;
DWORD m_width; DWORD m_virtualWidth;
DWORD m_height; DWORD m_virtualHeight;
D3DRMMATRIX4D m_viewProjectionwMatrix; D3DRMMATRIX4D m_viewProjectionwMatrix;
D3DRMMATRIX4D m_viewMatrix; D3DRMMATRIX4D m_viewMatrix;
D3DRMMATRIX4D m_projectionMatrix; D3DRMMATRIX4D m_projectionMatrix;

View File

@ -8,9 +8,7 @@
#include <SDL3/SDL.h> #include <SDL3/SDL.h>
extern SDL_Window* DDWindow; extern SDL_Window* DDWindow;
extern SDL_Surface* DDBackBuffer; extern Direct3DRMRenderer* DDRenderer;
extern FrameBufferImpl* DDFrameBuffer;
extern SDL_Renderer* DDRenderer;
inline static SDL_Rect ConvertRect(const RECT* r) inline static SDL_Rect ConvertRect(const RECT* r)
{ {
@ -47,6 +45,11 @@ 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;
private:
FrameBufferImpl* m_frameBuffer;
int m_virtualWidth = 0;
int m_virtualHeight = 0;
}; };
HRESULT DirectDrawEnumerate(LPDDENUMCALLBACKA cb, void* context); HRESULT DirectDrawEnumerate(LPDDENUMCALLBACKA cb, void* context);

View File

@ -35,8 +35,11 @@ struct DirectDrawSurfaceImpl : public IDirectDrawSurface3 {
HRESULT SetPalette(LPDIRECTDRAWPALETTE lpDDPalette) override; HRESULT SetPalette(LPDIRECTDRAWPALETTE lpDDPalette) override;
HRESULT Unlock(LPVOID lpSurfaceData) override; HRESULT Unlock(LPVOID lpSurfaceData) override;
IDirect3DRMTexture2* ToTexture();
SDL_Surface* m_surface = nullptr; SDL_Surface* m_surface = nullptr;
private: private:
IDirect3DRMTexture2* m_texture = nullptr;
IDirectDrawPalette* m_palette = nullptr; IDirectDrawPalette* m_palette = nullptr;
}; };

View File

@ -5,7 +5,7 @@
#include <miniwin/ddraw.h> #include <miniwin/ddraw.h>
struct FrameBufferImpl : public IDirectDrawSurface3 { struct FrameBufferImpl : public IDirectDrawSurface3 {
FrameBufferImpl(); FrameBufferImpl(DWORD virtualWidth, DWORD virtualHeight);
~FrameBufferImpl() override; ~FrameBufferImpl() override;
// IUnknown interface // IUnknown interface
@ -27,16 +27,18 @@ struct FrameBufferImpl : public IDirectDrawSurface3 {
HRESULT GetPalette(LPDIRECTDRAWPALETTE* lplpDDPalette) override; HRESULT GetPalette(LPDIRECTDRAWPALETTE* lplpDDPalette) override;
HRESULT GetPixelFormat(LPDDPIXELFORMAT lpDDPixelFormat) override; HRESULT GetPixelFormat(LPDDPIXELFORMAT lpDDPixelFormat) override;
HRESULT GetSurfaceDesc(DDSURFACEDESC* lpDDSurfaceDesc) override; HRESULT GetSurfaceDesc(DDSURFACEDESC* lpDDSurfaceDesc) override;
HRESULT IsLost() override; HRESULT IsLost() override { return DD_OK; }
HRESULT Lock(LPRECT lpDestRect, DDSURFACEDESC* lpDDSurfaceDesc, DDLockFlags dwFlags, HANDLE hEvent) override; HRESULT Lock(LPRECT lpDestRect, DDSURFACEDESC* lpDDSurfaceDesc, DDLockFlags dwFlags, HANDLE hEvent) override;
HRESULT ReleaseDC(HDC hDC) override; HRESULT ReleaseDC(HDC hDC) override;
HRESULT Restore() override; HRESULT Restore() override;
HRESULT SetClipper(IDirectDrawClipper* lpDDClipper) override; HRESULT SetClipper(IDirectDrawClipper* lpDDClipper) override { return DD_OK; }
HRESULT SetColorKey(DDColorKeyFlags dwFlags, LPDDCOLORKEY lpDDColorKey) override; HRESULT SetColorKey(DDColorKeyFlags dwFlags, LPDDCOLORKEY lpDDColorKey) override;
HRESULT SetPalette(LPDIRECTDRAWPALETTE lpDDPalette) override; HRESULT SetPalette(LPDIRECTDRAWPALETTE lpDDPalette) override;
HRESULT Unlock(LPVOID lpSurfaceData) override; HRESULT Unlock(LPVOID lpSurfaceData) override;
private: private:
SDL_Texture* m_uploadBuffer; uint32_t m_virtualWidth;
uint32_t m_virtualHeight;
DirectDrawSurfaceImpl* m_transferBuffer;
IDirectDrawPalette* m_palette = nullptr; IDirectDrawPalette* m_palette = nullptr;
}; };

View File

@ -15,3 +15,9 @@ struct Appearance {
uint32_t textureId; uint32_t textureId;
uint32_t flat; uint32_t flat;
}; };
struct ViewportTransform {
float scale;
float offsetX;
float offsetY;
};