2018-03-24 11:44:53 +00:00
|
|
|
|
|
|
|
#include "libretro/LibretroGraphicsContext.h"
|
|
|
|
#include "libretro/LibretroGLContext.h"
|
2020-09-27 13:24:17 +00:00
|
|
|
#include "libretro/LibretroGLCoreContext.h"
|
2018-03-24 11:44:53 +00:00
|
|
|
#include "libretro/LibretroVulkanContext.h"
|
2018-03-25 22:07:02 +00:00
|
|
|
#ifdef _WIN32
|
|
|
|
#include "libretro/LibretroD3D11Context.h"
|
|
|
|
#endif
|
2018-03-24 11:44:53 +00:00
|
|
|
|
|
|
|
#include "Common/Log.h"
|
|
|
|
#include "Core/Config.h"
|
|
|
|
#include "Core/System.h"
|
|
|
|
#include "GPU/GPUInterface.h"
|
|
|
|
|
|
|
|
retro_video_refresh_t LibretroGraphicsContext::video_cb;
|
|
|
|
|
2020-07-12 21:51:57 +00:00
|
|
|
extern "C" {
|
|
|
|
retro_hw_get_proc_address_t libretro_get_proc_address;
|
|
|
|
};
|
|
|
|
|
2018-03-24 11:44:53 +00:00
|
|
|
void retro_set_video_refresh(retro_video_refresh_t cb) { LibretroGraphicsContext::video_cb = cb; }
|
|
|
|
static void context_reset() { ((LibretroHWRenderContext *)Libretro::ctx)->ContextReset(); }
|
|
|
|
static void context_destroy() { ((LibretroHWRenderContext *)Libretro::ctx)->ContextDestroy(); }
|
|
|
|
|
2018-03-26 16:21:11 +00:00
|
|
|
bool LibretroHWRenderContext::Init(bool cache_context) {
|
|
|
|
hw_render_.cache_context = cache_context;
|
2020-07-12 21:51:57 +00:00
|
|
|
if (!Libretro::environ_cb(RETRO_ENVIRONMENT_SET_HW_RENDER, &hw_render_))
|
2024-05-28 05:07:20 +00:00
|
|
|
return false;
|
|
|
|
libretro_get_proc_address = hw_render_.get_proc_address;
|
|
|
|
return true;
|
2018-03-26 16:21:11 +00:00
|
|
|
}
|
2018-03-24 11:44:53 +00:00
|
|
|
|
2018-03-26 16:37:34 +00:00
|
|
|
LibretroHWRenderContext::LibretroHWRenderContext(retro_hw_context_type context_type, unsigned version_major, unsigned version_minor) {
|
2018-03-24 11:44:53 +00:00
|
|
|
hw_render_.context_type = context_type;
|
|
|
|
hw_render_.version_major = version_major;
|
|
|
|
hw_render_.version_minor = version_minor;
|
|
|
|
hw_render_.context_reset = context_reset;
|
|
|
|
hw_render_.context_destroy = context_destroy;
|
|
|
|
hw_render_.depth = true;
|
|
|
|
}
|
|
|
|
|
2018-03-26 16:37:34 +00:00
|
|
|
void LibretroHWRenderContext::ContextReset() {
|
2018-03-24 11:44:53 +00:00
|
|
|
INFO_LOG(G3D, "Context reset");
|
|
|
|
|
2024-06-05 01:50:19 +00:00
|
|
|
if (gpu && Libretro::useEmuThread) {
|
|
|
|
Libretro::EmuThreadPause();
|
|
|
|
}
|
|
|
|
|
2024-05-28 05:07:20 +00:00
|
|
|
if (gpu) {
|
|
|
|
gpu->DeviceLost();
|
2018-03-26 16:37:34 +00:00
|
|
|
}
|
2018-03-24 11:44:53 +00:00
|
|
|
|
2018-03-26 16:37:34 +00:00
|
|
|
if (!draw_) {
|
2018-03-24 11:44:53 +00:00
|
|
|
CreateDrawContext();
|
2018-03-25 22:07:02 +00:00
|
|
|
bool success = draw_->CreatePresets();
|
2020-08-16 10:48:09 +00:00
|
|
|
_assert_(success);
|
2018-03-24 11:44:53 +00:00
|
|
|
}
|
|
|
|
|
2018-03-25 22:07:02 +00:00
|
|
|
GotBackbuffer();
|
|
|
|
|
2018-03-26 16:37:34 +00:00
|
|
|
if (gpu) {
|
2023-02-25 22:04:27 +00:00
|
|
|
gpu->DeviceRestore(draw_);
|
2018-03-26 16:37:34 +00:00
|
|
|
}
|
2024-06-05 01:50:19 +00:00
|
|
|
|
|
|
|
if (gpu && Libretro::useEmuThread) {
|
|
|
|
Libretro::EmuThreadStart();
|
|
|
|
}
|
2018-03-24 11:44:53 +00:00
|
|
|
}
|
|
|
|
|
2018-03-26 16:37:34 +00:00
|
|
|
void LibretroHWRenderContext::ContextDestroy() {
|
2018-03-24 11:44:53 +00:00
|
|
|
INFO_LOG(G3D, "Context destroy");
|
|
|
|
|
2018-03-26 16:37:34 +00:00
|
|
|
if (Libretro::useEmuThread) {
|
2018-03-24 11:44:53 +00:00
|
|
|
Libretro::EmuThreadStop();
|
2024-05-28 05:07:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (gpu) {
|
|
|
|
gpu->DeviceLost();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!hw_render_.cache_context && Libretro::useEmuThread && draw_ && Libretro::emuThreadState != Libretro::EmuThreadState::PAUSED) {
|
|
|
|
DestroyDrawContext();
|
2018-03-24 11:44:53 +00:00
|
|
|
}
|
|
|
|
|
2018-03-26 16:37:34 +00:00
|
|
|
if (!hw_render_.cache_context && !Libretro::useEmuThread) {
|
2018-03-26 16:21:11 +00:00
|
|
|
Shutdown();
|
2018-03-26 16:37:34 +00:00
|
|
|
}
|
2018-03-24 11:44:53 +00:00
|
|
|
}
|
|
|
|
|
2018-03-26 16:37:34 +00:00
|
|
|
void LibretroGraphicsContext::GotBackbuffer() { draw_->HandleEvent(Draw::Event::GOT_BACKBUFFER, PSP_CoreParameter().pixelWidth, PSP_CoreParameter().pixelHeight); }
|
2018-03-25 22:07:02 +00:00
|
|
|
|
2018-03-26 16:37:34 +00:00
|
|
|
void LibretroGraphicsContext::LostBackbuffer() { draw_->HandleEvent(Draw::Event::LOST_BACKBUFFER, -1, -1); }
|
2018-03-25 22:07:02 +00:00
|
|
|
|
2018-03-26 16:37:34 +00:00
|
|
|
LibretroGraphicsContext *LibretroGraphicsContext::CreateGraphicsContext() {
|
2018-03-24 11:44:53 +00:00
|
|
|
LibretroGraphicsContext *ctx;
|
|
|
|
|
2020-09-27 13:24:17 +00:00
|
|
|
retro_hw_context_type preferred;
|
|
|
|
if (!Libretro::environ_cb(RETRO_ENVIRONMENT_GET_PREFERRED_HW_RENDER, &preferred))
|
|
|
|
preferred = RETRO_HW_CONTEXT_DUMMY;
|
2018-03-24 11:44:53 +00:00
|
|
|
|
2024-06-02 21:08:32 +00:00
|
|
|
if (Libretro::backend != RETRO_HW_CONTEXT_DUMMY)
|
|
|
|
preferred = Libretro::backend;
|
2024-05-31 02:26:12 +00:00
|
|
|
|
2020-09-27 13:24:17 +00:00
|
|
|
#ifndef USING_GLES2
|
|
|
|
if (preferred == RETRO_HW_CONTEXT_DUMMY || preferred == RETRO_HW_CONTEXT_OPENGL_CORE) {
|
|
|
|
ctx = new LibretroGLCoreContext();
|
|
|
|
|
|
|
|
if (ctx->Init()) {
|
|
|
|
return ctx;
|
|
|
|
}
|
|
|
|
delete ctx;
|
2018-03-26 16:37:34 +00:00
|
|
|
}
|
2020-09-27 13:24:17 +00:00
|
|
|
#endif
|
2018-03-24 11:44:53 +00:00
|
|
|
|
2023-02-12 12:49:58 +00:00
|
|
|
if (preferred == RETRO_HW_CONTEXT_DUMMY || preferred == RETRO_HW_CONTEXT_OPENGL || preferred == RETRO_HW_CONTEXT_OPENGLES3) {
|
2020-09-27 13:24:17 +00:00
|
|
|
ctx = new LibretroGLContext();
|
2018-03-24 11:44:53 +00:00
|
|
|
|
2020-09-27 13:24:17 +00:00
|
|
|
if (ctx->Init()) {
|
|
|
|
return ctx;
|
|
|
|
}
|
|
|
|
delete ctx;
|
2018-03-26 16:37:34 +00:00
|
|
|
}
|
2018-03-24 11:44:53 +00:00
|
|
|
|
2022-04-02 23:34:13 +00:00
|
|
|
#ifndef HAVE_LIBNX
|
2020-09-27 13:24:17 +00:00
|
|
|
if (preferred == RETRO_HW_CONTEXT_DUMMY || preferred == RETRO_HW_CONTEXT_VULKAN) {
|
|
|
|
ctx = new LibretroVulkanContext();
|
2018-03-24 11:44:53 +00:00
|
|
|
|
2020-09-27 13:24:17 +00:00
|
|
|
if (ctx->Init()) {
|
|
|
|
return ctx;
|
|
|
|
}
|
|
|
|
delete ctx;
|
2018-03-26 16:37:34 +00:00
|
|
|
}
|
2022-04-02 23:34:13 +00:00
|
|
|
#endif
|
2018-03-24 11:44:53 +00:00
|
|
|
|
2020-09-27 13:24:17 +00:00
|
|
|
#ifdef _WIN32
|
|
|
|
if (preferred == RETRO_HW_CONTEXT_DUMMY || preferred == RETRO_HW_CONTEXT_DIRECT3D) {
|
|
|
|
ctx = new LibretroD3D11Context();
|
2018-03-24 11:44:53 +00:00
|
|
|
|
2020-09-27 13:24:17 +00:00
|
|
|
if (ctx->Init()) {
|
|
|
|
return ctx;
|
|
|
|
}
|
|
|
|
delete ctx;
|
|
|
|
|
|
|
|
ctx = new LibretroD3D9Context();
|
|
|
|
if (ctx->Init()) {
|
|
|
|
return ctx;
|
|
|
|
}
|
|
|
|
delete ctx;
|
2018-03-26 16:37:34 +00:00
|
|
|
}
|
2018-03-24 11:44:53 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
ctx = new LibretroSoftwareContext();
|
2024-05-28 05:07:20 +00:00
|
|
|
ctx->Init();
|
|
|
|
return ctx;
|
2018-03-24 11:44:53 +00:00
|
|
|
}
|
2024-05-31 02:26:12 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|