2 Simple DirectMedia Layer
3 Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
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.
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:
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.
21 #include "../../SDL_internal.h"
23 #if SDL_VIDEO_DRIVER_PANDORA
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"
34 /* PND declarations */
35 #include "SDL_pandora.h"
36 #include "SDL_pandora_events.h"
38 /* WIZ declarations */
41 static NativeWindowType hNativeWnd = 0; /* A handle to the window we will create. */
51 PND_destroy(SDL_VideoDevice * device)
53 if (device->driverdata != NULL) {
54 SDL_free(device->driverdata);
55 device->driverdata = NULL;
60 static SDL_VideoDevice *
63 SDL_VideoDevice *device;
64 SDL_VideoData *phdata;
67 /* Check if pandora could be initialized */
68 status = PND_available();
70 /* PND could not be used */
74 /* Initialize SDL_VideoDevice structure */
75 device = (SDL_VideoDevice *) SDL_calloc(1, sizeof(SDL_VideoDevice));
81 /* Initialize internal Pandora specific data */
82 phdata = (SDL_VideoData *) SDL_calloc(1, sizeof(SDL_VideoData));
89 device->driverdata = phdata;
91 phdata->egl_initialized = SDL_TRUE;
94 /* Setup amount of available displays */
95 device->num_displays = 0;
97 /* Set device free function */
98 device->free = PND_destroy;
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;
120 device->GetWindowWMInfo = PND_getwindowwminfo;
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;
133 /* !!! FIXME: implement SetWindowBordered */
138 VideoBootStrap PND_bootstrap = {
141 "SDL Wiz Video Driver",
144 "SDL Pandora Video Driver",
150 /*****************************************************************************/
151 /* SDL Video and Display initialization/handling functions */
152 /*****************************************************************************/
156 SDL_VideoDisplay display;
157 SDL_DisplayMode current_mode;
159 SDL_zero(current_mode);
161 current_mode.w = 320;
162 current_mode.h = 240;
164 current_mode.w = 800;
165 current_mode.h = 480;
167 current_mode.refresh_rate = 60;
168 current_mode.format = SDL_PIXELFORMAT_RGB565;
169 current_mode.driverdata = NULL;
172 display.desktop_mode = current_mode;
173 display.current_mode = current_mode;
174 display.driverdata = NULL;
176 SDL_AddVideoDisplay(&display);
188 PND_getdisplaymodes(_THIS, SDL_VideoDisplay * display)
194 PND_setdisplaymode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode)
200 PND_createwindow(_THIS, SDL_Window * window)
202 SDL_VideoData *phdata = (SDL_VideoData *) _this->driverdata;
204 SDL_WindowData *wdata;
206 /* Allocate window internal data */
207 wdata = (SDL_WindowData *) SDL_calloc(1, sizeof(SDL_WindowData));
209 return SDL_OutOfMemory();
212 /* Setup driver data for this window */
213 window->driverdata = wdata;
215 /* Check if window must support OpenGL ES rendering */
216 if ((window->flags & SDL_WINDOW_OPENGL) == SDL_WINDOW_OPENGL) {
218 EGLBoolean initstatus;
220 /* Mark this window as OpenGL ES compatible */
221 wdata->uses_gles = SDL_TRUE;
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");
230 initstatus = eglInitialize(phdata->egl_display, NULL, NULL);
231 if (initstatus != EGL_TRUE) {
232 return SDL_SetError("PND: Can't init OpenGL ES library");
236 phdata->egl_refcount++;
239 /* Window has been successfully created */
244 PND_createwindowfrom(_THIS, SDL_Window * window, const void *data)
250 PND_setwindowtitle(_THIS, SDL_Window * window)
254 PND_setwindowicon(_THIS, SDL_Window * window, SDL_Surface * icon)
258 PND_setwindowposition(_THIS, SDL_Window * window)
262 PND_setwindowsize(_THIS, SDL_Window * window)
266 PND_showwindow(_THIS, SDL_Window * window)
270 PND_hidewindow(_THIS, SDL_Window * window)
274 PND_raisewindow(_THIS, SDL_Window * window)
278 PND_maximizewindow(_THIS, SDL_Window * window)
282 PND_minimizewindow(_THIS, SDL_Window * window)
286 PND_restorewindow(_THIS, SDL_Window * window)
290 PND_setwindowgrab(_THIS, SDL_Window * window, SDL_bool grabbed)
294 PND_destroywindow(_THIS, SDL_Window * window)
296 SDL_VideoData *phdata = (SDL_VideoData *) _this->driverdata;
297 eglTerminate(phdata->egl_display);
300 /*****************************************************************************/
301 /* SDL Window Manager function */
302 /*****************************************************************************/
305 PND_getwindowwminfo(_THIS, SDL_Window * window, struct SDL_SysWMinfo *info)
307 if (info->version.major <= SDL_MAJOR_VERSION) {
310 SDL_SetError("application not compiled with SDL %d.%d",
311 SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
315 /* Failed to get window manager information */
320 /*****************************************************************************/
321 /* SDL OpenGL/OpenGL ES functions */
322 /*****************************************************************************/
324 PND_gl_loadlibrary(_THIS, const char *path)
326 /* Check if OpenGL ES library is specified for GF driver */
328 path = SDL_getenv("SDL_OPENGL_LIBRARY");
330 path = SDL_getenv("SDL_OPENGLES_LIBRARY");
334 /* Check if default library loading requested */
336 /* Already linked with GF library which provides egl* subset of */
337 /* functions, use Common profile of OpenGL ES library by default */
339 path = "/lib/libopengles_lite.so";
341 path = "/usr/lib/libGLES_CM.so";
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");
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));
356 /* New OpenGL ES library is loaded */
361 PND_gl_getprocaddres(_THIS, const char *proc)
363 void *function_address;
365 /* Try to get function address through the egl interface */
366 function_address = eglGetProcAddress(proc);
367 if (function_address != NULL) {
368 return function_address;
371 /* Then try to get function in the OpenGL ES library */
372 if (_this->gl_config.dll_handle) {
374 SDL_LoadFunction(_this->gl_config.dll_handle, proc);
375 if (function_address != NULL) {
376 return function_address;
380 /* Failed to get GL ES function address pointer */
381 SDL_SetError("PND: Cannot locate OpenGL ES function name");
386 PND_gl_unloadlibrary(_THIS)
388 SDL_VideoData *phdata = (SDL_VideoData *) _this->driverdata;
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;
397 SDL_SetError("PND: GF initialization failed, no OpenGL ES support");
402 PND_gl_createcontext(_THIS, SDL_Window * window)
404 SDL_VideoData *phdata = (SDL_VideoData *) _this->driverdata;
405 SDL_WindowData *wdata = (SDL_WindowData *) window->driverdata;
412 /* Check if EGL was initialized */
413 if (phdata->egl_initialized != SDL_TRUE) {
414 SDL_SetError("PND: EGL initialization failed, no OpenGL ES support");
418 /* Prepare attributes list to pass them to OpenGL ES */
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;
430 /* Setup alpha size in bits */
431 if (_this->gl_config.alpha_size) {
432 wdata->gles_attributes[attr_pos++] = _this->gl_config.alpha_size;
434 wdata->gles_attributes[attr_pos++] = EGL_DONT_CARE;
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;
442 wdata->gles_attributes[attr_pos++] = EGL_BUFFER_SIZE;
443 wdata->gles_attributes[attr_pos++] = EGL_DONT_CARE;
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;
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;
455 wdata->gles_attributes[attr_pos++] = EGL_STENCIL_SIZE;
456 wdata->gles_attributes[attr_pos++] = EGL_DONT_CARE;
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;
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;
473 /* Finish attributes list */
474 wdata->gles_attributes[attr_pos] = EGL_NONE;
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");
484 /* Check if nothing has been found, try "don't care" settings */
488 GLint depthbits[4] = { 32, 24, 16, EGL_DONT_CARE };
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 */
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;
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];
513 wdata->gles_attributes[attr_pos++] = EGL_DEPTH_SIZE;
514 wdata->gles_attributes[attr_pos++] = EGL_DONT_CARE;
517 if (_this->gl_config.stencil_size) {
518 wdata->gles_attributes[attr_pos++] = EGL_STENCIL_SIZE;
519 wdata->gles_attributes[attr_pos++] = jt;
521 wdata->gles_attributes[attr_pos++] = EGL_STENCIL_SIZE;
522 wdata->gles_attributes[attr_pos++] = EGL_DONT_CARE;
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;
531 /* Request first suitable framebuffer configuration */
533 eglChooseConfig(phdata->egl_display,
534 wdata->gles_attributes,
535 wdata->gles_configs, 1, &configs);
537 if (status != EGL_TRUE) {
539 ("PND: Can't find closest configuration for OpenGL ES");
551 /* No available configs */
553 SDL_SetError("PND: Can't find any configuration for OpenGL ES");
558 /* Initialize config index */
559 wdata->gles_config = 0;
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;
569 if (_this->gl_config.stencil_size) {
571 eglGetConfigAttrib(phdata->egl_display,
572 wdata->gles_configs[cit], EGL_STENCIL_SIZE,
574 if (status == EGL_TRUE) {
575 if (attr_value != 0) {
583 if (_this->gl_config.depth_size) {
585 eglGetConfigAttrib(phdata->egl_display,
586 wdata->gles_configs[cit], EGL_DEPTH_SIZE,
588 if (status == EGL_TRUE) {
589 if (attr_value != 0) {
597 /* Exit from loop if found appropriate configuration */
598 if ((depth_found != 0) && (stencil_found != 0)) {
603 /* If best could not be found, use first */
604 if (cit == configs) {
607 wdata->gles_config = cit;
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");
620 hNativeWnd = (NativeWindowType)malloc(16*1024);
623 printf( "Error: Wiz framebuffer allocatation failed\n" );
625 printf( "SDL: Wiz framebuffer allocated: %X\n", hNativeWnd );
628 printf( "SDL: Wiz framebuffer already allocated: %X\n", hNativeWnd );
631 wdata->gles_surface =
632 eglCreateWindowSurface(phdata->egl_display,
633 wdata->gles_configs[wdata->gles_config],
636 wdata->gles_surface =
637 eglCreateWindowSurface(phdata->egl_display,
638 wdata->gles_configs[wdata->gles_config],
639 (NativeWindowType) 0, NULL);
643 if (wdata->gles_surface == 0) {
644 SDL_SetError("Error : eglCreateWindowSurface failed;");
648 /* Make just created context current */
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");
661 _this->gl_config.accelerated = 1;
663 /* Always clear stereo enable, since OpenGL ES do not supports stereo */
664 _this->gl_config.stereo = 0;
666 /* Get back samples and samplebuffers configurations. Rest framebuffer */
667 /* parameters could be obtained through the OpenGL ES API */
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;
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;
683 /* Get back stencil and depth buffer sizes */
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;
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;
699 /* Under PND OpenGL ES output can't be double buffered */
700 _this->gl_config.double_buffer = 0;
702 /* GL ES context was successfully created */
703 return wdata->gles_context;
707 PND_gl_makecurrent(_THIS, SDL_Window * window, SDL_GLContext context)
709 SDL_VideoData *phdata = (SDL_VideoData *) _this->driverdata;
710 SDL_WindowData *wdata;
713 if (phdata->egl_initialized != SDL_TRUE) {
714 return SDL_SetError("PND: GF initialization failed, no OpenGL ES support");
717 if ((window == NULL) && (context == NULL)) {
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");
726 wdata = (SDL_WindowData *) window->driverdata;
727 if (wdata->gles_surface == EGL_NO_SURFACE) {
729 ("PND: OpenGL ES surface is not initialized for this window");
731 if (wdata->gles_context == EGL_NO_CONTEXT) {
733 ("PND: OpenGL ES context is not initialized for this window");
735 if (wdata->gles_context != context) {
737 ("PND: OpenGL ES context is not belong to this window");
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");
751 PND_gl_setswapinterval(_THIS, int interval)
753 SDL_VideoData *phdata = (SDL_VideoData *) _this->driverdata;
756 if (phdata->egl_initialized != SDL_TRUE) {
757 return SDL_SetError("PND: EGL initialization failed, no OpenGL ES support");
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;
771 /* Failed to set swap interval */
772 return SDL_SetError("PND: Cannot set swap interval");
776 PND_gl_getswapinterval(_THIS)
778 return ((SDL_VideoData *) _this->driverdata)->swapinterval;
782 PND_gl_swapwindow(_THIS, SDL_Window * window)
784 SDL_VideoData *phdata = (SDL_VideoData *) _this->driverdata;
785 SDL_WindowData *wdata = (SDL_WindowData *) window->driverdata;
787 if (phdata->egl_initialized != SDL_TRUE) {
788 return SDL_SetError("PND: GLES initialization failed, no OpenGL ES support");
791 /* Many applications do not uses glFinish(), so we call it for them */
794 /* Wait until OpenGL ES rendering is completed */
797 eglSwapBuffers(phdata->egl_display, wdata->gles_surface);
802 PND_gl_deletecontext(_THIS, SDL_GLContext context)
804 SDL_VideoData *phdata = (SDL_VideoData *) _this->driverdata;
807 if (phdata->egl_initialized != SDL_TRUE) {
808 SDL_SetError("PND: GLES initialization failed, no OpenGL ES support");
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");
825 if( hNativeWnd != 0 )
829 printf( "SDL: Wiz framebuffer released\n" );
836 #endif /* SDL_VIDEO_DRIVER_PANDORA */
838 /* vi: set ts=4 sw=4 expandtab: */