1 
2 #include "libretro/LibretroGraphicsContext.h"
3 #include "libretro/LibretroGLContext.h"
4 #include "libretro/LibretroGLCoreContext.h"
5 #include "libretro/libretro.h"
6 #include "libretro/LibretroVulkanContext.h"
7 #ifdef _WIN32
8 #include "libretro/LibretroD3D11Context.h"
9 #endif
10 
11 #include "Common/Log.h"
12 #include "Core/Config.h"
13 #include "Core/System.h"
14 #include "GPU/GPUInterface.h"
15 
16 retro_video_refresh_t LibretroGraphicsContext::video_cb;
17 
18 extern "C" {
19    retro_hw_get_proc_address_t libretro_get_proc_address;
20 };
21 
retro_set_video_refresh(retro_video_refresh_t cb)22 void retro_set_video_refresh(retro_video_refresh_t cb) { LibretroGraphicsContext::video_cb = cb; }
context_reset()23 static void context_reset() { ((LibretroHWRenderContext *)Libretro::ctx)->ContextReset(); }
context_destroy()24 static void context_destroy() { ((LibretroHWRenderContext *)Libretro::ctx)->ContextDestroy(); }
25 
Init(bool cache_context)26 bool LibretroHWRenderContext::Init(bool cache_context) {
27 	hw_render_.cache_context = cache_context;
28 	if (!Libretro::environ_cb(RETRO_ENVIRONMENT_SET_HW_RENDER, &hw_render_))
29       return false;
30    libretro_get_proc_address = hw_render_.get_proc_address;
31    return true;
32 }
33 
LibretroHWRenderContext(retro_hw_context_type context_type,unsigned version_major,unsigned version_minor)34 LibretroHWRenderContext::LibretroHWRenderContext(retro_hw_context_type context_type, unsigned version_major, unsigned version_minor) {
35 	hw_render_.context_type = context_type;
36 	hw_render_.version_major = version_major;
37 	hw_render_.version_minor = version_minor;
38 	hw_render_.context_reset = context_reset;
39 	hw_render_.context_destroy = context_destroy;
40 	hw_render_.depth = true;
41 }
42 
ContextReset()43 void LibretroHWRenderContext::ContextReset() {
44 	INFO_LOG(G3D, "Context reset");
45 
46 	// needed to restart the thread
47 	// TODO: find a way to move this to ContextDestroy.
48 	if (!hw_render_.cache_context && Libretro::useEmuThread && draw_ && Libretro::emuThreadState != Libretro::EmuThreadState::PAUSED) {
49 		DestroyDrawContext();
50 	}
51 
52 	if (!draw_) {
53 		CreateDrawContext();
54 		bool success = draw_->CreatePresets();
55 		_assert_(success);
56 	}
57 
58 	GotBackbuffer();
59 
60 	if (gpu) {
61 		gpu->DeviceRestore();
62 	}
63 }
64 
ContextDestroy()65 void LibretroHWRenderContext::ContextDestroy() {
66 	INFO_LOG(G3D, "Context destroy");
67 
68 	if (Libretro::useEmuThread) {
69 #if 0
70 		Libretro::EmuThreadPause();
71 #else
72 		Libretro::EmuThreadStop();
73 #endif
74 	}
75 
76 	LostBackbuffer();
77 
78 	gpu->DeviceLost();
79 
80 	if (!hw_render_.cache_context && !Libretro::useEmuThread) {
81 		Shutdown();
82 	}
83 }
84 
GotBackbuffer()85 void LibretroGraphicsContext::GotBackbuffer() { draw_->HandleEvent(Draw::Event::GOT_BACKBUFFER, PSP_CoreParameter().pixelWidth, PSP_CoreParameter().pixelHeight); }
86 
LostBackbuffer()87 void LibretroGraphicsContext::LostBackbuffer() { draw_->HandleEvent(Draw::Event::LOST_BACKBUFFER, -1, -1); }
88 
CreateGraphicsContext()89 LibretroGraphicsContext *LibretroGraphicsContext::CreateGraphicsContext() {
90 	LibretroGraphicsContext *ctx;
91 
92 	retro_hw_context_type preferred;
93 	if (!Libretro::environ_cb(RETRO_ENVIRONMENT_GET_PREFERRED_HW_RENDER, &preferred))
94 		preferred = RETRO_HW_CONTEXT_DUMMY;
95 
96 #ifndef USING_GLES2
97 	if (preferred == RETRO_HW_CONTEXT_DUMMY || preferred == RETRO_HW_CONTEXT_OPENGL_CORE) {
98 		ctx = new LibretroGLCoreContext();
99 
100 		if (ctx->Init()) {
101 			return ctx;
102 		}
103 		delete ctx;
104 	}
105 #endif
106 
107 	if (preferred == RETRO_HW_CONTEXT_DUMMY || preferred == RETRO_HW_CONTEXT_OPENGL) {
108 		ctx = new LibretroGLContext();
109 
110 		if (ctx->Init()) {
111 			return ctx;
112 		}
113 		delete ctx;
114 	}
115 
116 	if (preferred == RETRO_HW_CONTEXT_DUMMY || preferred == RETRO_HW_CONTEXT_VULKAN) {
117 		ctx = new LibretroVulkanContext();
118 
119 		if (ctx->Init()) {
120 			return ctx;
121 		}
122 		delete ctx;
123 	}
124 
125 #ifdef _WIN32
126 	if (preferred == RETRO_HW_CONTEXT_DUMMY || preferred == RETRO_HW_CONTEXT_DIRECT3D) {
127 		ctx = new LibretroD3D11Context();
128 
129 		if (ctx->Init()) {
130 			return ctx;
131 		}
132 		delete ctx;
133 
134 		ctx = new LibretroD3D9Context();
135 
136 		if (ctx->Init()) {
137 			return ctx;
138 		}
139 		delete ctx;
140 	}
141 #endif
142 
143 	ctx = new LibretroSoftwareContext();
144    ctx->Init();
145    return ctx;
146 }
147