1
0
forked from 0ad/0ad

Removes scissor backend setup from GUI.

Differential Revision: https://code.wildfiregames.com/D5051
This was SVN commit r27798.
This commit is contained in:
Vladislav Belov 2023-08-15 17:29:45 +00:00
parent 23f1949e2a
commit 5ba7ec3bfa
4 changed files with 75 additions and 47 deletions

View File

@ -25,6 +25,7 @@
#include "graphics/TextureManager.h"
#include "maths/Rect.h"
#include "maths/Vector2D.h"
#include "ps/containers/StaticVector.h"
#include "ps/CStrInternStatic.h"
#include "renderer/Renderer.h"
@ -159,6 +160,22 @@ public:
return transform;
}
void ApplyScissors()
{
if (!Scissors.empty())
{
CRect rect = Scissors.back();
Renderer::Backend::IDeviceCommandContext::Rect scissorRect;
scissorRect.x = std::ceil(rect.left * Scale);
scissorRect.y = std::ceil(static_cast<float>(HeightInPixels) - rect.bottom * Scale);
scissorRect.width = std::floor(rect.GetWidth() * Scale);
scissorRect.height = std::floor(rect.GetHeight() * Scale);
DeviceCommandContext->SetScissors(1, &scissorRect);
}
else
DeviceCommandContext->SetScissors(0, nullptr);
}
uint32_t WidthInPixels = 1;
uint32_t HeightInPixels = 1;
float Scale = 1.0f;
@ -173,6 +190,8 @@ public:
// We assume that the shader can't be destroyed while it's bound. So these
// bindings remain valid while the shader is alive.
SBindingSlots BindingSlots;
PS::StaticVector<CRect, 4> Scissors;
};
CCanvas2D::CCanvas2D(
@ -186,6 +205,7 @@ CCanvas2D::CCanvas2D(
CCanvas2D::~CCanvas2D()
{
Flush();
ENSURE(m->Scissors.empty());
}
void CCanvas2D::DrawLine(const std::vector<CVector2D>& points, const float width, const CColor& color)
@ -448,6 +468,20 @@ void CCanvas2D::DrawText(CTextRenderer& textRenderer)
m->DeviceCommandContext, m->Tech->GetShader(), m->TransformScale, m->Translation);
}
void CCanvas2D::PushScissor(const CRect& scissor)
{
ENSURE(!m->Scissors.full());
m->Scissors.emplace_back(scissor);
m->ApplyScissors();
}
void CCanvas2D::PopScissor()
{
ENSURE(!m->Scissors.empty());
m->Scissors.pop_back();
m->ApplyScissors();
}
void CCanvas2D::Flush()
{
m->UnbindTech();

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2022 Wildfire Games.
/* Copyright (C) 2023 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -90,7 +90,37 @@ public:
void DrawText(CTextRenderer& textRenderer);
/**
* Unbinds all binded resources and clears caches. Frequent calls might
* Adds the scissor rect to a scissor stack. The only top scissor is
* applied. It's recommended to use as few nested scissors as possible.
*/
void PushScissor(const CRect& scissor);
/**
* Removes the top scissor rect from a scissor stack. The stack must not be
* empty.
*/
void PopScissor();
class ScopedScissor
{
public:
ScopedScissor(CCanvas2D& canvas, const CRect& scissor)
: m_Canvas(canvas)
{
m_Canvas.PushScissor(scissor);
}
~ScopedScissor()
{
m_Canvas.PopScissor();
}
private:
CCanvas2D& m_Canvas;
};
/**
* Unbinds all bound resources and clears caches. Frequent calls might
* affect performance. Useful to call a custom rendering code.
*/
void Flush();

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2022 Wildfire Games.
/* Copyright (C) 2023 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -26,11 +26,9 @@
#include "gui/ObjectBases/IGUIObject.h"
#include "gui/SettingTypes/CGUIString.h"
#include "ps/CStrInternStatic.h"
#include "ps/VideoMode.h"
#include "renderer/backend/IDeviceCommandContext.h"
#include "renderer/Renderer.h"
#include <math.h>
#include <cmath>
#include <optional>
extern int g_xres, g_yres;
@ -450,29 +448,13 @@ bool CGUIText::AssembleCalls(
void CGUIText::Draw(CGUI& pGUI, CCanvas2D& canvas, const CGUIColor& DefaultColor, const CVector2D& pos, CRect clipping) const
{
Renderer::Backend::IDeviceCommandContext* deviceCommandContext =
g_Renderer.GetDeviceCommandContext();
const bool isClipped = clipping != CRect();
std::optional<CCanvas2D::ScopedScissor> scopedScissor;
if (isClipped)
{
// Make clipping rect as small as possible to prevent rounding errors
clipping.top = std::ceil(clipping.top);
clipping.bottom = std::floor(clipping.bottom);
clipping.left = std::ceil(clipping.left);
clipping.right = std::floor(clipping.right);
if (clipping.GetWidth() <= 0.0f || clipping.GetHeight() <= 0.0f)
return;
const float scale = g_VideoMode.GetScale();
Renderer::Backend::IDeviceCommandContext::Rect 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);
scopedScissor.emplace(canvas, clipping);
}
CTextRenderer textRenderer;
@ -494,7 +476,4 @@ void CGUIText::Draw(CGUI& pGUI, CCanvas2D& canvas, const CGUIColor& DefaultColor
for (const SSpriteCall& sc : m_SpriteCalls)
pGUI.DrawSprite(sc.m_Sprite, canvas, sc.m_Area + pos);
if (isClipped)
deviceCommandContext->SetScissors(0, nullptr);
}

View File

@ -31,9 +31,6 @@
#include "ps/GameSetup/Config.h"
#include "ps/Globals.h"
#include "ps/Hotkey.h"
#include "ps/VideoMode.h"
#include "renderer/backend/IDeviceCommandContext.h"
#include "renderer/Renderer.h"
#include <sstream>
@ -1488,9 +1485,6 @@ void CInput::DrawContent(CCanvas2D& canvas)
void CInput::Draw(CCanvas2D& canvas)
{
Renderer::Backend::IDeviceCommandContext* deviceCommandContext =
g_Renderer.GetDeviceCommandContext();
// We'll have to setup clipping manually, since we're doing the rendering manually.
CRect cliparea(m_CachedActualSize);
@ -1513,20 +1507,11 @@ void CInput::Draw(CCanvas2D& canvas)
{
if (cliparea.GetWidth() <= 0.0f || cliparea.GetHeight() <= 0.0f)
return;
const float scale = g_VideoMode.GetScale();
Renderer::Backend::IDeviceCommandContext::Rect 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);
CCanvas2D::ScopedScissor scopedScissor(canvas, cliparea);
DrawContent(canvas);
}
DrawContent(canvas);
if (isClipped)
deviceCommandContext->SetScissors(0, nullptr);
else
DrawContent(canvas);
if (m_Caption->empty() && !m_PlaceholderText->GetRawString().empty())
DrawPlaceholderText(canvas, cliparea);