summaryrefslogtreecommitdiff
path: root/Source/Core/VideoCommon/AbstractGfx.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/Core/VideoCommon/AbstractGfx.cpp')
-rw-r--r--Source/Core/VideoCommon/AbstractGfx.cpp138
1 files changed, 138 insertions, 0 deletions
diff --git a/Source/Core/VideoCommon/AbstractGfx.cpp b/Source/Core/VideoCommon/AbstractGfx.cpp
new file mode 100644
index 0000000000..4406cd46b6
--- /dev/null
+++ b/Source/Core/VideoCommon/AbstractGfx.cpp
@@ -0,0 +1,138 @@
+// Copyright 2023 Dolphin Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "VideoCommon/AbstractGfx.h"
+
+#include "Common/Assert.h"
+
+#include "VideoCommon/AbstractFramebuffer.h"
+#include "VideoCommon/AbstractTexture.h"
+#include "VideoCommon/FramebufferManager.h"
+#include "VideoCommon/RenderBase.h"
+#include "VideoCommon/ShaderCache.h"
+#include "VideoCommon/VertexManagerBase.h"
+#include "VideoCommon/VideoConfig.h"
+
+bool AbstractGfx::IsHeadless() const
+{
+ return true;
+}
+
+void AbstractGfx::BeginUtilityDrawing()
+{
+ if (g_renderer)
+ g_renderer->BeginUtilityDrawing();
+}
+
+void AbstractGfx::EndUtilityDrawing()
+{
+ if (g_renderer)
+ g_renderer->EndUtilityDrawing();
+}
+
+void AbstractGfx::SetFramebuffer(AbstractFramebuffer* framebuffer)
+{
+ m_current_framebuffer = framebuffer;
+}
+
+void AbstractGfx::SetAndDiscardFramebuffer(AbstractFramebuffer* framebuffer)
+{
+ m_current_framebuffer = framebuffer;
+}
+
+void AbstractGfx::SetAndClearFramebuffer(AbstractFramebuffer* framebuffer,
+ const ClearColor& color_value, float depth_value)
+{
+ m_current_framebuffer = framebuffer;
+}
+
+void AbstractGfx::ClearRegion(const MathUtil::Rectangle<int>& rc,
+ const MathUtil::Rectangle<int>& target_rc, bool colorEnable,
+ bool alphaEnable, bool zEnable, u32 color, u32 z)
+{
+ g_framebuffer_manager->ClearEFB(rc, colorEnable, alphaEnable, zEnable, color, z);
+}
+
+void AbstractGfx::SetViewportAndScissor(const MathUtil::Rectangle<int>& rect, float min_depth,
+ float max_depth)
+{
+ SetViewport(static_cast<float>(rect.left), static_cast<float>(rect.top),
+ static_cast<float>(rect.GetWidth()), static_cast<float>(rect.GetHeight()), min_depth,
+ max_depth);
+ SetScissorRect(rect);
+}
+
+void AbstractGfx::ScaleTexture(AbstractFramebuffer* dst_framebuffer,
+ const MathUtil::Rectangle<int>& dst_rect,
+ const AbstractTexture* src_texture,
+ const MathUtil::Rectangle<int>& src_rect)
+{
+ ASSERT(dst_framebuffer->GetColorFormat() == AbstractTextureFormat::RGBA8);
+
+ BeginUtilityDrawing();
+
+ // The shader needs to know the source rectangle.
+ const auto converted_src_rect =
+ ConvertFramebufferRectangle(src_rect, src_texture->GetWidth(), src_texture->GetHeight());
+ const float rcp_src_width = 1.0f / src_texture->GetWidth();
+ const float rcp_src_height = 1.0f / src_texture->GetHeight();
+ const std::array<float, 4> uniforms = {{converted_src_rect.left * rcp_src_width,
+ converted_src_rect.top * rcp_src_height,
+ converted_src_rect.GetWidth() * rcp_src_width,
+ converted_src_rect.GetHeight() * rcp_src_height}};
+ g_vertex_manager->UploadUtilityUniforms(&uniforms, sizeof(uniforms));
+
+ // Discard if we're overwriting the whole thing.
+ if (static_cast<u32>(dst_rect.GetWidth()) == dst_framebuffer->GetWidth() &&
+ static_cast<u32>(dst_rect.GetHeight()) == dst_framebuffer->GetHeight())
+ {
+ SetAndDiscardFramebuffer(dst_framebuffer);
+ }
+ else
+ {
+ SetFramebuffer(dst_framebuffer);
+ }
+
+ SetViewportAndScissor(ConvertFramebufferRectangle(dst_rect, dst_framebuffer));
+ SetPipeline(dst_framebuffer->GetLayers() > 1 ? g_shader_cache->GetRGBA8StereoCopyPipeline() :
+ g_shader_cache->GetRGBA8CopyPipeline());
+ SetTexture(0, src_texture);
+ SetSamplerState(0, RenderState::GetLinearSamplerState());
+ Draw(0, 3);
+ EndUtilityDrawing();
+ if (dst_framebuffer->GetColorAttachment())
+ dst_framebuffer->GetColorAttachment()->FinishedRendering();
+}
+
+MathUtil::Rectangle<int>
+AbstractGfx::ConvertFramebufferRectangle(const MathUtil::Rectangle<int>& rect,
+ const AbstractFramebuffer* framebuffer) const
+{
+ return ConvertFramebufferRectangle(rect, framebuffer->GetWidth(), framebuffer->GetHeight());
+}
+
+MathUtil::Rectangle<int>
+AbstractGfx::ConvertFramebufferRectangle(const MathUtil::Rectangle<int>& rect, u32 fb_width,
+ u32 fb_height) const
+{
+ MathUtil::Rectangle<int> ret = rect;
+ if (g_ActiveConfig.backend_info.bUsesLowerLeftOrigin)
+ {
+ ret.top = fb_height - rect.bottom;
+ ret.bottom = fb_height - rect.top;
+ }
+ return ret;
+}
+
+std::unique_ptr<VideoCommon::AsyncShaderCompiler> AbstractGfx::CreateAsyncShaderCompiler()
+{
+ return std::make_unique<VideoCommon::AsyncShaderCompiler>();
+}
+
+bool AbstractGfx::UseGeometryShaderForUI() const
+{
+ // OpenGL doesn't render to a 2-layer backbuffer like D3D/Vulkan for quad-buffered stereo,
+ // instead drawing twice and the eye selected by glDrawBuffer() (see Presenter::RenderXFBToScreen)
+ return g_ActiveConfig.stereo_mode == StereoMode::QuadBuffer &&
+ g_ActiveConfig.backend_info.api_type != APIType::OpenGL;
+}