CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
Path: blob/master/libretro/LibretroGraphicsContext.cpp
Views: 1401
1#include "libretro/LibretroGraphicsContext.h"2#include "libretro/LibretroGLContext.h"3#include "libretro/LibretroGLCoreContext.h"4#include "libretro/LibretroVulkanContext.h"5#ifdef _WIN326#include "libretro/LibretroD3D11Context.h"7#endif89#include "Common/Log.h"10#include "Core/Config.h"11#include "Core/System.h"12#include "GPU/GPUInterface.h"1314retro_video_refresh_t LibretroGraphicsContext::video_cb;1516extern "C" {17retro_hw_get_proc_address_t libretro_get_proc_address;18};1920void retro_set_video_refresh(retro_video_refresh_t cb) { LibretroGraphicsContext::video_cb = cb; }21static void context_reset() { ((LibretroHWRenderContext *)Libretro::ctx)->ContextReset(); }22static void context_destroy() { ((LibretroHWRenderContext *)Libretro::ctx)->ContextDestroy(); }2324bool LibretroHWRenderContext::Init(bool cache_context) {25hw_render_.cache_context = cache_context;26if (!Libretro::environ_cb(RETRO_ENVIRONMENT_SET_HW_RENDER, &hw_render_))27return false;28libretro_get_proc_address = hw_render_.get_proc_address;29return true;30}3132LibretroHWRenderContext::LibretroHWRenderContext(retro_hw_context_type context_type, unsigned version_major, unsigned version_minor) {33hw_render_.context_type = context_type;34hw_render_.version_major = version_major;35hw_render_.version_minor = version_minor;36hw_render_.context_reset = context_reset;37hw_render_.context_destroy = context_destroy;38hw_render_.depth = true;39}4041void LibretroHWRenderContext::ContextReset() {42INFO_LOG(Log::G3D, "Context reset");4344if (gpu && Libretro::useEmuThread) {45Libretro::EmuThreadPause();46}4748if (gpu) {49gpu->DeviceLost();50}5152if (!draw_) {53CreateDrawContext();54bool success = draw_->CreatePresets();55_assert_(success);56}5758GotBackbuffer();5960if (gpu) {61gpu->DeviceRestore(draw_);62}6364if (gpu && Libretro::useEmuThread) {65Libretro::EmuThreadStart();66}67}6869void LibretroHWRenderContext::ContextDestroy() {70INFO_LOG(Log::G3D, "Context destroy");7172if (Libretro::useEmuThread) {73Libretro::EmuThreadStop();74}7576if (gpu) {77gpu->DeviceLost();78}7980if (!hw_render_.cache_context && Libretro::useEmuThread && draw_ && Libretro::emuThreadState != Libretro::EmuThreadState::PAUSED) {81DestroyDrawContext();82}8384if (!hw_render_.cache_context && !Libretro::useEmuThread) {85Shutdown();86}87}8889void LibretroGraphicsContext::GotBackbuffer() { draw_->HandleEvent(Draw::Event::GOT_BACKBUFFER, PSP_CoreParameter().pixelWidth, PSP_CoreParameter().pixelHeight); }9091void LibretroGraphicsContext::LostBackbuffer() { draw_->HandleEvent(Draw::Event::LOST_BACKBUFFER, -1, -1); }9293LibretroGraphicsContext *LibretroGraphicsContext::CreateGraphicsContext() {94LibretroGraphicsContext *ctx;9596retro_hw_context_type preferred;97if (!Libretro::environ_cb(RETRO_ENVIRONMENT_GET_PREFERRED_HW_RENDER, &preferred))98preferred = RETRO_HW_CONTEXT_DUMMY;99100if (Libretro::backend != RETRO_HW_CONTEXT_DUMMY)101preferred = Libretro::backend;102103#ifndef USING_GLES2104if (preferred == RETRO_HW_CONTEXT_DUMMY || preferred == RETRO_HW_CONTEXT_OPENGL_CORE) {105ctx = new LibretroGLCoreContext();106107if (ctx->Init()) {108return ctx;109}110delete ctx;111}112#endif113114if (preferred == RETRO_HW_CONTEXT_DUMMY || preferred == RETRO_HW_CONTEXT_OPENGL || preferred == RETRO_HW_CONTEXT_OPENGLES3) {115ctx = new LibretroGLContext();116117if (ctx->Init()) {118return ctx;119}120delete ctx;121}122123#ifndef HAVE_LIBNX124if (preferred == RETRO_HW_CONTEXT_DUMMY || preferred == RETRO_HW_CONTEXT_VULKAN) {125ctx = new LibretroVulkanContext();126127if (ctx->Init()) {128return ctx;129}130delete ctx;131}132#endif133134#ifdef _WIN32135if (preferred == RETRO_HW_CONTEXT_DUMMY || preferred == RETRO_HW_CONTEXT_DIRECT3D) {136ctx = new LibretroD3D11Context();137138if (ctx->Init()) {139return ctx;140}141delete ctx;142143ctx = new LibretroD3D9Context();144if (ctx->Init()) {145return ctx;146}147delete ctx;148}149#endif150151ctx = new LibretroSoftwareContext();152ctx->Init();153return ctx;154}155156std::vector<u32> TranslateDebugBufferToCompare(const GPUDebugBuffer *buffer, u32 stride, u32 h) {157// If the output was small, act like everything outside was 0.158// This can happen depending on viewport parameters.159u32 safeW = std::min(stride, buffer->GetStride());160u32 safeH = std::min(h, buffer->GetHeight());161162std::vector<u32> data;163data.resize(stride * h, 0);164165const u32 *pixels32 = (const u32 *)buffer->GetData();166const u16 *pixels16 = (const u16 *)buffer->GetData();167int outStride = buffer->GetStride();168#if 0169if (!buffer->GetFlipped()) {170// Bitmaps are flipped, so we have to compare backwards in this case.171int toLastRow = outStride * (h > buffer->GetHeight() ? buffer->GetHeight() - 1 : h - 1);172pixels32 += toLastRow;173pixels16 += toLastRow;174outStride = -outStride;175}176#endif177// Skip the bottom of the image in the buffer was smaller. Remember, we're flipped.178u32 *dst = &data[0];179if (safeH < h) {180dst += (h - safeH) * stride;181}182183for (u32 y = 0; y < safeH; ++y) {184switch (buffer->GetFormat()) {185case GPU_DBG_FORMAT_8888:186ConvertBGRA8888ToRGBA8888(&dst[y * stride], pixels32, safeW);187break;188case GPU_DBG_FORMAT_8888_BGRA:189memcpy(&dst[y * stride], pixels32, safeW * sizeof(u32));190break;191192case GPU_DBG_FORMAT_565:193ConvertRGB565ToBGRA8888(&dst[y * stride], pixels16, safeW);194break;195case GPU_DBG_FORMAT_5551:196ConvertRGBA5551ToBGRA8888(&dst[y * stride], pixels16, safeW);197break;198case GPU_DBG_FORMAT_4444:199ConvertRGBA4444ToBGRA8888(&dst[y * stride], pixels16, safeW);200break;201202default:203data.resize(0);204return data;205}206207pixels32 += outStride;208pixels16 += outStride;209}210211return data;212}213214215