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