From 402bdb1b57744c39b33be7cc422de43a4c41e2c8 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Fri, 21 Jun 2024 21:08:57 +1000 Subject: [PATCH] Implement scissoring for Direct3D9/11/OpenGL too --- misc/opengl/GL1Funcs.h | 1 + misc/opengl/GLCommon.h | 2 ++ src/Graphics_D3D11.c | 50 +++++++++++++++++++++++++--------------- src/Graphics_D3D9.c | 12 ++++++++++ src/Graphics_Dreamcast.c | 15 +++++------- src/Graphics_SoftGPU.c | 21 ++++++++++------- src/_GLShared.h | 7 ++++++ 7 files changed, 73 insertions(+), 35 deletions(-) diff --git a/misc/opengl/GL1Funcs.h b/misc/opengl/GL1Funcs.h index d4a8b01dc..5a97ee942 100644 --- a/misc/opengl/GL1Funcs.h +++ b/misc/opengl/GL1Funcs.h @@ -33,6 +33,7 @@ GL_FUNC(void, glVertexPointer)(GLint size, GLenum type, GLsizei stride, GLpointe GL_FUNC(void, glClear)(GLuint mask); GL_FUNC(void, glHint)(GLenum target, GLenum mode); GL_FUNC(void, glReadPixels)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels); +GL_FUNC(void, glScissor)(GLint x, GLint y, GLsizei width, GLsizei height); /* Texture functions */ GL_FUNC(void, glBindTexture)(GLenum target, GLuint texture); diff --git a/misc/opengl/GLCommon.h b/misc/opengl/GLCommon.h index 4722c14bf..b894ad021 100644 --- a/misc/opengl/GLCommon.h +++ b/misc/opengl/GLCommon.h @@ -63,6 +63,8 @@ typedef cc_uintptr GLpointer; #define GL_MATRIX_MODE 0x0BA0 #define GL_VIEWPORT 0x0BA2 #define GL_ALPHA_TEST 0x0BC0 +#define GL_SCISSOR_TEST 0x0C11 + #define GL_MAX_TEXTURE_SIZE 0x0D33 #define GL_DEPTH_BITS 0x0D56 diff --git a/src/Graphics_D3D11.c b/src/Graphics_D3D11.c index a6005ac4a..912c50663 100644 --- a/src/Graphics_D3D11.c +++ b/src/Graphics_D3D11.c @@ -630,22 +630,35 @@ void Gfx_DisableTextureOffset(void) { //---------------------------------------------------------Rasteriser----------------------------------------------------- //######################################################################################################################## // https://docs.microsoft.com/en-us/windows/win32/direct3d11/d3d10-graphics-programming-guide-rasterizer-stage -static ID3D11RasterizerState* rs_states[2]; -static cc_bool rs_culling; +static ID3D11RasterizerState* rs_states[4]; +static cc_bool rs_culling, rs_scissor; static void RS_CreateRasterState(void) { // https://docs.microsoft.com/en-us/windows/win32/api/d3d11/ns-d3d11-d3d11_rasterizer_desc D3D11_RASTERIZER_DESC desc = { 0 }; - desc.CullMode = D3D11_CULL_NONE; - desc.FillMode = D3D11_FILL_SOLID; - desc.FrontCounterClockwise = true; - desc.DepthClipEnable = true; // otherwise vertices/pixels beyond far plane are still wrongly rendered - ID3D11Device_CreateRasterizerState(device, &desc, &rs_states[0]); - - desc.CullMode = D3D11_CULL_BACK; - ID3D11Device_CreateRasterizerState(device, &desc, &rs_states[1]); + for (int i = 0; i < Array_Elems(rs_states); i++) + { + desc.CullMode = (i & 1) ? D3D11_CULL_BACK : D3D11_CULL_NONE; + desc.ScissorEnable = (i & 2) != 0; + desc.FillMode = D3D11_FILL_SOLID; + desc.FrontCounterClockwise = true; + desc.DepthClipEnable = true; // otherwise vertices/pixels beyond far plane are still wrongly rendered + ID3D11Device_CreateRasterizerState(device, &desc, &rs_states[i]); + } } +static void RS_UpdateRasterState(void) { + ID3D11DeviceContext_RSSetState(context, rs_states[rs_culling | (rs_scissor << 1)]); +} + +static void RS_FreeRasterStates(void) { + for (int i = 0; i < Array_Elems(rs_states); i++) + { + ID3D11RasterizerState_Release(rs_states[i]); + } +} + + void Gfx_SetViewport(int x, int y, int w, int h) { D3D11_VIEWPORT viewport; viewport.TopLeftX = x; @@ -657,15 +670,16 @@ void Gfx_SetViewport(int x, int y, int w, int h) { ID3D11DeviceContext_RSSetViewports(context, 1, &viewport); } -static void RS_UpdateRasterState(void) { - ID3D11DeviceContext_RSSetState(context, rs_states[rs_culling]); -} +void Gfx_SetScissor(int x, int y, int w, int h) { + rs_scissor = x != 0 || y != 0 || w != Game.Width || h != Game.Height; -static void RS_FreeRasterStates(void) { - for (int i = 0; i < Array_Elems(rs_states); i++) - { - ID3D11RasterizerState_Release(rs_states[i]); - } + D3D11_RECT rect; + rect.left = x; + rect.top = y; + rect.right = x + w; + rect.bottom = y + h; + ID3D11DeviceContext_RSSetScissorRects(context, 1, &rect); + RS_UpdateRasterState(); } static void RS_Init(void) { diff --git a/src/Graphics_D3D9.c b/src/Graphics_D3D9.c index 7f0a14bc9..3a7fd05fc 100644 --- a/src/Graphics_D3D9.c +++ b/src/Graphics_D3D9.c @@ -891,4 +891,16 @@ void Gfx_SetViewport(int x, int y, int w, int h) { vp.MaxZ = 1.0f; IDirect3DDevice9_SetViewport(device, &vp); } + +void Gfx_SetScissor(int x, int y, int w, int h) { + cc_bool enabled = x != 0 || y != 0 || w != Game.Width || h != Game.Height; + RECT rect; + rect.left = x; + rect.top = y; + rect.right = x + w; + rect.bottom = y + h; + + IDirect3DDevice9_SetRenderState(device, D3DRS_SCISSORTESTENABLE, enabled); + IDirect3DDevice9_SetScissorRect(device, &rect); +} #endif diff --git a/src/Graphics_Dreamcast.c b/src/Graphics_Dreamcast.c index f51cedf59..8e28ddc7f 100644 --- a/src/Graphics_Dreamcast.c +++ b/src/Graphics_Dreamcast.c @@ -624,15 +624,6 @@ extern float VP_COL_X_PLUS_HWIDTH, VP_TEX_X_PLUS_HWIDTH; extern float VP_COL_Y_PLUS_HHEIGHT, VP_TEX_Y_PLUS_HHEIGHT; void Gfx_SetViewport(int x, int y, int w, int h) { - if (x == 0 && y == 0 && w == Game.Width && h == Game.Height) { - SCISSOR_TEST_ENABLED = GL_FALSE; - } else { - SCISSOR_TEST_ENABLED = GL_TRUE; - } - STATE_DIRTY = GL_TRUE; - - glScissor (x, y, w, h); - VIEWPORT.hwidth = w * 0.5f; VIEWPORT.hheight = h * -0.5f; VIEWPORT.x_plus_hwidth = x + w * 0.5f; @@ -644,4 +635,10 @@ void Gfx_SetViewport(int x, int y, int w, int h) { VP_COL_X_PLUS_HWIDTH = VP_TEX_X_PLUS_HWIDTH = x + w * 0.5f; VP_COL_Y_PLUS_HHEIGHT = VP_TEX_Y_PLUS_HHEIGHT = y + h * 0.5f; } + +void Gfx_SetScissor(int x, int y, int w, int h) { + SCISSOR_TEST_ENABLED = x != 0 || y != 0 || w != Game.Width || h != Game.Height; + STATE_DIRTY = GL_TRUE; + glScissor(x, y, w, h); +} #endif diff --git a/src/Graphics_SoftGPU.c b/src/Graphics_SoftGPU.c index a6175688c..d7455e120 100644 --- a/src/Graphics_SoftGPU.c +++ b/src/Graphics_SoftGPU.c @@ -932,22 +932,27 @@ void Gfx_OnWindowResize(void) { fb_width = Game.Width; fb_height = Game.Height; - vp_hwidth = fb_width / 2.0f; - vp_hheight = fb_height / 2.0f; - - fb_maxX = fb_width - 1; - fb_maxY = fb_height - 1; - Window_AllocFramebuffer(&fb_bmp, Game.Width, Game.Height); colorBuffer = fb_bmp.scan0; cb_stride = fb_bmp.width; depthBuffer = Mem_Alloc(fb_width * fb_height, 4, "depth buffer"); db_stride = fb_width; + + Gfx_SetViewport(0, 0, Game.Width, Game.Height); + Gfx_SetScissor (0, 0, Game.Width, Game.Height); } -void Gfx_SetViewport(int x, int y, int w, int h) { } -void Gfx_SetScissor (int x, int y, int w, int h) { } +void Gfx_SetViewport(int x, int y, int w, int h) { + vp_hwidth = w / 2.0f; + vp_hheight = h / 2.0f; +} + +void Gfx_SetScissor (int x, int y, int w, int h) { + /* TODO minX/Y */ + fb_maxX = x + w - 1; + fb_maxY = y + h - 1; +} void Gfx_GetApiInfo(cc_string* info) { int pointerSize = sizeof(void*) * 8; diff --git a/src/_GLShared.h b/src/_GLShared.h index cd27a047a..6c71b37bb 100644 --- a/src/_GLShared.h +++ b/src/_GLShared.h @@ -336,3 +336,10 @@ void Gfx_OnWindowResize(void) { void Gfx_SetViewport(int x, int y, int w, int h) { glViewport(x, y, w, h); } + +void Gfx_SetScissor(int x, int y, int w, int h) { + cc_bool enabled = x != 0 || y != 0 || w != Game.Width || h != Game.Height; + if (enabled) { glEnable(GL_SCISSOR_TEST); } else { glDisable(GL_SCISSOR_TEST); } + + glScissor(x, Game.Height - h - y, w, h); +}