1 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
2 | * Mupen64plus-core - api/vidext.c * |
3 | * Mupen64Plus homepage: https://mupen64plus.org/ * |
4 | * Copyright (C) 2009 Richard Goedeken * |
5 | * * |
6 | * This program is free software; you can redistribute it and/or modify * |
7 | * it under the terms of the GNU General Public License as published by * |
8 | * the Free Software Foundation; either version 2 of the License, or * |
9 | * (at your option) any later version. * |
10 | * * |
11 | * This program is distributed in the hope that it will be useful, * |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * |
14 | * GNU General Public License for more details. * |
15 | * * |
16 | * You should have received a copy of the GNU General Public License * |
17 | * along with this program; if not, write to the * |
18 | * Free Software Foundation, Inc., * |
19 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * |
20 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ |
21 | |
22 | /* This file contains the Core video extension functions which will be exported |
23 | * outside of the core library. |
24 | */ |
25 | |
26 | #include <SDL.h> |
27 | #include <stdlib.h> |
28 | #include <string.h> |
29 | |
30 | #define M64P_CORE_PROTOTYPES 1 |
31 | #include "osal/preproc.h" |
32 | #include "../osd/osd.h" |
33 | #include "callbacks.h" |
34 | #include "m64p_types.h" |
35 | #include "m64p_vidext.h" |
36 | #include "vidext.h" |
37 | |
38 | #if SDL_VERSION_ATLEAST(2,0,0) |
39 | #ifndef USE_GLES |
40 | static int l_ForceCompatibilityContext = 1; |
41 | #endif |
42 | #include "vidext_sdl2_compat.h" |
43 | #endif |
44 | |
45 | /* local variables */ |
46 | static m64p_video_extension_functions l_ExternalVideoFuncTable = {12, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}; |
47 | static int l_VideoExtensionActive = 0; |
48 | static int l_VideoOutputActive = 0; |
49 | static int l_Fullscreen = 0; |
50 | static int l_SwapControl = 0; |
51 | static SDL_Surface *l_pScreen = NULL; |
52 | |
53 | /* global function for use by frontend.c */ |
54 | m64p_error OverrideVideoFunctions(m64p_video_extension_functions *VideoFunctionStruct) |
55 | { |
56 | /* check input data */ |
57 | if (VideoFunctionStruct == NULL) |
58 | return M64ERR_INPUT_ASSERT; |
59 | if (VideoFunctionStruct->Functions < 12) |
60 | return M64ERR_INPUT_INVALID; |
61 | |
62 | /* disable video extension if any of the function pointers are NULL */ |
63 | if (VideoFunctionStruct->VidExtFuncInit == NULL || |
64 | VideoFunctionStruct->VidExtFuncQuit == NULL || |
65 | VideoFunctionStruct->VidExtFuncListModes == NULL || |
66 | VideoFunctionStruct->VidExtFuncSetMode == NULL || |
67 | VideoFunctionStruct->VidExtFuncGLGetProc == NULL || |
68 | VideoFunctionStruct->VidExtFuncGLSetAttr == NULL || |
69 | VideoFunctionStruct->VidExtFuncGLGetAttr == NULL || |
70 | VideoFunctionStruct->VidExtFuncGLSwapBuf == NULL || |
71 | VideoFunctionStruct->VidExtFuncSetCaption == NULL || |
72 | VideoFunctionStruct->VidExtFuncToggleFS == NULL || |
73 | VideoFunctionStruct->VidExtFuncResizeWindow == NULL || |
74 | VideoFunctionStruct->VidExtFuncGLGetDefaultFramebuffer == NULL) |
75 | { |
76 | l_ExternalVideoFuncTable.Functions = 12; |
77 | memset(&l_ExternalVideoFuncTable.VidExtFuncInit, 0, 12 * sizeof(void *)); |
78 | l_VideoExtensionActive = 0; |
79 | return M64ERR_SUCCESS; |
80 | } |
81 | |
82 | /* otherwise copy in the override function pointers */ |
83 | memcpy(&l_ExternalVideoFuncTable, VideoFunctionStruct, sizeof(m64p_video_extension_functions)); |
84 | l_VideoExtensionActive = 1; |
85 | return M64ERR_SUCCESS; |
86 | } |
87 | |
88 | int VidExt_InFullscreenMode(void) |
89 | { |
90 | return l_Fullscreen; |
91 | } |
92 | |
93 | int VidExt_VideoRunning(void) |
94 | { |
95 | return l_VideoOutputActive; |
96 | } |
97 | |
98 | /* video extension functions to be called by the video plugin */ |
99 | EXPORT m64p_error CALL VidExt_Init(void) |
100 | { |
101 | /* call video extension override if necessary */ |
102 | if (l_VideoExtensionActive) |
103 | return (*l_ExternalVideoFuncTable.VidExtFuncInit)(); |
104 | |
105 | #if SDL_VERSION_ATLEAST(2,0,0) |
106 | SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1" ); |
107 | /* retrieve default swap interval/VSync */ |
108 | l_SwapControl = SDL_GL_GetSwapInterval(); |
109 | #endif |
110 | |
111 | if (SDL_InitSubSystem(SDL_INIT_VIDEO) == -1) |
112 | { |
113 | DebugMessage(M64MSG_ERROR, "SDL video subsystem init failed: %s" , SDL_GetError()); |
114 | return M64ERR_SYSTEM_FAIL; |
115 | } |
116 | |
117 | return M64ERR_SUCCESS; |
118 | } |
119 | |
120 | EXPORT m64p_error CALL VidExt_Quit(void) |
121 | { |
122 | /* call video extension override if necessary */ |
123 | if (l_VideoExtensionActive) |
124 | { |
125 | m64p_error rval = (*l_ExternalVideoFuncTable.VidExtFuncQuit)(); |
126 | if (rval == M64ERR_SUCCESS) |
127 | { |
128 | l_VideoOutputActive = 0; |
129 | StateChanged(M64CORE_VIDEO_MODE, M64VIDEO_NONE); |
130 | } |
131 | return rval; |
132 | } |
133 | |
134 | if (!SDL_WasInit(SDL_INIT_VIDEO)) |
135 | return M64ERR_NOT_INIT; |
136 | |
137 | SDL_ShowCursor(SDL_ENABLE); |
138 | #if SDL_VERSION_ATLEAST(2,0,0) |
139 | SDL2_DestroyWindow(); |
140 | #endif |
141 | SDL_QuitSubSystem(SDL_INIT_VIDEO); |
142 | l_pScreen = NULL; |
143 | l_VideoOutputActive = 0; |
144 | StateChanged(M64CORE_VIDEO_MODE, M64VIDEO_NONE); |
145 | |
146 | return M64ERR_SUCCESS; |
147 | } |
148 | |
149 | EXPORT m64p_error CALL VidExt_ListFullscreenModes(m64p_2d_size *SizeArray, int *NumSizes) |
150 | { |
151 | const SDL_VideoInfo *videoInfo; |
152 | unsigned int videoFlags; |
153 | SDL_Rect **modes; |
154 | int i; |
155 | |
156 | /* call video extension override if necessary */ |
157 | if (l_VideoExtensionActive) |
158 | return (*l_ExternalVideoFuncTable.VidExtFuncListModes)(SizeArray, NumSizes); |
159 | |
160 | if (!SDL_WasInit(SDL_INIT_VIDEO)) |
161 | return M64ERR_NOT_INIT; |
162 | |
163 | /* get a list of SDL video modes */ |
164 | videoFlags = SDL_OPENGL | SDL_FULLSCREEN; |
165 | |
166 | if ((videoInfo = SDL_GetVideoInfo()) == NULL) |
167 | { |
168 | DebugMessage(M64MSG_ERROR, "SDL_GetVideoInfo query failed: %s" , SDL_GetError()); |
169 | return M64ERR_SYSTEM_FAIL; |
170 | } |
171 | |
172 | if(videoInfo->hw_available) |
173 | videoFlags |= SDL_HWSURFACE; |
174 | else |
175 | videoFlags |= SDL_SWSURFACE; |
176 | |
177 | modes = SDL_ListModes(NULL, videoFlags); |
178 | |
179 | if (modes == (SDL_Rect **) 0 || modes == (SDL_Rect **) -1) |
180 | { |
181 | DebugMessage(M64MSG_WARNING, "No fullscreen SDL video modes available" ); |
182 | *NumSizes = 0; |
183 | return M64ERR_SUCCESS; |
184 | } |
185 | |
186 | i = 0; |
187 | while (i < *NumSizes && modes[i] != NULL) |
188 | { |
189 | SizeArray[i].uiWidth = modes[i]->w; |
190 | SizeArray[i].uiHeight = modes[i]->h; |
191 | i++; |
192 | } |
193 | |
194 | *NumSizes = i; |
195 | |
196 | return M64ERR_SUCCESS; |
197 | } |
198 | |
199 | EXPORT m64p_error CALL VidExt_SetVideoMode(int Width, int Height, int BitsPerPixel, m64p_video_mode ScreenMode, m64p_video_flags Flags) |
200 | { |
201 | const SDL_VideoInfo *videoInfo; |
202 | int videoFlags = 0; |
203 | |
204 | /* call video extension override if necessary */ |
205 | if (l_VideoExtensionActive) |
206 | { |
207 | m64p_error rval = (*l_ExternalVideoFuncTable.VidExtFuncSetMode)(Width, Height, BitsPerPixel, ScreenMode, Flags); |
208 | l_Fullscreen = (rval == M64ERR_SUCCESS && ScreenMode == M64VIDEO_FULLSCREEN); |
209 | l_VideoOutputActive = (rval == M64ERR_SUCCESS); |
210 | if (l_VideoOutputActive) |
211 | { |
212 | StateChanged(M64CORE_VIDEO_MODE, ScreenMode); |
213 | StateChanged(M64CORE_VIDEO_SIZE, (Width << 16) | Height); |
214 | } |
215 | return rval; |
216 | } |
217 | |
218 | if (!SDL_WasInit(SDL_INIT_VIDEO)) |
219 | return M64ERR_NOT_INIT; |
220 | |
221 | /* Get SDL video flags to use */ |
222 | if (ScreenMode == M64VIDEO_WINDOWED) |
223 | { |
224 | videoFlags = SDL_OPENGL; |
225 | if (Flags & M64VIDEOFLAG_SUPPORT_RESIZING) |
226 | videoFlags |= SDL_RESIZABLE; |
227 | } |
228 | else if (ScreenMode == M64VIDEO_FULLSCREEN) |
229 | { |
230 | videoFlags = SDL_OPENGL | SDL_FULLSCREEN; |
231 | } |
232 | else |
233 | { |
234 | return M64ERR_INPUT_INVALID; |
235 | } |
236 | |
237 | if ((videoInfo = SDL_GetVideoInfo()) == NULL) |
238 | { |
239 | DebugMessage(M64MSG_ERROR, "SDL_GetVideoInfo query failed: %s" , SDL_GetError()); |
240 | return M64ERR_SYSTEM_FAIL; |
241 | } |
242 | if (videoInfo->hw_available) |
243 | videoFlags |= SDL_HWSURFACE; |
244 | else |
245 | videoFlags |= SDL_SWSURFACE; |
246 | |
247 | /* set the mode */ |
248 | if (BitsPerPixel > 0) |
249 | DebugMessage(M64MSG_INFO, "Setting %i-bit video mode: %ix%i" , BitsPerPixel, Width, Height); |
250 | else |
251 | DebugMessage(M64MSG_INFO, "Setting video mode: %ix%i" , Width, Height); |
252 | |
253 | l_pScreen = SDL_SetVideoMode(Width, Height, BitsPerPixel, videoFlags); |
254 | if (l_pScreen == NULL) |
255 | { |
256 | DebugMessage(M64MSG_ERROR, "SDL_SetVideoMode failed: %s" , SDL_GetError()); |
257 | return M64ERR_SYSTEM_FAIL; |
258 | } |
259 | |
260 | SDL_ShowCursor(SDL_DISABLE); |
261 | |
262 | #if SDL_VERSION_ATLEAST(2,0,0) |
263 | /* set swap interval/VSync */ |
264 | if (SDL_GL_SetSwapInterval(l_SwapControl) != 0) |
265 | { |
266 | DebugMessage(M64MSG_ERROR, "SDL swap interval (VSync) set failed: %s" , SDL_GetError()); |
267 | return M64ERR_SYSTEM_FAIL; |
268 | } |
269 | #endif |
270 | |
271 | l_Fullscreen = (ScreenMode == M64VIDEO_FULLSCREEN); |
272 | l_VideoOutputActive = 1; |
273 | StateChanged(M64CORE_VIDEO_MODE, ScreenMode); |
274 | StateChanged(M64CORE_VIDEO_SIZE, (Width << 16) | Height); |
275 | return M64ERR_SUCCESS; |
276 | } |
277 | |
278 | EXPORT m64p_error CALL VidExt_ResizeWindow(int Width, int Height) |
279 | { |
280 | const SDL_VideoInfo *videoInfo; |
281 | int videoFlags = 0; |
282 | |
283 | /* call video extension override if necessary */ |
284 | if (l_VideoExtensionActive) |
285 | { |
286 | m64p_error rval; |
287 | // shut down the OSD |
288 | osd_exit(); |
289 | // re-create the OGL context |
290 | rval = (*l_ExternalVideoFuncTable.VidExtFuncResizeWindow)(Width, Height); |
291 | if (rval == M64ERR_SUCCESS) |
292 | { |
293 | StateChanged(M64CORE_VIDEO_SIZE, (Width << 16) | Height); |
294 | // re-create the On-Screen Display |
295 | osd_init(Width, Height); |
296 | } |
297 | return rval; |
298 | } |
299 | |
300 | if (!l_VideoOutputActive || !SDL_WasInit(SDL_INIT_VIDEO)) |
301 | return M64ERR_NOT_INIT; |
302 | |
303 | if (l_Fullscreen) |
304 | { |
305 | DebugMessage(M64MSG_ERROR, "VidExt_ResizeWindow() called in fullscreen mode." ); |
306 | return M64ERR_INVALID_STATE; |
307 | } |
308 | |
309 | /* Get SDL video flags to use */ |
310 | videoFlags = SDL_OPENGL | SDL_RESIZABLE; |
311 | if ((videoInfo = SDL_GetVideoInfo()) == NULL) |
312 | { |
313 | DebugMessage(M64MSG_ERROR, "SDL_GetVideoInfo query failed: %s" , SDL_GetError()); |
314 | return M64ERR_SYSTEM_FAIL; |
315 | } |
316 | if (videoInfo->hw_available) |
317 | videoFlags |= SDL_HWSURFACE; |
318 | else |
319 | videoFlags |= SDL_SWSURFACE; |
320 | |
321 | // destroy the On-Screen Display |
322 | osd_exit(); |
323 | |
324 | /* set the re-sizing the screen will create a new OpenGL context */ |
325 | l_pScreen = SDL_SetVideoMode(Width, Height, 0, videoFlags); |
326 | if (l_pScreen == NULL) |
327 | { |
328 | DebugMessage(M64MSG_ERROR, "SDL_SetVideoMode failed: %s" , SDL_GetError()); |
329 | return M64ERR_SYSTEM_FAIL; |
330 | } |
331 | |
332 | StateChanged(M64CORE_VIDEO_SIZE, (Width << 16) | Height); |
333 | // re-create the On-Screen Display |
334 | osd_init(Width, Height); |
335 | return M64ERR_SUCCESS; |
336 | } |
337 | |
338 | EXPORT m64p_error CALL VidExt_SetCaption(const char *Title) |
339 | { |
340 | /* call video extension override if necessary */ |
341 | if (l_VideoExtensionActive) |
342 | return (*l_ExternalVideoFuncTable.VidExtFuncSetCaption)(Title); |
343 | |
344 | if (!SDL_WasInit(SDL_INIT_VIDEO)) |
345 | return M64ERR_NOT_INIT; |
346 | |
347 | SDL_WM_SetCaption(Title, "M64+ Video" ); |
348 | |
349 | return M64ERR_SUCCESS; |
350 | } |
351 | |
352 | EXPORT m64p_error CALL VidExt_ToggleFullScreen(void) |
353 | { |
354 | /* call video extension override if necessary */ |
355 | if (l_VideoExtensionActive) |
356 | { |
357 | m64p_error rval = (*l_ExternalVideoFuncTable.VidExtFuncToggleFS)(); |
358 | if (rval == M64ERR_SUCCESS) |
359 | { |
360 | l_Fullscreen = !l_Fullscreen; |
361 | StateChanged(M64CORE_VIDEO_MODE, l_Fullscreen ? M64VIDEO_FULLSCREEN : M64VIDEO_WINDOWED); |
362 | } |
363 | return rval; |
364 | } |
365 | |
366 | if (!SDL_WasInit(SDL_INIT_VIDEO)) |
367 | return M64ERR_NOT_INIT; |
368 | |
369 | /* TODO: |
370 | * SDL_WM_ToggleFullScreen doesn't work under Windows and others |
371 | * (see http://wiki.libsdl.org/moin.cgi/FAQWindows for explanation). |
372 | * Instead, we should call SDL_SetVideoMode with the SDL_FULLSCREEN flag. |
373 | * (see http://sdl.beuc.net/sdl.wiki/SDL_SetVideoMode), but on Windows |
374 | * this resets the OpenGL context and video plugins don't support it yet. |
375 | * Uncomment the next line to test it: */ |
376 | //return VidExt_SetVideoMode(l_pScreen->w, l_pScreen->h, l_pScreen->format->BitsPerPixel, l_Fullscreen ? M64VIDEO_WINDOWED : M64VIDEO_FULLSCREEN); |
377 | if (SDL_WM_ToggleFullScreen(l_pScreen) == 1) |
378 | { |
379 | l_Fullscreen = !l_Fullscreen; |
380 | StateChanged(M64CORE_VIDEO_MODE, l_Fullscreen ? M64VIDEO_FULLSCREEN : M64VIDEO_WINDOWED); |
381 | return M64ERR_SUCCESS; |
382 | } |
383 | |
384 | return M64ERR_SYSTEM_FAIL; |
385 | } |
386 | |
387 | EXPORT m64p_function CALL VidExt_GL_GetProcAddress(const char* Proc) |
388 | { |
389 | /* call video extension override if necessary */ |
390 | if (l_VideoExtensionActive) |
391 | return (*l_ExternalVideoFuncTable.VidExtFuncGLGetProc)(Proc); |
392 | |
393 | if (!SDL_WasInit(SDL_INIT_VIDEO)) |
394 | return NULL; |
395 | |
396 | /* WARN: assume cast to m64p_function is supported by platform and disable warning accordingly */ |
397 | OSAL_WARNING_PUSH |
398 | OSAL_NO_WARNING_FPTR_VOIDP_CAST |
399 | return (m64p_function)SDL_GL_GetProcAddress(Proc); |
400 | OSAL_WARNING_POP |
401 | } |
402 | |
403 | typedef struct { |
404 | m64p_GLattr m64Attr; |
405 | SDL_GLattr sdlAttr; |
406 | } GLAttrMapNode; |
407 | |
408 | static const GLAttrMapNode GLAttrMap[] = { |
409 | { M64P_GL_DOUBLEBUFFER, SDL_GL_DOUBLEBUFFER }, |
410 | { M64P_GL_BUFFER_SIZE, SDL_GL_BUFFER_SIZE }, |
411 | { M64P_GL_DEPTH_SIZE, SDL_GL_DEPTH_SIZE }, |
412 | { M64P_GL_RED_SIZE, SDL_GL_RED_SIZE }, |
413 | { M64P_GL_GREEN_SIZE, SDL_GL_GREEN_SIZE }, |
414 | { M64P_GL_BLUE_SIZE, SDL_GL_BLUE_SIZE }, |
415 | { M64P_GL_ALPHA_SIZE, SDL_GL_ALPHA_SIZE }, |
416 | #if !SDL_VERSION_ATLEAST(1,3,0) |
417 | { M64P_GL_SWAP_CONTROL, SDL_GL_SWAP_CONTROL }, |
418 | #endif |
419 | { M64P_GL_MULTISAMPLEBUFFERS, SDL_GL_MULTISAMPLEBUFFERS }, |
420 | { M64P_GL_MULTISAMPLESAMPLES, SDL_GL_MULTISAMPLESAMPLES } |
421 | #if SDL_VERSION_ATLEAST(2,0,0) |
422 | ,{ M64P_GL_CONTEXT_MAJOR_VERSION, SDL_GL_CONTEXT_MAJOR_VERSION }, |
423 | { M64P_GL_CONTEXT_MINOR_VERSION, SDL_GL_CONTEXT_MINOR_VERSION }, |
424 | { M64P_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_MASK } |
425 | #endif |
426 | }; |
427 | static const int mapSize = sizeof(GLAttrMap) / sizeof(GLAttrMapNode); |
428 | |
429 | EXPORT m64p_error CALL VidExt_GL_SetAttribute(m64p_GLattr Attr, int Value) |
430 | { |
431 | int i; |
432 | |
433 | /* call video extension override if necessary */ |
434 | if (l_VideoExtensionActive) |
435 | return (*l_ExternalVideoFuncTable.VidExtFuncGLSetAttr)(Attr, Value); |
436 | |
437 | if (!SDL_WasInit(SDL_INIT_VIDEO)) |
438 | return M64ERR_NOT_INIT; |
439 | |
440 | if (Attr == M64P_GL_SWAP_CONTROL) |
441 | { |
442 | /* SDL swap interval/vsync needs to be set on current GL context, so save it for later */ |
443 | l_SwapControl = Value; |
444 | } |
445 | |
446 | /* translate the GL context type mask if necessary */ |
447 | #if SDL_VERSION_ATLEAST(2,0,0) |
448 | if (Attr == M64P_GL_CONTEXT_PROFILE_MASK) |
449 | { |
450 | switch (Value) |
451 | { |
452 | case M64P_GL_CONTEXT_PROFILE_CORE: |
453 | Value = SDL_GL_CONTEXT_PROFILE_CORE; |
454 | #ifndef USE_GLES |
455 | l_ForceCompatibilityContext = 0; |
456 | #endif |
457 | break; |
458 | case M64P_GL_CONTEXT_PROFILE_COMPATIBILITY: |
459 | Value = SDL_GL_CONTEXT_PROFILE_COMPATIBILITY; |
460 | break; |
461 | case M64P_GL_CONTEXT_PROFILE_ES: |
462 | Value = SDL_GL_CONTEXT_PROFILE_ES; |
463 | break; |
464 | default: |
465 | Value = 0; |
466 | } |
467 | } |
468 | #endif |
469 | |
470 | for (i = 0; i < mapSize; i++) |
471 | { |
472 | if (GLAttrMap[i].m64Attr == Attr) |
473 | { |
474 | if (SDL_GL_SetAttribute(GLAttrMap[i].sdlAttr, Value) != 0) |
475 | return M64ERR_SYSTEM_FAIL; |
476 | return M64ERR_SUCCESS; |
477 | } |
478 | } |
479 | |
480 | return M64ERR_INPUT_INVALID; |
481 | } |
482 | |
483 | EXPORT m64p_error CALL VidExt_GL_GetAttribute(m64p_GLattr Attr, int *pValue) |
484 | { |
485 | int i; |
486 | |
487 | /* call video extension override if necessary */ |
488 | if (l_VideoExtensionActive) |
489 | return (*l_ExternalVideoFuncTable.VidExtFuncGLGetAttr)(Attr, pValue); |
490 | |
491 | if (!SDL_WasInit(SDL_INIT_VIDEO)) |
492 | return M64ERR_NOT_INIT; |
493 | |
494 | #if SDL_VERSION_ATLEAST(2,0,0) |
495 | if (Attr == M64P_GL_SWAP_CONTROL) |
496 | { |
497 | *pValue = SDL_GL_GetSwapInterval(); |
498 | return M64ERR_SUCCESS; |
499 | } |
500 | #endif |
501 | |
502 | for (i = 0; i < mapSize; i++) |
503 | { |
504 | if (GLAttrMap[i].m64Attr == Attr) |
505 | { |
506 | int NewValue = 0; |
507 | if (SDL_GL_GetAttribute(GLAttrMap[i].sdlAttr, &NewValue) != 0) |
508 | return M64ERR_SYSTEM_FAIL; |
509 | /* translate the GL context type mask if necessary */ |
510 | #if SDL_VERSION_ATLEAST(2,0,0) |
511 | if (Attr == M64P_GL_CONTEXT_PROFILE_MASK) |
512 | { |
513 | switch (NewValue) |
514 | { |
515 | case SDL_GL_CONTEXT_PROFILE_CORE: |
516 | NewValue = M64P_GL_CONTEXT_PROFILE_CORE; |
517 | break; |
518 | case SDL_GL_CONTEXT_PROFILE_COMPATIBILITY: |
519 | NewValue = M64P_GL_CONTEXT_PROFILE_COMPATIBILITY; |
520 | break; |
521 | case SDL_GL_CONTEXT_PROFILE_ES: |
522 | NewValue = M64P_GL_CONTEXT_PROFILE_ES; |
523 | break; |
524 | default: |
525 | NewValue = 0; |
526 | } |
527 | } |
528 | #endif |
529 | *pValue = NewValue; |
530 | return M64ERR_SUCCESS; |
531 | } |
532 | } |
533 | |
534 | return M64ERR_INPUT_INVALID; |
535 | } |
536 | |
537 | EXPORT m64p_error CALL VidExt_GL_SwapBuffers(void) |
538 | { |
539 | /* call video extension override if necessary */ |
540 | if (l_VideoExtensionActive) |
541 | return (*l_ExternalVideoFuncTable.VidExtFuncGLSwapBuf)(); |
542 | |
543 | if (!SDL_WasInit(SDL_INIT_VIDEO)) |
544 | return M64ERR_NOT_INIT; |
545 | |
546 | SDL_GL_SwapBuffers(); |
547 | return M64ERR_SUCCESS; |
548 | } |
549 | |
550 | EXPORT uint32_t CALL VidExt_GL_GetDefaultFramebuffer(void) |
551 | { |
552 | if (l_VideoExtensionActive) |
553 | return (*l_ExternalVideoFuncTable.VidExtFuncGLGetDefaultFramebuffer)(); |
554 | |
555 | return 0; |
556 | } |
557 | |