2015-05-23 22:55:12 -06:00
|
|
|
// Copyright 2010 Dolphin Emulator Project
|
2021-07-04 19:22:19 -06:00
|
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
2010-11-17 19:21:26 -07:00
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------------------------
|
|
|
|
// GC graphics pipeline
|
|
|
|
// ---------------------------------------------------------------------------------------------
|
2015-01-10 22:17:29 -07:00
|
|
|
// 3d commands are issued through the fifo. The GPU draws to the 2MB EFB.
|
2010-11-17 19:21:26 -07:00
|
|
|
// The efb can be copied back into ram in two forms: as textures or as XFB.
|
|
|
|
// The XFB is the region in RAM that the VI chip scans out to the television.
|
|
|
|
// So, after all rendering to EFB is done, the image is copied into one of two XFBs in RAM.
|
|
|
|
// Next frame, that one is scanned out and the other one gets the copy. = double buffering.
|
|
|
|
// ---------------------------------------------------------------------------------------------
|
|
|
|
|
2017-02-03 10:31:20 -07:00
|
|
|
#include "VideoCommon/RenderBase.h"
|
|
|
|
|
2017-12-25 16:38:44 -07:00
|
|
|
#include <algorithm>
|
2010-11-17 19:21:26 -07:00
|
|
|
#include <cmath>
|
2015-12-20 19:49:49 -07:00
|
|
|
#include <memory>
|
2017-02-03 10:31:20 -07:00
|
|
|
#include <tuple>
|
2010-11-17 19:21:26 -07:00
|
|
|
|
2019-11-22 15:10:41 -07:00
|
|
|
#include <fmt/format.h>
|
2018-10-09 07:57:52 -06:00
|
|
|
|
2016-11-18 05:57:08 -07:00
|
|
|
#include "Common/Logging/Log.h"
|
|
|
|
#include "Common/MsgHandler.h"
|
2014-02-17 03:18:15 -07:00
|
|
|
|
2014-10-12 21:53:10 -06:00
|
|
|
#include "Core/ConfigManager.h"
|
2022-11-27 05:50:50 -07:00
|
|
|
#include "Core/System.h"
|
2015-07-20 18:12:29 -06:00
|
|
|
|
2023-01-30 21:29:16 -07:00
|
|
|
#include "VideoCommon/FramebufferManager.h"
|
2019-02-14 18:59:50 -07:00
|
|
|
#include "VideoCommon/PixelEngine.h"
|
|
|
|
#include "VideoCommon/VideoBackendBase.h"
|
2023-01-30 05:19:19 -07:00
|
|
|
#include "VideoCommon/VideoCommon.h"
|
2023-01-30 21:29:16 -07:00
|
|
|
#include "VideoCommon/VideoConfig.h"
|
2014-02-17 03:18:15 -07:00
|
|
|
|
2015-12-20 19:49:49 -07:00
|
|
|
std::unique_ptr<Renderer> g_renderer;
|
2010-11-17 19:21:26 -07:00
|
|
|
|
2017-09-13 22:46:30 -06:00
|
|
|
Renderer::~Renderer() = default;
|
|
|
|
|
2019-02-14 18:59:50 -07:00
|
|
|
void Renderer::ReinterpretPixelData(EFBReinterpretType convtype)
|
|
|
|
{
|
|
|
|
g_framebuffer_manager->ReinterpretPixelData(convtype);
|
|
|
|
}
|
|
|
|
|
|
|
|
u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data)
|
|
|
|
{
|
|
|
|
if (type == EFBAccessType::PeekColor)
|
|
|
|
{
|
|
|
|
u32 color = g_framebuffer_manager->PeekEFBColor(x, y);
|
|
|
|
|
|
|
|
// a little-endian value is expected to be returned
|
|
|
|
color = ((color & 0xFF00FF00) | ((color >> 16) & 0xFF) | ((color << 16) & 0xFF0000));
|
|
|
|
|
2021-02-10 19:11:31 -07:00
|
|
|
if (bpmem.zcontrol.pixel_format == PixelFormat::RGBA6_Z24)
|
2019-02-14 18:59:50 -07:00
|
|
|
{
|
|
|
|
color = RGBA8ToRGBA6ToRGBA8(color);
|
|
|
|
}
|
2021-02-10 19:11:31 -07:00
|
|
|
else if (bpmem.zcontrol.pixel_format == PixelFormat::RGB565_Z16)
|
2019-02-14 18:59:50 -07:00
|
|
|
{
|
|
|
|
color = RGBA8ToRGB565ToRGBA8(color);
|
|
|
|
}
|
2021-02-10 19:11:31 -07:00
|
|
|
if (bpmem.zcontrol.pixel_format != PixelFormat::RGBA6_Z24)
|
2019-02-14 18:59:50 -07:00
|
|
|
{
|
|
|
|
color |= 0xFF000000;
|
|
|
|
}
|
|
|
|
|
2022-01-29 14:28:17 -07:00
|
|
|
// check what to do with the alpha channel (GX_PokeAlphaRead)
|
2022-12-10 08:35:07 -07:00
|
|
|
PixelEngine::AlphaReadMode alpha_read_mode =
|
|
|
|
Core::System::GetInstance().GetPixelEngine().GetAlphaReadMode();
|
2022-01-29 14:28:17 -07:00
|
|
|
|
|
|
|
if (alpha_read_mode == PixelEngine::AlphaReadMode::ReadNone)
|
2019-02-14 18:59:50 -07:00
|
|
|
{
|
2022-01-29 14:28:17 -07:00
|
|
|
return color;
|
2019-02-14 18:59:50 -07:00
|
|
|
}
|
2022-01-29 14:28:17 -07:00
|
|
|
else if (alpha_read_mode == PixelEngine::AlphaReadMode::ReadFF)
|
2019-02-14 18:59:50 -07:00
|
|
|
{
|
2022-01-29 14:28:17 -07:00
|
|
|
return color | 0xFF000000;
|
2019-02-14 18:59:50 -07:00
|
|
|
}
|
2022-01-29 14:28:17 -07:00
|
|
|
else
|
2019-02-14 18:59:50 -07:00
|
|
|
{
|
2022-01-29 14:28:17 -07:00
|
|
|
if (alpha_read_mode != PixelEngine::AlphaReadMode::Read00)
|
|
|
|
{
|
|
|
|
PanicAlertFmt("Invalid PE alpha read mode: {}", static_cast<u16>(alpha_read_mode));
|
|
|
|
}
|
|
|
|
return color & 0x00FFFFFF;
|
2019-02-14 18:59:50 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else // if (type == EFBAccessType::PeekZ)
|
|
|
|
{
|
|
|
|
// Depth buffer is inverted for improved precision near far plane
|
|
|
|
float depth = g_framebuffer_manager->PeekEFBDepth(x, y);
|
|
|
|
if (!g_ActiveConfig.backend_info.bSupportsReversedDepthRange)
|
|
|
|
depth = 1.0f - depth;
|
|
|
|
|
2021-04-26 03:55:38 -06:00
|
|
|
// Convert to 24bit depth
|
|
|
|
u32 z24depth = std::clamp<u32>(static_cast<u32>(depth * 16777216.0f), 0, 0xFFFFFF);
|
|
|
|
|
2021-02-10 19:11:31 -07:00
|
|
|
if (bpmem.zcontrol.pixel_format == PixelFormat::RGB565_Z16)
|
2019-02-14 18:59:50 -07:00
|
|
|
{
|
2021-04-26 03:55:38 -06:00
|
|
|
// When in RGB565_Z16 mode, EFB Z peeks return a 16bit value, which is presumably a
|
|
|
|
// resolved sample from the MSAA buffer.
|
|
|
|
// Dolphin doesn't currently emulate the 3 sample MSAA mode (and potentially never will)
|
|
|
|
// it just transparently upgrades the framebuffer to 24bit depth and color and whatever
|
|
|
|
// level of MSAA and higher Internal Resolution the user has configured.
|
|
|
|
|
|
|
|
// This is mostly transparent, unless the game does an EFB read.
|
|
|
|
// But we can simply convert the 24bit depth on the fly to the 16bit depth the game expects.
|
|
|
|
|
|
|
|
return CompressZ16(z24depth, bpmem.zcontrol.zformat);
|
2019-02-14 18:59:50 -07:00
|
|
|
}
|
|
|
|
|
2021-04-26 03:55:38 -06:00
|
|
|
return z24depth;
|
2019-02-14 18:59:50 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Renderer::PokeEFB(EFBAccessType type, const EfbPokeData* points, size_t num_points)
|
|
|
|
{
|
|
|
|
if (type == EFBAccessType::PokeColor)
|
|
|
|
{
|
|
|
|
for (size_t i = 0; i < num_points; i++)
|
|
|
|
{
|
|
|
|
// Convert to expected format (BGRA->RGBA)
|
|
|
|
// TODO: Check alpha, depending on mode?
|
|
|
|
const EfbPokeData& point = points[i];
|
|
|
|
u32 color = ((point.data & 0xFF00FF00) | ((point.data >> 16) & 0xFF) |
|
|
|
|
((point.data << 16) & 0xFF0000));
|
|
|
|
g_framebuffer_manager->PokeEFBColor(point.x, point.y, color);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else // if (type == EFBAccessType::PokeZ)
|
|
|
|
{
|
|
|
|
for (size_t i = 0; i < num_points; i++)
|
|
|
|
{
|
|
|
|
// Convert to floating-point depth.
|
|
|
|
const EfbPokeData& point = points[i];
|
|
|
|
float depth = float(point.data & 0xFFFFFF) / 16777216.0f;
|
|
|
|
if (!g_ActiveConfig.backend_info.bSupportsReversedDepthRange)
|
|
|
|
depth = 1.0f - depth;
|
|
|
|
|
|
|
|
g_framebuffer_manager->PokeEFBDepth(point.x, point.y, depth);
|
|
|
|
}
|
|
|
|
}
|
2018-01-25 22:09:07 -07:00
|
|
|
}
|