1 /*
2   Simple DirectMedia Layer
3   Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
4 
5   This software is provided 'as-is', without any express or implied
6   warranty.  In no event will the authors be held liable for any damages
7   arising from the use of this software.
8 
9   Permission is granted to anyone to use this software for any purpose,
10   including commercial applications, and to alter it and redistribute it
11   freely, subject to the following restrictions:
12 
13   1. The origin of this software must not be misrepresented; you must not
14      claim that you wrote the original software. If you use this software
15      in a product, an acknowledgment in the product documentation would be
16      appreciated but is not required.
17   2. Altered source versions must be plainly marked as such, and must not be
18      misrepresented as being the original software.
19   3. This notice may not be removed or altered from any source distribution.
20 */
21 #include "../../SDL_internal.h"
22 
23 #if SDL_VIDEO_DRIVER_PANDORA
24 
25 /* SDL internals */
26 #include "../SDL_sysvideo.h"
27 #include "SDL_version.h"
28 #include "SDL_syswm.h"
29 #include "SDL_loadso.h"
30 #include "SDL_events.h"
31 #include "../../events/SDL_mouse_c.h"
32 #include "../../events/SDL_keyboard_c.h"
33 
34 /* PND declarations */
35 #include "SDL_pandora.h"
36 #include "SDL_pandora_events.h"
37 
38 /* WIZ declarations */
39 #include "GLES/gl.h"
40 #ifdef WIZ_GLES_LITE
41 static NativeWindowType hNativeWnd = 0; /* A handle to the window we will create. */
42 #endif
43 
44 static int
PND_available(void)45 PND_available(void)
46 {
47     return 1;
48 }
49 
50 static void
PND_destroy(SDL_VideoDevice * device)51 PND_destroy(SDL_VideoDevice * device)
52 {
53     if (device->driverdata != NULL) {
54         SDL_free(device->driverdata);
55         device->driverdata = NULL;
56     }
57     SDL_free(device);
58 }
59 
60 static SDL_VideoDevice *
PND_create()61 PND_create()
62 {
63     SDL_VideoDevice *device;
64     SDL_VideoData *phdata;
65     int status;
66 
67     /* Check if pandora could be initialized */
68     status = PND_available();
69     if (status == 0) {
70         /* PND could not be used */
71         return NULL;
72     }
73 
74     /* Initialize SDL_VideoDevice structure */
75     device = (SDL_VideoDevice *) SDL_calloc(1, sizeof(SDL_VideoDevice));
76     if (device == NULL) {
77         SDL_OutOfMemory();
78         return NULL;
79     }
80 
81     /* Initialize internal Pandora specific data */
82     phdata = (SDL_VideoData *) SDL_calloc(1, sizeof(SDL_VideoData));
83     if (phdata == NULL) {
84         SDL_OutOfMemory();
85         SDL_free(device);
86         return NULL;
87     }
88 
89     device->driverdata = phdata;
90 
91     phdata->egl_initialized = SDL_TRUE;
92 
93 
94     /* Setup amount of available displays */
95     device->num_displays = 0;
96 
97     /* Set device free function */
98     device->free = PND_destroy;
99 
100     /* Setup all functions which we can handle */
101     device->VideoInit = PND_videoinit;
102     device->VideoQuit = PND_videoquit;
103     device->GetDisplayModes = PND_getdisplaymodes;
104     device->SetDisplayMode = PND_setdisplaymode;
105     device->CreateSDLWindow = PND_createwindow;
106     device->CreateSDLWindowFrom = PND_createwindowfrom;
107     device->SetWindowTitle = PND_setwindowtitle;
108     device->SetWindowIcon = PND_setwindowicon;
109     device->SetWindowPosition = PND_setwindowposition;
110     device->SetWindowSize = PND_setwindowsize;
111     device->ShowWindow = PND_showwindow;
112     device->HideWindow = PND_hidewindow;
113     device->RaiseWindow = PND_raisewindow;
114     device->MaximizeWindow = PND_maximizewindow;
115     device->MinimizeWindow = PND_minimizewindow;
116     device->RestoreWindow = PND_restorewindow;
117     device->SetWindowGrab = PND_setwindowgrab;
118     device->DestroyWindow = PND_destroywindow;
119 #if 0
120     device->GetWindowWMInfo = PND_getwindowwminfo;
121 #endif
122     device->GL_LoadLibrary = PND_gl_loadlibrary;
123     device->GL_GetProcAddress = PND_gl_getprocaddres;
124     device->GL_UnloadLibrary = PND_gl_unloadlibrary;
125     device->GL_CreateContext = PND_gl_createcontext;
126     device->GL_MakeCurrent = PND_gl_makecurrent;
127     device->GL_SetSwapInterval = PND_gl_setswapinterval;
128     device->GL_GetSwapInterval = PND_gl_getswapinterval;
129     device->GL_SwapWindow = PND_gl_swapwindow;
130     device->GL_DeleteContext = PND_gl_deletecontext;
131     device->PumpEvents = PND_PumpEvents;
132 
133     /* !!! FIXME: implement SetWindowBordered */
134 
135     return device;
136 }
137 
138 VideoBootStrap PND_bootstrap = {
139 #ifdef WIZ_GLES_LITE
140     "wiz",
141     "SDL Wiz Video Driver",
142 #else
143     "pandora",
144     "SDL Pandora Video Driver",
145 #endif
146     PND_available,
147     PND_create
148 };
149 
150 /*****************************************************************************/
151 /* SDL Video and Display initialization/handling functions                   */
152 /*****************************************************************************/
153 int
PND_videoinit(_THIS)154 PND_videoinit(_THIS)
155 {
156     SDL_VideoDisplay display;
157     SDL_DisplayMode current_mode;
158 
159     SDL_zero(current_mode);
160 #ifdef WIZ_GLES_LITE
161     current_mode.w = 320;
162     current_mode.h = 240;
163 #else
164     current_mode.w = 800;
165     current_mode.h = 480;
166 #endif
167     current_mode.refresh_rate = 60;
168     current_mode.format = SDL_PIXELFORMAT_RGB565;
169     current_mode.driverdata = NULL;
170 
171     SDL_zero(display);
172     display.desktop_mode = current_mode;
173     display.current_mode = current_mode;
174     display.driverdata = NULL;
175 
176     SDL_AddVideoDisplay(&display);
177 
178     return 1;
179 }
180 
181 void
PND_videoquit(_THIS)182 PND_videoquit(_THIS)
183 {
184 
185 }
186 
187 void
PND_getdisplaymodes(_THIS,SDL_VideoDisplay * display)188 PND_getdisplaymodes(_THIS, SDL_VideoDisplay * display)
189 {
190 
191 }
192 
193 int
PND_setdisplaymode(_THIS,SDL_VideoDisplay * display,SDL_DisplayMode * mode)194 PND_setdisplaymode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode)
195 {
196     return 0;
197 }
198 
199 int
PND_createwindow(_THIS,SDL_Window * window)200 PND_createwindow(_THIS, SDL_Window * window)
201 {
202     SDL_VideoData *phdata = (SDL_VideoData *) _this->driverdata;
203 
204     SDL_WindowData *wdata;
205 
206     /* Allocate window internal data */
207     wdata = (SDL_WindowData *) SDL_calloc(1, sizeof(SDL_WindowData));
208     if (wdata == NULL) {
209         return SDL_OutOfMemory();
210     }
211 
212     /* Setup driver data for this window */
213     window->driverdata = wdata;
214 
215     /* Check if window must support OpenGL ES rendering */
216     if ((window->flags & SDL_WINDOW_OPENGL) == SDL_WINDOW_OPENGL) {
217 
218         EGLBoolean initstatus;
219 
220         /* Mark this window as OpenGL ES compatible */
221         wdata->uses_gles = SDL_TRUE;
222 
223         /* Create connection to OpenGL ES */
224         if (phdata->egl_display == EGL_NO_DISPLAY) {
225             phdata->egl_display = eglGetDisplay((NativeDisplayType) 0);
226             if (phdata->egl_display == EGL_NO_DISPLAY) {
227                 return SDL_SetError("PND: Can't get connection to OpenGL ES");
228             }
229 
230             initstatus = eglInitialize(phdata->egl_display, NULL, NULL);
231             if (initstatus != EGL_TRUE) {
232                 return SDL_SetError("PND: Can't init OpenGL ES library");
233             }
234         }
235 
236         phdata->egl_refcount++;
237     }
238 
239     /* Window has been successfully created */
240     return 0;
241 }
242 
243 int
PND_createwindowfrom(_THIS,SDL_Window * window,const void * data)244 PND_createwindowfrom(_THIS, SDL_Window * window, const void *data)
245 {
246     return -1;
247 }
248 
249 void
PND_setwindowtitle(_THIS,SDL_Window * window)250 PND_setwindowtitle(_THIS, SDL_Window * window)
251 {
252 }
253 void
PND_setwindowicon(_THIS,SDL_Window * window,SDL_Surface * icon)254 PND_setwindowicon(_THIS, SDL_Window * window, SDL_Surface * icon)
255 {
256 }
257 void
PND_setwindowposition(_THIS,SDL_Window * window)258 PND_setwindowposition(_THIS, SDL_Window * window)
259 {
260 }
261 void
PND_setwindowsize(_THIS,SDL_Window * window)262 PND_setwindowsize(_THIS, SDL_Window * window)
263 {
264 }
265 void
PND_showwindow(_THIS,SDL_Window * window)266 PND_showwindow(_THIS, SDL_Window * window)
267 {
268 }
269 void
PND_hidewindow(_THIS,SDL_Window * window)270 PND_hidewindow(_THIS, SDL_Window * window)
271 {
272 }
273 void
PND_raisewindow(_THIS,SDL_Window * window)274 PND_raisewindow(_THIS, SDL_Window * window)
275 {
276 }
277 void
PND_maximizewindow(_THIS,SDL_Window * window)278 PND_maximizewindow(_THIS, SDL_Window * window)
279 {
280 }
281 void
PND_minimizewindow(_THIS,SDL_Window * window)282 PND_minimizewindow(_THIS, SDL_Window * window)
283 {
284 }
285 void
PND_restorewindow(_THIS,SDL_Window * window)286 PND_restorewindow(_THIS, SDL_Window * window)
287 {
288 }
289 void
PND_setwindowgrab(_THIS,SDL_Window * window,SDL_bool grabbed)290 PND_setwindowgrab(_THIS, SDL_Window * window, SDL_bool grabbed)
291 {
292 }
293 void
PND_destroywindow(_THIS,SDL_Window * window)294 PND_destroywindow(_THIS, SDL_Window * window)
295 {
296     SDL_VideoData *phdata = (SDL_VideoData *) _this->driverdata;
297     eglTerminate(phdata->egl_display);
298 }
299 
300 /*****************************************************************************/
301 /* SDL Window Manager function                                               */
302 /*****************************************************************************/
303 #if 0
304 SDL_bool
305 PND_getwindowwminfo(_THIS, SDL_Window * window, struct SDL_SysWMinfo *info)
306 {
307     if (info->version.major <= SDL_MAJOR_VERSION) {
308         return SDL_TRUE;
309     } else {
310         SDL_SetError("application not compiled with SDL %d.%d",
311                      SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
312         return SDL_FALSE;
313     }
314 
315     /* Failed to get window manager information */
316     return SDL_FALSE;
317 }
318 #endif
319 
320 /*****************************************************************************/
321 /* SDL OpenGL/OpenGL ES functions                                            */
322 /*****************************************************************************/
323 int
PND_gl_loadlibrary(_THIS,const char * path)324 PND_gl_loadlibrary(_THIS, const char *path)
325 {
326     /* Check if OpenGL ES library is specified for GF driver */
327     if (path == NULL) {
328         path = SDL_getenv("SDL_OPENGL_LIBRARY");
329         if (path == NULL) {
330             path = SDL_getenv("SDL_OPENGLES_LIBRARY");
331         }
332     }
333 
334     /* Check if default library loading requested */
335     if (path == NULL) {
336         /* Already linked with GF library which provides egl* subset of  */
337         /* functions, use Common profile of OpenGL ES library by default */
338 #ifdef WIZ_GLES_LITE
339     path = "/lib/libopengles_lite.so";
340 #else
341         path = "/usr/lib/libGLES_CM.so";
342 #endif
343     }
344 
345     /* Load dynamic library */
346     _this->gl_config.dll_handle = SDL_LoadObject(path);
347     if (!_this->gl_config.dll_handle) {
348         /* Failed to load new GL ES library */
349         return SDL_SetError("PND: Failed to locate OpenGL ES library");
350     }
351 
352     /* Store OpenGL ES library path and name */
353     SDL_strlcpy(_this->gl_config.driver_path, path,
354                 SDL_arraysize(_this->gl_config.driver_path));
355 
356     /* New OpenGL ES library is loaded */
357     return 0;
358 }
359 
360 void *
PND_gl_getprocaddres(_THIS,const char * proc)361 PND_gl_getprocaddres(_THIS, const char *proc)
362 {
363     void *function_address;
364 
365     /* Try to get function address through the egl interface */
366     function_address = eglGetProcAddress(proc);
367     if (function_address != NULL) {
368         return function_address;
369     }
370 
371     /* Then try to get function in the OpenGL ES library */
372     if (_this->gl_config.dll_handle) {
373         function_address =
374             SDL_LoadFunction(_this->gl_config.dll_handle, proc);
375         if (function_address != NULL) {
376             return function_address;
377         }
378     }
379 
380     /* Failed to get GL ES function address pointer */
381     SDL_SetError("PND: Cannot locate OpenGL ES function name");
382     return NULL;
383 }
384 
385 void
PND_gl_unloadlibrary(_THIS)386 PND_gl_unloadlibrary(_THIS)
387 {
388     SDL_VideoData *phdata = (SDL_VideoData *) _this->driverdata;
389 
390     if (phdata->egl_initialized == SDL_TRUE) {
391         /* Unload OpenGL ES library */
392         if (_this->gl_config.dll_handle) {
393             SDL_UnloadObject(_this->gl_config.dll_handle);
394             _this->gl_config.dll_handle = NULL;
395         }
396     } else {
397         SDL_SetError("PND: GF initialization failed, no OpenGL ES support");
398     }
399 }
400 
401 SDL_GLContext
PND_gl_createcontext(_THIS,SDL_Window * window)402 PND_gl_createcontext(_THIS, SDL_Window * window)
403 {
404     SDL_VideoData *phdata = (SDL_VideoData *) _this->driverdata;
405     SDL_WindowData *wdata = (SDL_WindowData *) window->driverdata;
406     EGLBoolean status;
407     EGLint configs;
408     uint32_t attr_pos;
409     EGLint attr_value;
410     EGLint cit;
411 
412     /* Check if EGL was initialized */
413     if (phdata->egl_initialized != SDL_TRUE) {
414         SDL_SetError("PND: EGL initialization failed, no OpenGL ES support");
415         return NULL;
416     }
417 
418     /* Prepare attributes list to pass them to OpenGL ES */
419     attr_pos = 0;
420     wdata->gles_attributes[attr_pos++] = EGL_SURFACE_TYPE;
421     wdata->gles_attributes[attr_pos++] = EGL_WINDOW_BIT;
422     wdata->gles_attributes[attr_pos++] = EGL_RED_SIZE;
423     wdata->gles_attributes[attr_pos++] = _this->gl_config.red_size;
424     wdata->gles_attributes[attr_pos++] = EGL_GREEN_SIZE;
425     wdata->gles_attributes[attr_pos++] = _this->gl_config.green_size;
426     wdata->gles_attributes[attr_pos++] = EGL_BLUE_SIZE;
427     wdata->gles_attributes[attr_pos++] = _this->gl_config.blue_size;
428     wdata->gles_attributes[attr_pos++] = EGL_ALPHA_SIZE;
429 
430     /* Setup alpha size in bits */
431     if (_this->gl_config.alpha_size) {
432         wdata->gles_attributes[attr_pos++] = _this->gl_config.alpha_size;
433     } else {
434         wdata->gles_attributes[attr_pos++] = EGL_DONT_CARE;
435     }
436 
437     /* Setup color buffer size */
438     if (_this->gl_config.buffer_size) {
439         wdata->gles_attributes[attr_pos++] = EGL_BUFFER_SIZE;
440         wdata->gles_attributes[attr_pos++] = _this->gl_config.buffer_size;
441     } else {
442         wdata->gles_attributes[attr_pos++] = EGL_BUFFER_SIZE;
443         wdata->gles_attributes[attr_pos++] = EGL_DONT_CARE;
444     }
445 
446     /* Setup depth buffer bits */
447     wdata->gles_attributes[attr_pos++] = EGL_DEPTH_SIZE;
448     wdata->gles_attributes[attr_pos++] = _this->gl_config.depth_size;
449 
450     /* Setup stencil bits */
451     if (_this->gl_config.stencil_size) {
452         wdata->gles_attributes[attr_pos++] = EGL_STENCIL_SIZE;
453         wdata->gles_attributes[attr_pos++] = _this->gl_config.buffer_size;
454     } else {
455         wdata->gles_attributes[attr_pos++] = EGL_STENCIL_SIZE;
456         wdata->gles_attributes[attr_pos++] = EGL_DONT_CARE;
457     }
458 
459     /* Set number of samples in multisampling */
460     if (_this->gl_config.multisamplesamples) {
461         wdata->gles_attributes[attr_pos++] = EGL_SAMPLES;
462         wdata->gles_attributes[attr_pos++] =
463             _this->gl_config.multisamplesamples;
464     }
465 
466     /* Multisample buffers, OpenGL ES 1.0 spec defines 0 or 1 buffer */
467     if (_this->gl_config.multisamplebuffers) {
468         wdata->gles_attributes[attr_pos++] = EGL_SAMPLE_BUFFERS;
469         wdata->gles_attributes[attr_pos++] =
470             _this->gl_config.multisamplebuffers;
471     }
472 
473     /* Finish attributes list */
474     wdata->gles_attributes[attr_pos] = EGL_NONE;
475 
476     /* Request first suitable framebuffer configuration */
477     status = eglChooseConfig(phdata->egl_display, wdata->gles_attributes,
478                              wdata->gles_configs, 1, &configs);
479     if (status != EGL_TRUE) {
480         SDL_SetError("PND: Can't find closest configuration for OpenGL ES");
481         return NULL;
482     }
483 
484     /* Check if nothing has been found, try "don't care" settings */
485     if (configs == 0) {
486         int32_t it;
487         int32_t jt;
488         GLint depthbits[4] = { 32, 24, 16, EGL_DONT_CARE };
489 
490         for (it = 0; it < 4; it++) {
491             for (jt = 16; jt >= 0; jt--) {
492                 /* Don't care about color buffer bits, use what exist */
493                 /* Replace previous set data with EGL_DONT_CARE       */
494                 attr_pos = 0;
495                 wdata->gles_attributes[attr_pos++] = EGL_SURFACE_TYPE;
496                 wdata->gles_attributes[attr_pos++] = EGL_WINDOW_BIT;
497                 wdata->gles_attributes[attr_pos++] = EGL_RED_SIZE;
498                 wdata->gles_attributes[attr_pos++] = EGL_DONT_CARE;
499                 wdata->gles_attributes[attr_pos++] = EGL_GREEN_SIZE;
500                 wdata->gles_attributes[attr_pos++] = EGL_DONT_CARE;
501                 wdata->gles_attributes[attr_pos++] = EGL_BLUE_SIZE;
502                 wdata->gles_attributes[attr_pos++] = EGL_DONT_CARE;
503                 wdata->gles_attributes[attr_pos++] = EGL_ALPHA_SIZE;
504                 wdata->gles_attributes[attr_pos++] = EGL_DONT_CARE;
505                 wdata->gles_attributes[attr_pos++] = EGL_BUFFER_SIZE;
506                 wdata->gles_attributes[attr_pos++] = EGL_DONT_CARE;
507 
508                 /* Try to find requested or smallest depth */
509                 if (_this->gl_config.depth_size) {
510                     wdata->gles_attributes[attr_pos++] = EGL_DEPTH_SIZE;
511                     wdata->gles_attributes[attr_pos++] = depthbits[it];
512                 } else {
513                     wdata->gles_attributes[attr_pos++] = EGL_DEPTH_SIZE;
514                     wdata->gles_attributes[attr_pos++] = EGL_DONT_CARE;
515                 }
516 
517                 if (_this->gl_config.stencil_size) {
518                     wdata->gles_attributes[attr_pos++] = EGL_STENCIL_SIZE;
519                     wdata->gles_attributes[attr_pos++] = jt;
520                 } else {
521                     wdata->gles_attributes[attr_pos++] = EGL_STENCIL_SIZE;
522                     wdata->gles_attributes[attr_pos++] = EGL_DONT_CARE;
523                 }
524 
525                 wdata->gles_attributes[attr_pos++] = EGL_SAMPLES;
526                 wdata->gles_attributes[attr_pos++] = EGL_DONT_CARE;
527                 wdata->gles_attributes[attr_pos++] = EGL_SAMPLE_BUFFERS;
528                 wdata->gles_attributes[attr_pos++] = EGL_DONT_CARE;
529                 wdata->gles_attributes[attr_pos] = EGL_NONE;
530 
531                 /* Request first suitable framebuffer configuration */
532                 status =
533                     eglChooseConfig(phdata->egl_display,
534                                     wdata->gles_attributes,
535                                     wdata->gles_configs, 1, &configs);
536 
537                 if (status != EGL_TRUE) {
538                     SDL_SetError
539                         ("PND: Can't find closest configuration for OpenGL ES");
540                     return NULL;
541                 }
542                 if (configs != 0) {
543                     break;
544                 }
545             }
546             if (configs != 0) {
547                 break;
548             }
549         }
550 
551         /* No available configs */
552         if (configs == 0) {
553             SDL_SetError("PND: Can't find any configuration for OpenGL ES");
554             return NULL;
555         }
556     }
557 
558     /* Initialize config index */
559     wdata->gles_config = 0;
560 
561     /* Now check each configuration to find out the best */
562     for (cit = 0; cit < configs; cit++) {
563         uint32_t stencil_found;
564         uint32_t depth_found;
565 
566         stencil_found = 0;
567         depth_found = 0;
568 
569         if (_this->gl_config.stencil_size) {
570             status =
571                 eglGetConfigAttrib(phdata->egl_display,
572                                    wdata->gles_configs[cit], EGL_STENCIL_SIZE,
573                                    &attr_value);
574             if (status == EGL_TRUE) {
575                 if (attr_value != 0) {
576                     stencil_found = 1;
577                 }
578             }
579         } else {
580             stencil_found = 1;
581         }
582 
583         if (_this->gl_config.depth_size) {
584             status =
585                 eglGetConfigAttrib(phdata->egl_display,
586                                    wdata->gles_configs[cit], EGL_DEPTH_SIZE,
587                                    &attr_value);
588             if (status == EGL_TRUE) {
589                 if (attr_value != 0) {
590                     depth_found = 1;
591                 }
592             }
593         } else {
594             depth_found = 1;
595         }
596 
597         /* Exit from loop if found appropriate configuration */
598         if ((depth_found != 0) && (stencil_found != 0)) {
599             break;
600         }
601     }
602 
603     /* If best could not be found, use first */
604     if (cit == configs) {
605         cit = 0;
606     }
607     wdata->gles_config = cit;
608 
609     /* Create OpenGL ES context */
610     wdata->gles_context =
611         eglCreateContext(phdata->egl_display,
612                          wdata->gles_configs[wdata->gles_config], NULL, NULL);
613     if (wdata->gles_context == EGL_NO_CONTEXT) {
614         SDL_SetError("PND: OpenGL ES context creation has been failed");
615         return NULL;
616     }
617 
618 #ifdef WIZ_GLES_LITE
619     if( !hNativeWnd ) {
620     hNativeWnd = (NativeWindowType)malloc(16*1024);
621 
622     if(!hNativeWnd)
623         printf( "Error: Wiz framebuffer allocatation failed\n" );
624     else
625         printf( "SDL: Wiz framebuffer allocated: %X\n", hNativeWnd );
626     }
627     else {
628         printf( "SDL: Wiz framebuffer already allocated: %X\n", hNativeWnd );
629     }
630 
631     wdata->gles_surface =
632     eglCreateWindowSurface(phdata->egl_display,
633                    wdata->gles_configs[wdata->gles_config],
634                    hNativeWnd, NULL );
635 #else
636     wdata->gles_surface =
637         eglCreateWindowSurface(phdata->egl_display,
638                                wdata->gles_configs[wdata->gles_config],
639                                (NativeWindowType) 0, NULL);
640 #endif
641 
642 
643     if (wdata->gles_surface == 0) {
644         SDL_SetError("Error : eglCreateWindowSurface failed;");
645         return NULL;
646     }
647 
648     /* Make just created context current */
649     status =
650         eglMakeCurrent(phdata->egl_display, wdata->gles_surface,
651                        wdata->gles_surface, wdata->gles_context);
652     if (status != EGL_TRUE) {
653         /* Destroy OpenGL ES surface */
654         eglDestroySurface(phdata->egl_display, wdata->gles_surface);
655         eglDestroyContext(phdata->egl_display, wdata->gles_context);
656         wdata->gles_context = EGL_NO_CONTEXT;
657         SDL_SetError("PND: Can't set OpenGL ES context on creation");
658         return NULL;
659     }
660 
661     _this->gl_config.accelerated = 1;
662 
663     /* Always clear stereo enable, since OpenGL ES do not supports stereo */
664     _this->gl_config.stereo = 0;
665 
666     /* Get back samples and samplebuffers configurations. Rest framebuffer */
667     /* parameters could be obtained through the OpenGL ES API              */
668     status =
669         eglGetConfigAttrib(phdata->egl_display,
670                            wdata->gles_configs[wdata->gles_config],
671                            EGL_SAMPLES, &attr_value);
672     if (status == EGL_TRUE) {
673         _this->gl_config.multisamplesamples = attr_value;
674     }
675     status =
676         eglGetConfigAttrib(phdata->egl_display,
677                            wdata->gles_configs[wdata->gles_config],
678                            EGL_SAMPLE_BUFFERS, &attr_value);
679     if (status == EGL_TRUE) {
680         _this->gl_config.multisamplebuffers = attr_value;
681     }
682 
683     /* Get back stencil and depth buffer sizes */
684     status =
685         eglGetConfigAttrib(phdata->egl_display,
686                            wdata->gles_configs[wdata->gles_config],
687                            EGL_DEPTH_SIZE, &attr_value);
688     if (status == EGL_TRUE) {
689         _this->gl_config.depth_size = attr_value;
690     }
691     status =
692         eglGetConfigAttrib(phdata->egl_display,
693                            wdata->gles_configs[wdata->gles_config],
694                            EGL_STENCIL_SIZE, &attr_value);
695     if (status == EGL_TRUE) {
696         _this->gl_config.stencil_size = attr_value;
697     }
698 
699     /* Under PND OpenGL ES output can't be double buffered */
700     _this->gl_config.double_buffer = 0;
701 
702     /* GL ES context was successfully created */
703     return wdata->gles_context;
704 }
705 
706 int
PND_gl_makecurrent(_THIS,SDL_Window * window,SDL_GLContext context)707 PND_gl_makecurrent(_THIS, SDL_Window * window, SDL_GLContext context)
708 {
709     SDL_VideoData *phdata = (SDL_VideoData *) _this->driverdata;
710     SDL_WindowData *wdata;
711     EGLBoolean status;
712 
713     if (phdata->egl_initialized != SDL_TRUE) {
714         return SDL_SetError("PND: GF initialization failed, no OpenGL ES support");
715     }
716 
717     if ((window == NULL) && (context == NULL)) {
718         status =
719             eglMakeCurrent(phdata->egl_display, EGL_NO_SURFACE,
720                            EGL_NO_SURFACE, EGL_NO_CONTEXT);
721         if (status != EGL_TRUE) {
722             /* Failed to set current GL ES context */
723             return SDL_SetError("PND: Can't set OpenGL ES context");
724         }
725     } else {
726         wdata = (SDL_WindowData *) window->driverdata;
727         if (wdata->gles_surface == EGL_NO_SURFACE) {
728             return SDL_SetError
729                 ("PND: OpenGL ES surface is not initialized for this window");
730         }
731         if (wdata->gles_context == EGL_NO_CONTEXT) {
732             return SDL_SetError
733                 ("PND: OpenGL ES context is not initialized for this window");
734         }
735         if (wdata->gles_context != context) {
736             return SDL_SetError
737                 ("PND: OpenGL ES context is not belong to this window");
738         }
739         status =
740             eglMakeCurrent(phdata->egl_display, wdata->gles_surface,
741                            wdata->gles_surface, wdata->gles_context);
742         if (status != EGL_TRUE) {
743             /* Failed to set current GL ES context */
744             return SDL_SetError("PND: Can't set OpenGL ES context");
745         }
746     }
747     return 0;
748 }
749 
750 int
PND_gl_setswapinterval(_THIS,int interval)751 PND_gl_setswapinterval(_THIS, int interval)
752 {
753     SDL_VideoData *phdata = (SDL_VideoData *) _this->driverdata;
754     EGLBoolean status;
755 
756     if (phdata->egl_initialized != SDL_TRUE) {
757         return SDL_SetError("PND: EGL initialization failed, no OpenGL ES support");
758     }
759 
760     /* Check if OpenGL ES connection has been initialized */
761     if (phdata->egl_display != EGL_NO_DISPLAY) {
762         /* Set swap OpenGL ES interval */
763         status = eglSwapInterval(phdata->egl_display, interval);
764         if (status == EGL_TRUE) {
765             /* Return success to upper level */
766             phdata->swapinterval = interval;
767             return 0;
768         }
769     }
770 
771     /* Failed to set swap interval */
772     return SDL_SetError("PND: Cannot set swap interval");
773 }
774 
775 int
PND_gl_getswapinterval(_THIS)776 PND_gl_getswapinterval(_THIS)
777 {
778     return ((SDL_VideoData *) _this->driverdata)->swapinterval;
779 }
780 
781 int
PND_gl_swapwindow(_THIS,SDL_Window * window)782 PND_gl_swapwindow(_THIS, SDL_Window * window)
783 {
784     SDL_VideoData *phdata = (SDL_VideoData *) _this->driverdata;
785     SDL_WindowData *wdata = (SDL_WindowData *) window->driverdata;
786 
787     if (phdata->egl_initialized != SDL_TRUE) {
788         return SDL_SetError("PND: GLES initialization failed, no OpenGL ES support");
789     }
790 
791     /* Many applications do not uses glFinish(), so we call it for them */
792     glFinish();
793 
794     /* Wait until OpenGL ES rendering is completed */
795     eglWaitGL();
796 
797     eglSwapBuffers(phdata->egl_display, wdata->gles_surface);
798     return 0;
799 }
800 
801 void
PND_gl_deletecontext(_THIS,SDL_GLContext context)802 PND_gl_deletecontext(_THIS, SDL_GLContext context)
803 {
804     SDL_VideoData *phdata = (SDL_VideoData *) _this->driverdata;
805     EGLBoolean status;
806 
807     if (phdata->egl_initialized != SDL_TRUE) {
808         SDL_SetError("PND: GLES initialization failed, no OpenGL ES support");
809         return;
810     }
811 
812     /* Check if OpenGL ES connection has been initialized */
813     if (phdata->egl_display != EGL_NO_DISPLAY) {
814         if (context != EGL_NO_CONTEXT) {
815             status = eglDestroyContext(phdata->egl_display, context);
816             if (status != EGL_TRUE) {
817                 /* Error during OpenGL ES context destroying */
818                 SDL_SetError("PND: OpenGL ES context destroy error");
819                 return;
820             }
821         }
822     }
823 
824 #ifdef WIZ_GLES_LITE
825     if( hNativeWnd != 0 )
826     {
827       free(hNativeWnd);
828       hNativeWnd = 0;
829       printf( "SDL: Wiz framebuffer released\n" );
830     }
831 #endif
832 
833     return;
834 }
835 
836 #endif /* SDL_VIDEO_DRIVER_PANDORA */
837 
838 /* vi: set ts=4 sw=4 expandtab: */
839