libretro: Add video renderer core option

This commit is contained in:
sonninnos 2024-05-31 05:26:12 +03:00
parent dce27e4da4
commit c8b7ae817d
4 changed files with 119 additions and 4 deletions

View File

@ -90,6 +90,9 @@ LibretroGraphicsContext *LibretroGraphicsContext::CreateGraphicsContext() {
if (!Libretro::environ_cb(RETRO_ENVIRONMENT_GET_PREFERRED_HW_RENDER, &preferred))
preferred = RETRO_HW_CONTEXT_DUMMY;
if (Libretro::renderer != RETRO_HW_CONTEXT_DUMMY)
preferred = Libretro::renderer;
#ifndef USING_GLES2
if (preferred == RETRO_HW_CONTEXT_DUMMY || preferred == RETRO_HW_CONTEXT_OPENGL_CORE) {
ctx = new LibretroGLCoreContext();
@ -131,7 +134,6 @@ LibretroGraphicsContext *LibretroGraphicsContext::CreateGraphicsContext() {
delete ctx;
ctx = new LibretroD3D9Context();
if (ctx->Init()) {
return ctx;
}
@ -143,3 +145,61 @@ LibretroGraphicsContext *LibretroGraphicsContext::CreateGraphicsContext() {
ctx->Init();
return ctx;
}
std::vector<u32> TranslateDebugBufferToCompare(const GPUDebugBuffer *buffer, u32 stride, u32 h) {
// If the output was small, act like everything outside was 0.
// This can happen depending on viewport parameters.
u32 safeW = std::min(stride, buffer->GetStride());
u32 safeH = std::min(h, buffer->GetHeight());
std::vector<u32> data;
data.resize(stride * h, 0);
const u32 *pixels32 = (const u32 *)buffer->GetData();
const u16 *pixels16 = (const u16 *)buffer->GetData();
int outStride = buffer->GetStride();
#if 0
if (!buffer->GetFlipped()) {
// Bitmaps are flipped, so we have to compare backwards in this case.
int toLastRow = outStride * (h > buffer->GetHeight() ? buffer->GetHeight() - 1 : h - 1);
pixels32 += toLastRow;
pixels16 += toLastRow;
outStride = -outStride;
}
#endif
// Skip the bottom of the image in the buffer was smaller. Remember, we're flipped.
u32 *dst = &data[0];
if (safeH < h) {
dst += (h - safeH) * stride;
}
for (u32 y = 0; y < safeH; ++y) {
switch (buffer->GetFormat()) {
case GPU_DBG_FORMAT_8888:
ConvertBGRA8888ToRGBA8888(&dst[y * stride], pixels32, safeW);
break;
case GPU_DBG_FORMAT_8888_BGRA:
memcpy(&dst[y * stride], pixels32, safeW * sizeof(u32));
break;
case GPU_DBG_FORMAT_565:
ConvertRGB565ToBGRA8888(&dst[y * stride], pixels16, safeW);
break;
case GPU_DBG_FORMAT_5551:
ConvertRGBA5551ToBGRA8888(&dst[y * stride], pixels16, safeW);
break;
case GPU_DBG_FORMAT_4444:
ConvertRGBA4444ToBGRA8888(&dst[y * stride], pixels16, safeW);
break;
default:
data.resize(0);
return data;
}
pixels32 += outStride;
pixels16 += outStride;
}
return data;
}

View File

@ -7,6 +7,9 @@
#include "Core/System.h"
#include "GPU/GPUState.h"
#include "GPU/Software/SoftGpu.h"
#include "headless/Compare.h"
#include "Common/Data/Convert/ColorConv.h"
class LibretroGraphicsContext : public GraphicsContext {
public:
@ -80,7 +83,14 @@ class LibretroSoftwareContext : public LibretroGraphicsContext {
public:
LibretroSoftwareContext() {}
bool Init() override { return true; }
void SwapBuffers() override { video_cb(NULL, PSP_CoreParameter().pixelWidth, PSP_CoreParameter().pixelHeight, 0); }
void SwapBuffers() override {
GPUDebugBuffer buf;
u32 w = PSP_CoreParameter().pixelWidth;
u32 h = PSP_CoreParameter().pixelHeight;
gpuDebug->GetCurrentFramebuffer(buf, GPU_DBG_FRAMEBUF_DISPLAY);
const std::vector<u32> pixels = TranslateDebugBufferToCompare(&buf, w, h);
video_cb(pixels.data(), w, h, w << 2);
}
GPUCore GetGPUCore() override { return GPUCORE_SOFTWARE; }
const char *Ident() override { return "Software"; }
};
@ -88,6 +98,7 @@ public:
namespace Libretro {
extern LibretroGraphicsContext *ctx;
extern retro_environment_t environ_cb;
extern retro_hw_context_type renderer;
enum class EmuThreadState {
DISABLED,

View File

@ -100,6 +100,7 @@ namespace Libretro
{
LibretroGraphicsContext *ctx;
retro_environment_t environ_cb;
retro_hw_context_type renderer = RETRO_HW_CONTEXT_DUMMY;
static retro_audio_sample_batch_t audio_batch_cb;
static retro_input_poll_t input_poll_cb;
static retro_input_state_t input_state_cb;
@ -1329,6 +1330,26 @@ namespace Libretro
} // namespace Libretro
static void retro_check_renderer(void)
{
struct retro_variable var = {0};
var.key = "ppsspp_renderer";
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
{
if (!strcmp(var.value, "hardware"))
renderer = RETRO_HW_CONTEXT_DUMMY;
else if (!strcmp(var.value, "hardware_gl"))
renderer = RETRO_HW_CONTEXT_OPENGL;
else if (!strcmp(var.value, "hardware_vk"))
renderer = RETRO_HW_CONTEXT_VULKAN;
else if (!strcmp(var.value, "hardware_d3d"))
renderer = RETRO_HW_CONTEXT_DIRECT3D;
else if (!strcmp(var.value, "software"))
renderer = RETRO_HW_CONTEXT_NONE;
}
}
bool retro_load_game(const struct retro_game_info *game)
{
retro_pixel_format fmt = retro_pixel_format::RETRO_PIXEL_FORMAT_XRGB8888;
@ -1338,6 +1359,8 @@ bool retro_load_game(const struct retro_game_info *game)
return false;
}
retro_check_renderer();
coreState = CORE_POWERUP;
ctx = LibretroGraphicsContext::CreateGraphicsContext();
INFO_LOG(SYSTEM, "Using %s backend", ctx->Ident());

View File

@ -287,11 +287,32 @@ struct retro_core_option_v2_definition option_defs_us[] = {
BOOL_OPTIONS,
"enabled"
},
{
"ppsspp_renderer",
"Renderer",
NULL,
"'Hardware (Auto)' selects the renderer depending upon the current libretro frontend video driver. Restart required.",
NULL,
"video",
{
{ "hardware", "Hardware (Auto)" },
{ "hardware_gl", "Hardware (OpenGL)" },
#ifndef HAVE_LIBNX
{ "hardware_vk", "Hardware (Vulkan)" },
#endif
#ifdef _WIN32
{ "hardware_d3d", "Hardware (D3D11)" },
#endif
{ "software", "Software" },
{ NULL, NULL },
},
"hardware"
},
{
"ppsspp_internal_resolution",
"Internal Resolution (Restart)",
NULL,
"Internal Resolution",
NULL,
"Restart required.",
NULL,
"video",
{