1 /* RetroArch - A frontend for libretro.
2 * Copyright (C) 2010-2014 - Hans-Kristian Arntzen
3 * Copyright (C) 2018 - M4xw
4 *
5 * RetroArch is free software: you can redistribute it and/or modify it under the terms
6 * of the GNU General Public License as published by the Free Software Found-
7 * ation, either version 3 of the License, or (at your option) any later version.
8 *
9 * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
10 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along with RetroArch.
14 * If not, see <http://www.gnu.org/licenses/>.
15 */
16
17 #include <stdlib.h>
18
19 #include <compat/strl.h>
20
21 #ifdef HAVE_CONFIG_H
22 #include "../../config.h"
23 #endif
24
25 #ifdef HAVE_EGL
26 #include "../common/egl_common.h"
27 #endif
28
29 #include "../common/orbis_common.h"
30 #include "../../frontend/frontend_driver.h"
31 #include "../../configuration.h"
32
33 /* TODO/FIXME - static globals */
34 static enum gfx_ctx_api ctx_orbis_api = GFX_CTX_OPENGL_API;
35
36 /* TODO/FIXME - global reference */
37 extern bool platform_orbis_has_focus;
38
orbis_ctx_destroy(void * data)39 void orbis_ctx_destroy(void *data)
40 {
41 orbis_ctx_data_t *ctx_orbis = (orbis_ctx_data_t *)data;
42
43 if (ctx_orbis)
44 {
45 #ifdef HAVE_EGL
46 egl_destroy(&ctx_orbis->egl);
47 #endif
48 ctx_orbis->resize = false;
49 free(ctx_orbis);
50 }
51 }
52
orbis_ctx_get_video_size(void * data,unsigned * width,unsigned * height)53 static void orbis_ctx_get_video_size(void *data,
54 unsigned *width, unsigned *height)
55 {
56 orbis_ctx_data_t
57 *ctx_orbis = (orbis_ctx_data_t *)data;
58
59 *width = ATTR_ORBISGL_WIDTH;
60 *height = ATTR_ORBISGL_HEIGHT;
61 }
62
orbis_ctx_init(void * video_driver)63 static void *orbis_ctx_init(void *video_driver)
64 {
65 #ifdef HAVE_EGL
66 int ret;
67 EGLint n;
68 EGLint major, minor;
69 static const EGLint attribs[] = {
70 EGL_RED_SIZE, 8,
71 EGL_GREEN_SIZE, 8,
72 EGL_BLUE_SIZE, 8,
73 EGL_ALPHA_SIZE, 8,
74 EGL_DEPTH_SIZE, 16,
75 EGL_STENCIL_SIZE, 0,
76 EGL_SAMPLE_BUFFERS, 0,
77 EGL_SAMPLES, 0,
78 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
79 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
80 EGL_NONE};
81 #endif
82
83 orbis_ctx_data_t *ctx_orbis = (orbis_ctx_data_t *)
84 calloc(1, sizeof(*ctx_orbis));
85
86 if (!ctx_orbis)
87 return NULL;
88
89 #ifdef HAVE_EGL
90
91 memset(&ctx_orbis->pgl_config, 0, sizeof(ctx_orbis->pgl_config));
92
93 {
94 ctx_orbis->pgl_config.size =
95 sizeof(ctx_orbis->pgl_config);
96 ctx_orbis->pgl_config.flags =
97 SCE_PGL_FLAGS_USE_COMPOSITE_EXT
98 | SCE_PGL_FLAGS_USE_FLEXIBLE_MEMORY
99 | 0x60;
100 ctx_orbis->pgl_config.processOrder = 1;
101 ctx_orbis->pgl_config.systemSharedMemorySize = 0x200000;
102 ctx_orbis->pgl_config.videoSharedMemorySize = 0x2400000;
103 ctx_orbis->pgl_config.maxMappedFlexibleMemory = 0xAA00000;
104 ctx_orbis->pgl_config.drawCommandBufferSize = 0xC0000;
105 ctx_orbis->pgl_config.lcueResourceBufferSize = 0x10000;
106 ctx_orbis->pgl_config.dbgPosCmd_0x40 = ATTR_ORBISGL_WIDTH;
107 ctx_orbis->pgl_config.dbgPosCmd_0x44 = ATTR_ORBISGL_HEIGHT;
108 ctx_orbis->pgl_config.dbgPosCmd_0x48 = 0;
109 ctx_orbis->pgl_config.dbgPosCmd_0x4C = 0;
110 ctx_orbis->pgl_config.unk_0x5C = 2;
111 }
112 ret = scePigletSetConfigurationVSH(&ctx_orbis->pgl_config);
113 if (!ret)
114 {
115 printf("[ORBISGL] scePigletSetConfigurationVSH failed 0x%08X.\n",ret);
116 goto error;
117 }
118
119 if (!egl_init_context(&ctx_orbis->egl, EGL_NONE, EGL_DEFAULT_DISPLAY,
120 &major, &minor, &n, attribs, NULL))
121 {
122 egl_report_error();
123 printf("[ORBIS]: EGL error: %d.\n", eglGetError());
124 goto error;
125 }
126 #endif
127
128 return ctx_orbis;
129
130 error:
131 orbis_ctx_destroy(video_driver);
132 return NULL;
133 }
134
orbis_ctx_check_window(void * data,bool * quit,bool * resize,unsigned * width,unsigned * height)135 static void orbis_ctx_check_window(void *data, bool *quit,
136 bool *resize, unsigned *width, unsigned *height)
137 {
138 unsigned new_width, new_height;
139
140 orbis_ctx_get_video_size(data, &new_width, &new_height);
141
142 if (new_width != *width || new_height != *height)
143 {
144 *width = new_width;
145 *height = new_height;
146 *resize = true;
147 }
148
149 *quit = (bool)false;
150 }
151
orbis_ctx_set_video_mode(void * data,unsigned width,unsigned height,bool fullscreen)152 static bool orbis_ctx_set_video_mode(void *data,
153 unsigned width, unsigned height,
154 bool fullscreen)
155 {
156 /* Create an EGL rendering context */
157 static const EGLint
158 contextAttributeList[] =
159 {
160 EGL_CONTEXT_CLIENT_VERSION, 2,
161 EGL_NONE};
162
163 orbis_ctx_data_t *ctx_orbis = (orbis_ctx_data_t *)data;
164
165 ctx_orbis->width = ATTR_ORBISGL_WIDTH;
166 ctx_orbis->height = ATTR_ORBISGL_HEIGHT;
167
168 ctx_orbis->native_window.width = ctx_orbis->width;
169 ctx_orbis->native_window.height = ctx_orbis->height;
170
171 ctx_orbis->refresh_rate = 60;
172
173 #ifdef HAVE_EGL
174 if (!egl_create_context(&ctx_orbis->egl, contextAttributeList))
175 goto error;
176 #endif
177
178 #ifdef HAVE_EGL
179 if (!egl_create_surface(&ctx_orbis->egl, &ctx_orbis->native_window))
180 goto error;
181 #endif
182
183 return true;
184
185 error:
186 #ifdef HAVE_EGL
187 egl_report_error();
188 #endif
189 orbis_ctx_destroy(data);
190
191 return false;
192 }
193
orbis_ctx_input_driver(void * data,const char * name,input_driver_t ** input,void ** input_data)194 static void orbis_ctx_input_driver(void *data,
195 const char *name,
196 input_driver_t **input, void **input_data)
197 {
198 *input = NULL;
199 *input_data = NULL;
200 }
201
orbis_ctx_get_api(void * data)202 static enum gfx_ctx_api orbis_ctx_get_api(void *data)
203 {
204 return ctx_orbis_api;
205 }
206
orbis_ctx_bind_api(void * data,enum gfx_ctx_api api,unsigned major,unsigned minor)207 static bool orbis_ctx_bind_api(void *data,
208 enum gfx_ctx_api api, unsigned major, unsigned minor)
209 {
210 ctx_orbis_api = api;
211
212 #ifdef HAVE_EGL
213 if (api == GFX_CTX_OPENGL_ES_API)
214 if (egl_bind_api(EGL_OPENGL_ES_API))
215 return true;
216 #endif
217
218 return false;
219 }
220
orbis_ctx_has_focus(void * data)221 static bool orbis_ctx_has_focus(void *data) { return true; }
222
orbis_ctx_suppress_screensaver(void * data,bool enable)223 static bool orbis_ctx_suppress_screensaver(void *data, bool enable) { return false; }
224
orbis_ctx_set_swap_interval(void * data,int swap_interval)225 static void orbis_ctx_set_swap_interval(void *data,
226 int swap_interval)
227 {
228 #ifdef HAVE_EGL
229 orbis_ctx_data_t *ctx_orbis = (orbis_ctx_data_t *)data;
230 egl_set_swap_interval(&ctx_orbis->egl, 0);
231 #endif
232 }
233
orbis_ctx_swap_buffers(void * data)234 static void orbis_ctx_swap_buffers(void *data)
235 {
236 #ifdef HAVE_EGL
237 orbis_ctx_data_t *ctx_orbis = (orbis_ctx_data_t *)data;
238 egl_swap_buffers(&ctx_orbis->egl);
239 #endif
240 }
241
orbis_ctx_bind_hw_render(void * data,bool enable)242 static void orbis_ctx_bind_hw_render(void *data, bool enable)
243 {
244 orbis_ctx_data_t *ctx_orbis = (orbis_ctx_data_t *)data;
245
246 #ifdef HAVE_EGL
247 egl_bind_hw_render(&ctx_orbis->egl, enable);
248 #endif
249 }
250
orbis_ctx_get_flags(void * data)251 static uint32_t orbis_ctx_get_flags(void *data)
252 {
253 uint32_t flags = 0;
254
255 if (string_is_equal(video_driver_get_ident(), "glcore"))
256 {
257 #if defined(HAVE_SLANG) && defined(HAVE_SPIRV_CROSS)
258 BIT32_SET(flags, GFX_CTX_FLAGS_SHADERS_SLANG);
259 #endif
260 }
261 else
262 {
263 BIT32_SET(flags, GFX_CTX_FLAGS_SHADERS_GLSL);
264 }
265
266 return flags;
267 }
268
orbis_ctx_set_flags(void * data,uint32_t flags)269 static void orbis_ctx_set_flags(void *data, uint32_t flags) { }
270
orbis_ctx_get_refresh_rate(void * data)271 static float orbis_ctx_get_refresh_rate(void *data)
272 {
273 orbis_ctx_data_t *ctx_orbis = (orbis_ctx_data_t *)data;
274
275 return ctx_orbis->refresh_rate;
276 }
277
278 const gfx_ctx_driver_t orbis_ctx = {
279 orbis_ctx_init,
280 orbis_ctx_destroy,
281 orbis_ctx_get_api,
282 orbis_ctx_bind_api,
283 orbis_ctx_set_swap_interval,
284 orbis_ctx_set_video_mode,
285 orbis_ctx_get_video_size,
286 orbis_ctx_get_refresh_rate,
287 NULL, /* get_video_output_size */
288 NULL, /* get_video_output_prev */
289 NULL, /* get_video_output_next */
290 NULL, /* get_metrics */
291 NULL,
292 NULL, /* update_title */
293 orbis_ctx_check_window,
294 NULL, /* set_resize */
295 orbis_ctx_has_focus,
296 orbis_ctx_suppress_screensaver,
297 false, /* has_windowed */
298 orbis_ctx_swap_buffers,
299 orbis_ctx_input_driver,
300 #ifdef HAVE_EGL
301 egl_get_proc_address,
302 #else
303 NULL,
304 #endif
305 NULL,
306 NULL,
307 NULL,
308 "egl_orbis",
309 orbis_ctx_get_flags,
310 orbis_ctx_set_flags,
311 orbis_ctx_bind_hw_render,
312 NULL,
313 NULL};
314