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