1 /* RetroArch - A frontend for libretro.
2 * Copyright (C) 2010-2014 - Hans-Kristian Arntzen
3 * Copyright (C) 2011-2017 - Daniel De Matteis
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 <stdint.h>
18
19 #ifdef HAVE_CONFIG_H
20 #include "config.h"
21 #endif
22
23 #include <sys/spu_initialize.h>
24
25 #include <compat/strl.h>
26
27 #include "../../configuration.h"
28 #include "../../retroarch.h"
29 #include "../../verbosity.h"
30 #include <defines/ps3_defines.h>
31 #include "../../frontend/frontend_driver.h"
32 #include "../common/gl_common.h"
33
34 typedef struct gfx_ctx_ps3_data
35 {
36 #if defined(HAVE_PSGL)
37 PSGLdevice* gl_device;
38 PSGLcontext* gl_context;
39 #else
40 void *empty;
41 #endif
42 } gfx_ctx_ps3_data_t;
43
44 /* TODO/FIXME - static global */
45 static enum gfx_ctx_api ps3_api = GFX_CTX_NONE;
46
gfx_ctx_ps3_get_resolution(unsigned idx,unsigned * width,unsigned * height)47 static void gfx_ctx_ps3_get_resolution(unsigned idx,
48 unsigned *width, unsigned *height)
49 {
50 CellVideoOutResolution resolution;
51 cellVideoOutGetResolution(idx, &resolution);
52
53 *width = resolution.width;
54 *height = resolution.height;
55 }
56
gfx_ctx_ps3_get_aspect_ratio(void * data)57 static float gfx_ctx_ps3_get_aspect_ratio(void *data)
58 {
59 CellVideoOutState videoState;
60
61 cellVideoOutGetState(CELL_VIDEO_OUT_PRIMARY, 0, &videoState);
62
63 switch (videoState.displayMode.aspect)
64 {
65 case CELL_VIDEO_OUT_ASPECT_4_3:
66 return 4.0f/3.0f;
67 case CELL_VIDEO_OUT_ASPECT_16_9:
68 break;
69 }
70
71 return 16.0f/9.0f;
72 }
73
gfx_ctx_ps3_get_available_resolutions(void)74 static void gfx_ctx_ps3_get_available_resolutions(void)
75 {
76 unsigned i;
77 uint32_t videomode[] = {
78 CELL_VIDEO_OUT_RESOLUTION_480,
79 CELL_VIDEO_OUT_RESOLUTION_576,
80 CELL_VIDEO_OUT_RESOLUTION_960x1080,
81 CELL_VIDEO_OUT_RESOLUTION_720,
82 CELL_VIDEO_OUT_RESOLUTION_1280x1080,
83 CELL_VIDEO_OUT_RESOLUTION_1440x1080,
84 CELL_VIDEO_OUT_RESOLUTION_1600x1080,
85 CELL_VIDEO_OUT_RESOLUTION_1080
86 };
87 uint32_t resolution_count = 0;
88 bool defaultresolution = true;
89 uint16_t num_videomodes = sizeof(videomode) / sizeof(uint32_t);
90 global_t *global = global_get_ptr();
91
92 if (global->console.screen.resolutions.check)
93 return;
94
95 for (i = 0; i < num_videomodes; i++)
96 {
97 if (cellVideoOutGetResolutionAvailability(
98 CELL_VIDEO_OUT_PRIMARY, videomode[i],
99 CELL_VIDEO_OUT_ASPECT_AUTO, 0))
100 resolution_count++;
101 }
102
103 global->console.screen.resolutions.count = 0;
104 global->console.screen.resolutions.list =
105 malloc(resolution_count * sizeof(uint32_t));
106
107 for (i = 0; i < num_videomodes; i++)
108 {
109 if (cellVideoOutGetResolutionAvailability(
110 CELL_VIDEO_OUT_PRIMARY,
111 videomode[i],
112 CELL_VIDEO_OUT_ASPECT_AUTO, 0))
113 {
114 global->console.screen.resolutions.list[
115 global->console.screen.resolutions.count++] = videomode[i];
116 global->console.screen.resolutions.initial.id = videomode[i];
117
118 if (global->console.screen.resolutions.current.id == videomode[i])
119 {
120 defaultresolution = false;
121 global->console.screen.resolutions.current.idx =
122 global->console.screen.resolutions.count-1;
123 }
124 }
125 }
126
127 /* In case we didn't specify a resolution -
128 * make the last resolution
129 that was added to the list (the highest resolution)
130 the default resolution */
131 if (global->console.screen.resolutions.current.id > num_videomodes || defaultresolution)
132 {
133 global->console.screen.resolutions.current.idx = resolution_count - 1;
134 global->console.screen.resolutions.current.id = global->console.screen.resolutions.list[global->console.screen.resolutions.current.idx];
135 }
136
137 global->console.screen.resolutions.check = true;
138 }
139
gfx_ctx_ps3_set_swap_interval(void * data,int interval)140 static void gfx_ctx_ps3_set_swap_interval(void *data, int interval)
141 {
142 #if defined(HAVE_PSGL)
143 if (interval == 1)
144 glEnable(GL_VSYNC_SCE);
145 else
146 glDisable(GL_VSYNC_SCE);
147 #endif
148 }
149
gfx_ctx_ps3_check_window(void * data,bool * quit,bool * resize,unsigned * width,unsigned * height)150 static void gfx_ctx_ps3_check_window(void *data, bool *quit,
151 bool *resize, unsigned *width, unsigned *height)
152 {
153 gl_t *gl = data;
154
155 *quit = false;
156 *resize = false;
157
158 if (gl->should_resize)
159 *resize = true;
160 }
161
gfx_ctx_ps3_has_focus(void * data)162 static bool gfx_ctx_ps3_has_focus(void *data) { return true; }
gfx_ctx_ps3_suppress_screensaver(void * data,bool enable)163 static bool gfx_ctx_ps3_suppress_screensaver(void *data, bool enable) { return false; }
164
gfx_ctx_ps3_swap_buffers(void * data)165 static void gfx_ctx_ps3_swap_buffers(void *data)
166 {
167 #ifdef HAVE_PSGL
168 psglSwap();
169 #endif
170 #ifdef HAVE_SYSUTILS
171 cellSysutilCheckCallback();
172 #endif
173 }
174
gfx_ctx_ps3_get_video_size(void * data,unsigned * width,unsigned * height)175 static void gfx_ctx_ps3_get_video_size(void *data,
176 unsigned *width, unsigned *height)
177 {
178 gfx_ctx_ps3_data_t *ps3 = (gfx_ctx_ps3_data_t*)data;
179
180 #if defined(HAVE_PSGL)
181 if (ps3)
182 psglGetDeviceDimensions(ps3->gl_device, width, height);
183 #endif
184 }
185
gfx_ctx_ps3_init(void * video_driver)186 static void *gfx_ctx_ps3_init(void *video_driver)
187 {
188 #ifdef HAVE_PSGL
189 PSGLdeviceParameters params;
190 PSGLinitOptions options;
191 #endif
192 global_t *global = global_get_ptr();
193 gfx_ctx_ps3_data_t *ps3 = (gfx_ctx_ps3_data_t*)
194 calloc(1, sizeof(gfx_ctx_ps3_data_t));
195
196 if (!ps3)
197 return NULL;
198
199 #if defined(HAVE_PSGL)
200 options.enable = PSGL_INIT_MAX_SPUS | PSGL_INIT_INITIALIZE_SPUS;
201 options.maxSPUs = 1;
202 options.initializeSPUs = GL_FALSE;
203
204 /* Initialize 6 SPUs but reserve 1 SPU as a raw SPU for PSGL. */
205 sys_spu_initialize(6, 1);
206 psglInit(&options);
207
208 params.enable =
209 PSGL_DEVICE_PARAMETERS_COLOR_FORMAT |
210 PSGL_DEVICE_PARAMETERS_DEPTH_FORMAT |
211 PSGL_DEVICE_PARAMETERS_MULTISAMPLING_MODE;
212 params.colorFormat = GL_ARGB_SCE;
213 params.depthFormat = GL_NONE;
214 params.multisamplingMode = GL_MULTISAMPLING_NONE_SCE;
215
216 if (global->console.screen.resolutions.current.id)
217 {
218 params.enable |= PSGL_DEVICE_PARAMETERS_WIDTH_HEIGHT;
219
220 gfx_ctx_ps3_get_resolution(
221 global->console.screen.resolutions.current.id,
222 ¶ms.width, ¶ms.height);
223
224 global->console.screen.pal_enable = false;
225
226 if (params.width == 720 && params.height == 576)
227 {
228 RARCH_LOG("[PSGL Context]: 720x576 resolution detected, setting MODE_VIDEO_PAL_ENABLE.\n");
229 global->console.screen.pal_enable = true;
230 }
231 }
232
233 if (global->console.screen.pal60_enable)
234 {
235 RARCH_LOG("[PSGL Context]: Setting temporal PAL60 mode.\n");
236 params.enable |= PSGL_DEVICE_PARAMETERS_RESC_PAL_TEMPORAL_MODE;
237 params.enable |= PSGL_DEVICE_PARAMETERS_RESC_RATIO_MODE;
238 params.rescPalTemporalMode = RESC_PAL_TEMPORAL_MODE_60_INTERPOLATE;
239 params.rescRatioMode = RESC_RATIO_MODE_FULLSCREEN;
240 }
241
242 ps3->gl_device = psglCreateDeviceExtended(¶ms);
243 ps3->gl_context = psglCreateContext();
244
245 psglMakeCurrent(ps3->gl_context, ps3->gl_device);
246 psglResetCurrentContext();
247 #endif
248
249 global->console.screen.pal_enable =
250 cellVideoOutGetResolutionAvailability(
251 CELL_VIDEO_OUT_PRIMARY, CELL_VIDEO_OUT_RESOLUTION_576,
252 CELL_VIDEO_OUT_ASPECT_AUTO, 0);
253
254 gfx_ctx_ps3_get_available_resolutions();
255
256 return ps3;
257 }
258
gfx_ctx_ps3_set_video_mode(void * data,unsigned width,unsigned height,bool fullscreen)259 static bool gfx_ctx_ps3_set_video_mode(void *data,
260 unsigned width, unsigned height,
261 bool fullscreen) { return true; }
262
gfx_ctx_ps3_destroy_resources(gfx_ctx_ps3_data_t * ps3)263 static void gfx_ctx_ps3_destroy_resources(gfx_ctx_ps3_data_t *ps3)
264 {
265 if (!ps3)
266 return;
267
268 #if defined(HAVE_PSGL)
269 psglDestroyContext(ps3->gl_context);
270 psglDestroyDevice(ps3->gl_device);
271
272 psglExit();
273 #endif
274 }
275
gfx_ctx_ps3_destroy(void * data)276 static void gfx_ctx_ps3_destroy(void *data)
277 {
278 gfx_ctx_ps3_data_t *ps3 = (gfx_ctx_ps3_data_t*)data;
279
280 if (!ps3)
281 return;
282
283 gfx_ctx_ps3_destroy_resources(ps3);
284 free(data);
285 }
286
gfx_ctx_ps3_input_driver(void * data,const char * joypad_name,input_driver_t ** input,void ** input_data)287 static void gfx_ctx_ps3_input_driver(void *data,
288 const char *joypad_name,
289 input_driver_t **input, void **input_data)
290 {
291 void *ps3input = input_driver_init_wrap(&input_ps3, joypad_name);
292
293 *input = ps3input ? &input_ps3 : NULL;
294 *input_data = ps3input;
295 }
296
gfx_ctx_ps3_get_api(void * data)297 static enum gfx_ctx_api gfx_ctx_ps3_get_api(void *data) { return ps3_api; }
298
gfx_ctx_ps3_bind_api(void * data,enum gfx_ctx_api api,unsigned major,unsigned minor)299 static bool gfx_ctx_ps3_bind_api(void *data,
300 enum gfx_ctx_api api, unsigned major, unsigned minor)
301 {
302 ps3_api = api;
303
304 if (
305 api == GFX_CTX_OPENGL_API ||
306 api == GFX_CTX_OPENGL_ES_API
307 )
308 return true;
309
310 return false;
311 }
312
gfx_ctx_ps3_get_video_output_size(void * data,unsigned * width,unsigned * height)313 static void gfx_ctx_ps3_get_video_output_size(void *data,
314 unsigned *width, unsigned *height)
315 {
316 global_t *global = global_get_ptr();
317
318 if (!global)
319 return;
320
321 gfx_ctx_ps3_get_resolution(global->console.screen.resolutions.current.id,
322 width, height);
323
324 if (*width == 720 && *height == 576)
325 {
326 if (global->console.screen.pal_enable)
327 global->console.screen.pal60_enable = true;
328 }
329 else
330 {
331 global->console.screen.pal_enable = false;
332 global->console.screen.pal60_enable = false;
333 }
334 }
335
gfx_ctx_ps3_get_video_output_prev(void * data)336 static void gfx_ctx_ps3_get_video_output_prev(void *data)
337 {
338 global_t *global = global_get_ptr();
339
340 if (!global)
341 return;
342
343 if (global->console.screen.resolutions.current.idx)
344 {
345 global->console.screen.resolutions.current.idx--;
346 global->console.screen.resolutions.current.id =
347 global->console.screen.resolutions.list
348 [global->console.screen.resolutions.current.idx];
349 }
350 }
351
gfx_ctx_ps3_get_video_output_next(void * data)352 static void gfx_ctx_ps3_get_video_output_next(void *data)
353 {
354 global_t *global = global_get_ptr();
355
356 if (!global)
357 return;
358
359 if (global->console.screen.resolutions.current.idx + 1 <
360 global->console.screen.resolutions.count)
361 {
362 global->console.screen.resolutions.current.idx++;
363 global->console.screen.resolutions.current.id =
364 global->console.screen.resolutions.list
365 [global->console.screen.resolutions.current.idx];
366 }
367 }
368
gfx_ctx_ps3_get_flags(void * data)369 static uint32_t gfx_ctx_ps3_get_flags(void *data)
370 {
371 uint32_t flags = 0;
372
373 #ifdef HAVE_CG
374 BIT32_SET(flags, GFX_CTX_FLAGS_SHADERS_CG);
375 #endif
376
377 return flags;
378 }
379
gfx_ctx_ps3_set_flags(void * data,uint32_t flags)380 static void gfx_ctx_ps3_set_flags(void *data, uint32_t flags) { }
381
382 const gfx_ctx_driver_t gfx_ctx_ps3 = {
383 gfx_ctx_ps3_init,
384 gfx_ctx_ps3_destroy,
385 gfx_ctx_ps3_get_api,
386 gfx_ctx_ps3_bind_api,
387 gfx_ctx_ps3_set_swap_interval,
388 gfx_ctx_ps3_set_video_mode,
389 gfx_ctx_ps3_get_video_size,
390 NULL, /* get_refresh_rate */
391 gfx_ctx_ps3_get_video_output_size,
392 gfx_ctx_ps3_get_video_output_prev,
393 gfx_ctx_ps3_get_video_output_next,
394 NULL, /* get_metrics */
395 NULL,
396 NULL, /* update_title */
397 gfx_ctx_ps3_check_window,
398 NULL, /* set_resize */
399 gfx_ctx_ps3_has_focus,
400 gfx_ctx_ps3_suppress_screensaver,
401 false, /* has_windowed */
402 gfx_ctx_ps3_swap_buffers,
403 gfx_ctx_ps3_input_driver,
404 NULL,
405 NULL,
406 NULL,
407 NULL,
408 "ps3",
409 gfx_ctx_ps3_get_flags,
410 gfx_ctx_ps3_set_flags,
411 NULL,
412 NULL
413 };
414