From ac77d1c3e0507f4f4c89b9caac27ce25124646d6 Mon Sep 17 00:00:00 2001 From: vladislavbelov Date: Tue, 1 Feb 2022 17:58:21 +0000 Subject: [PATCH] Moves scissor test management to DeviceCommandContext. This was SVN commit r26288. --- source/graphics/MiniMapTexture.cpp | 8 ++-- source/graphics/TextRenderer.h | 4 +- source/gui/CGUIText.cpp | 21 ++++++---- source/gui/ObjectTypes/CInput.cpp | 21 ++++++---- source/renderer/SceneRenderer.cpp | 20 +++++++--- source/renderer/ShadowMap.cpp | 13 ++++--- .../backend/gl/DeviceCommandContext.cpp | 39 +++++++++++++++++++ .../backend/gl/DeviceCommandContext.h | 12 ++++++ 8 files changed, 105 insertions(+), 33 deletions(-) diff --git a/source/graphics/MiniMapTexture.cpp b/source/graphics/MiniMapTexture.cpp index 49dde63e6e..20c2e3eaeb 100644 --- a/source/graphics/MiniMapTexture.cpp +++ b/source/graphics/MiniMapTexture.cpp @@ -497,8 +497,10 @@ void CMiniMapTexture::RenderFinalTexture( if (m_EntitiesDrawn > 0) { - glEnable(GL_SCISSOR_TEST); - glScissor(1, 1, FINAL_TEXTURE_SIZE - 2, FINAL_TEXTURE_SIZE - 2); + Renderer::Backend::GL::CDeviceCommandContext::ScissorRect scissorRect; + scissorRect.x = scissorRect.y = 1; + scissorRect.width = scissorRect.height = FINAL_TEXTURE_SIZE - 2; + deviceCommandContext->SetScissors(1, &scissorRect); #if !CONFIG2_GLES glEnable(GL_VERTEX_PROGRAM_POINT_SIZE); #endif @@ -519,7 +521,7 @@ void CMiniMapTexture::RenderFinalTexture( #if !CONFIG2_GLES glDisable(GL_VERTEX_PROGRAM_POINT_SIZE); #endif - glDisable(GL_SCISSOR_TEST); + deviceCommandContext->SetScissors(0, nullptr); } tech->EndPass(); diff --git a/source/graphics/TextRenderer.h b/source/graphics/TextRenderer.h index 6101fb1e3b..5b1dce54ff 100644 --- a/source/graphics/TextRenderer.h +++ b/source/graphics/TextRenderer.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2021 Wildfire Games. +/* Copyright (C) 2022 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -45,7 +45,7 @@ public: /** * Set clipping rectangle, in pre-transform coordinates (i.e. text is clipped against * this rect based purely on the x,y values passed into Put()). Text fully outside the - * clipping rectangle may not be rendered. Should be used in conjunction with glScissor + * clipping rectangle may not be rendered. Should be used in conjunction with SetScissors * for precise clipping - this is just an optimisation. */ void SetClippingRect(const CRect& rect); diff --git a/source/gui/CGUIText.cpp b/source/gui/CGUIText.cpp index be4cf0c1d3..1bb15354eb 100644 --- a/source/gui/CGUIText.cpp +++ b/source/gui/CGUIText.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2021 Wildfire Games. +/* Copyright (C) 2022 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -27,6 +27,7 @@ #include "gui/SettingTypes/CGUIString.h" #include "ps/CStrInternStatic.h" #include "ps/VideoMode.h" +#include "renderer/backend/gl/DeviceCommandContext.h" #include "renderer/Renderer.h" #include @@ -430,6 +431,9 @@ bool CGUIText::AssembleCalls( void CGUIText::Draw(CGUI& pGUI, CCanvas2D& canvas, const CGUIColor& DefaultColor, const CVector2D& pos, CRect clipping) const { + Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext = + g_Renderer.GetDeviceCommandContext(); + bool isClipped = clipping != CRect(); if (isClipped) { @@ -440,12 +444,13 @@ void CGUIText::Draw(CGUI& pGUI, CCanvas2D& canvas, const CGUIColor& DefaultColor clipping.right = std::floor(clipping.right); float scale = g_VideoMode.GetScale(); - glEnable(GL_SCISSOR_TEST); - glScissor( - std::ceil(clipping.left * scale), - std::ceil(g_yres - clipping.bottom * scale), - std::floor(clipping.GetWidth() * scale), - std::floor(clipping.GetHeight() * scale)); + Renderer::Backend::GL::CDeviceCommandContext::ScissorRect scissorRect; + scissorRect.x = std::ceil(clipping.left * scale); + scissorRect.y = std::ceil(g_yres - clipping.bottom * scale); + scissorRect.width = std::floor(clipping.GetWidth() * scale); + scissorRect.height = std::floor(clipping.GetHeight() * scale); + // TODO: move scissors to CCanvas2D. + deviceCommandContext->SetScissors(1, &scissorRect); } CTextRenderer textRenderer; @@ -469,5 +474,5 @@ void CGUIText::Draw(CGUI& pGUI, CCanvas2D& canvas, const CGUIColor& DefaultColor pGUI.DrawSprite(sc.m_Sprite, canvas, sc.m_Area + pos); if (isClipped) - glDisable(GL_SCISSOR_TEST); + deviceCommandContext->SetScissors(0, nullptr); } diff --git a/source/gui/ObjectTypes/CInput.cpp b/source/gui/ObjectTypes/CInput.cpp index a8a821a7bc..a6fda55719 100644 --- a/source/gui/ObjectTypes/CInput.cpp +++ b/source/gui/ObjectTypes/CInput.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2021 Wildfire Games. +/* Copyright (C) 2022 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -32,6 +32,7 @@ #include "ps/Globals.h" #include "ps/Hotkey.h" #include "ps/VideoMode.h" +#include "renderer/backend/gl/DeviceCommandContext.h" #include "renderer/Renderer.h" #include @@ -1190,6 +1191,9 @@ void CInput::UpdateCachedSize() void CInput::Draw(CCanvas2D& canvas) { + Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext = + g_Renderer.GetDeviceCommandContext(); + if (m_CursorBlinkRate > 0.0) { // check if the cursor visibility state needs to be changed @@ -1240,12 +1244,13 @@ void CInput::Draw(CCanvas2D& canvas) if (cliparea != CRect()) { float scale = g_VideoMode.GetScale(); - glEnable(GL_SCISSOR_TEST); - glScissor( - cliparea.left * scale, - g_yres - cliparea.bottom * scale, - cliparea.GetWidth() * scale, - cliparea.GetHeight() * scale); + Renderer::Backend::GL::CDeviceCommandContext::ScissorRect scissorRect; + scissorRect.x = cliparea.left * scale; + scissorRect.y = g_yres - cliparea.bottom * scale; + scissorRect.width = cliparea.GetWidth() * scale; + scissorRect.height = cliparea.GetHeight() * scale; + // TODO: move scissors to CCanvas2D. + deviceCommandContext->SetScissors(1, &scissorRect); } // These are useful later. @@ -1515,7 +1520,7 @@ void CInput::Draw(CCanvas2D& canvas) canvas.DrawText(textRenderer); if (cliparea != CRect()) - glDisable(GL_SCISSOR_TEST); + deviceCommandContext->SetScissors(0, nullptr); if (m_Caption->empty() && !m_PlaceholderText->GetRawString().empty()) DrawPlaceholderText(canvas, cliparea); diff --git a/source/renderer/SceneRenderer.cpp b/source/renderer/SceneRenderer.cpp index 256a243198..0c7d31177e 100644 --- a/source/renderer/SceneRenderer.cpp +++ b/source/renderer/SceneRenderer.cpp @@ -632,8 +632,12 @@ void CSceneRenderer::RenderReflections( screenScissor.x2 = (GLint)ceil((reflectionScissor[1].X*0.5f+0.5f)*vpWidth); screenScissor.y2 = (GLint)ceil((reflectionScissor[1].Y*0.5f+0.5f)*vpHeight); - glEnable(GL_SCISSOR_TEST); - glScissor(screenScissor.x1, screenScissor.y1, screenScissor.x2 - screenScissor.x1, screenScissor.y2 - screenScissor.y1); + Renderer::Backend::GL::CDeviceCommandContext::ScissorRect scissorRect; + scissorRect.x = screenScissor.x1; + scissorRect.y = screenScissor.y1; + scissorRect.width = screenScissor.x2 - screenScissor.x1; + scissorRect.height = screenScissor.y2 - screenScissor.y1; + deviceCommandContext->SetScissors(1, &scissorRect); // try binding the framebuffer glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, wm.m_ReflectionFbo); @@ -670,7 +674,7 @@ void CSceneRenderer::RenderReflections( ogl_WarnIfError(); } - glDisable(GL_SCISSOR_TEST); + deviceCommandContext->SetScissors(0, nullptr); // Reset old camera m_ViewCamera = normalCamera; @@ -715,8 +719,12 @@ void CSceneRenderer::RenderRefractions( screenScissor.x2 = (GLint)ceil((refractionScissor[1].X*0.5f+0.5f)*vpWidth); screenScissor.y2 = (GLint)ceil((refractionScissor[1].Y*0.5f+0.5f)*vpHeight); - glEnable(GL_SCISSOR_TEST); - glScissor(screenScissor.x1, screenScissor.y1, screenScissor.x2 - screenScissor.x1, screenScissor.y2 - screenScissor.y1); + Renderer::Backend::GL::CDeviceCommandContext::ScissorRect scissorRect; + scissorRect.x = screenScissor.x1; + scissorRect.y = screenScissor.y1; + scissorRect.width = screenScissor.x2 - screenScissor.x1; + scissorRect.height = screenScissor.y2 - screenScissor.y1; + deviceCommandContext->SetScissors(1, &scissorRect); // try binding the framebuffer glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, wm.m_RefractionFbo); @@ -735,7 +743,7 @@ void CSceneRenderer::RenderRefractions( RenderTransparentModels(deviceCommandContext, context, CULL_REFRACTIONS, TRANSPARENT_OPAQUE); ogl_WarnIfError(); - glDisable(GL_SCISSOR_TEST); + deviceCommandContext->SetScissors(0, nullptr); // Reset old camera m_ViewCamera = normalCamera; diff --git a/source/renderer/ShadowMap.cpp b/source/renderer/ShadowMap.cpp index f35a2519ac..36c9b16c6c 100644 --- a/source/renderer/ShadowMap.cpp +++ b/source/renderer/ShadowMap.cpp @@ -632,8 +632,6 @@ void ShadowMap::BeginRender() } m->SavedViewCamera = g_Renderer.GetSceneRenderer().GetViewCamera(); - - glEnable(GL_SCISSOR_TEST); } void ShadowMap::PrepareCamera(const int cascade) @@ -649,15 +647,18 @@ void ShadowMap::PrepareCamera(const int cascade) g_Renderer.GetSceneRenderer().SetViewCamera(camera); const SViewPort& cascadeViewPort = m->Cascades[cascade].ViewPort; - glScissor( - cascadeViewPort.m_X, cascadeViewPort.m_Y, - cascadeViewPort.m_Width, cascadeViewPort.m_Height); + Renderer::Backend::GL::CDeviceCommandContext::ScissorRect scissorRect; + scissorRect.x = cascadeViewPort.m_X; + scissorRect.y = cascadeViewPort.m_Y; + scissorRect.width = cascadeViewPort.m_Width; + scissorRect.height = cascadeViewPort.m_Height; + g_Renderer.GetDeviceCommandContext()->SetScissors(1, &scissorRect); } // Finish rendering into shadow map texture void ShadowMap::EndRender() { - glDisable(GL_SCISSOR_TEST); + g_Renderer.GetDeviceCommandContext()->SetScissors(0, nullptr); g_Renderer.GetSceneRenderer().SetViewCamera(m->SavedViewCamera); diff --git a/source/renderer/backend/gl/DeviceCommandContext.cpp b/source/renderer/backend/gl/DeviceCommandContext.cpp index 19ed2cb0bf..009b38723a 100644 --- a/source/renderer/backend/gl/DeviceCommandContext.cpp +++ b/source/renderer/backend/gl/DeviceCommandContext.cpp @@ -47,6 +47,22 @@ bool operator!=(const StencilOpState& lhs, const StencilOpState& rhs) return !operator==(lhs, rhs); } +bool operator==( + const CDeviceCommandContext::ScissorRect& lhs, + const CDeviceCommandContext::ScissorRect& rhs) +{ + return + lhs.x == rhs.x && lhs.y == rhs.y && + lhs.width == rhs.width && lhs.height == rhs.height; +} + +bool operator!=( + const CDeviceCommandContext::ScissorRect& lhs, + const CDeviceCommandContext::ScissorRect& rhs) +{ + return !operator==(lhs, rhs); +} + } // anonymous namespace // static @@ -149,6 +165,7 @@ void CDeviceCommandContext::Flush() void CDeviceCommandContext::ResetStates() { SetGraphicsPipelineStateImpl(MakeDefaultGraphicsPipelineStateDesc(), true); + SetScissors(0, nullptr); } void CDeviceCommandContext::SetGraphicsPipelineStateImpl( @@ -337,6 +354,28 @@ void CDeviceCommandContext::SetGraphicsPipelineStateImpl( m_GraphicsPipelineStateDesc = pipelineStateDesc; } +void CDeviceCommandContext::SetScissors(const uint32_t scissorCount, const ScissorRect* scissors) +{ + ENSURE(scissorCount <= 1); + if (scissorCount == 0) + { + if (m_ScissorCount != scissorCount) + glDisable(GL_SCISSOR_TEST); + } + else + { + if (m_ScissorCount != scissorCount) + glEnable(GL_SCISSOR_TEST); + if (m_ScissorCount != scissorCount || m_Scissors[0] != scissors[0]) + { + ENSURE(scissors); + m_Scissors[0] = scissors[0]; + glScissor(m_Scissors[0].x, m_Scissors[0].y, m_Scissors[0].width, m_Scissors[0].height); + } + } + m_ScissorCount = scissorCount; +} + } // namespace GL } // namespace Backend diff --git a/source/renderer/backend/gl/DeviceCommandContext.h b/source/renderer/backend/gl/DeviceCommandContext.h index 7733ea83e1..02207630f4 100644 --- a/source/renderer/backend/gl/DeviceCommandContext.h +++ b/source/renderer/backend/gl/DeviceCommandContext.h @@ -21,6 +21,7 @@ #include "renderer/backend/Format.h" #include "renderer/backend/PipelineState.h" +#include #include #include @@ -53,6 +54,14 @@ public: const uint32_t width, const uint32_t height, const uint32_t level = 0, const uint32_t layer = 0); + // TODO: maybe we should add a more common type, like CRectI. + struct ScissorRect + { + int32_t x, y; + int32_t width, height; + }; + void SetScissors(const uint32_t scissorCount, const ScissorRect* scissors); + void Flush(); private: @@ -64,6 +73,9 @@ private: const GraphicsPipelineStateDesc& pipelineStateDesc, const bool force); GraphicsPipelineStateDesc m_GraphicsPipelineStateDesc{}; + uint32_t m_ScissorCount = 0; + // GL2.1 doesn't support more than 1 scissor. + std::array m_Scissors; }; } // namespace GL