src/video/pandora/SDL_pandora.c
changeset 3161 494559cc723b
child 3235 d35b649858e0
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/video/pandora/SDL_pandora.c	Sun May 31 11:53:12 2009 +0000
     1.3 @@ -0,0 +1,858 @@
     1.4 +/*
     1.5 +    SDL - Simple DirectMedia Layer
     1.6 +    Copyright (C) 1997-2009 Sam Lantinga
     1.7 +
     1.8 +    This library is free software; you can redistribute it and/or
     1.9 +    modify it under the terms of the GNU Lesser General Public
    1.10 +    License as published by the Free Software Foundation; either
    1.11 +    version 2.1 of the License, or (at your option) any later version.
    1.12 +
    1.13 +    This library is distributed in the hope that it will be useful,
    1.14 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
    1.15 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    1.16 +    Lesser General Public License for more details.
    1.17 +
    1.18 +    You should have received a copy of the GNU Lesser General Public
    1.19 +    License along with this library; if not, write to the Free Software
    1.20 +    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    1.21 +
    1.22 +    Sam Lantinga
    1.23 +    slouken@libsdl.org
    1.24 +
    1.25 +    Open Pandora SDL driver
    1.26 +    Copyright (C) 2009 David Carré
    1.27 +    (cpasjuste@gmail.com)
    1.28 +*/
    1.29 +
    1.30 +/* SDL internals */
    1.31 +#include "SDL_config.h"
    1.32 +#include "../SDL_sysvideo.h"
    1.33 +#include "SDL_version.h"
    1.34 +#include "SDL_syswm.h"
    1.35 +#include "SDL_loadso.h"
    1.36 +#include "SDL_events.h"
    1.37 +#include "../../events/SDL_mouse_c.h"
    1.38 +#include "../../events/SDL_keyboard_c.h"
    1.39 +
    1.40 +/* PND declarations */
    1.41 +#include "SDL_pandora.h"
    1.42 +#include "SDL_pandora_events.h"
    1.43 +
    1.44 +static SDL_bool PND_initialized = SDL_FALSE;
    1.45 +
    1.46 +static int
    1.47 +PND_available(void)
    1.48 +{
    1.49 +    return 1;
    1.50 +}
    1.51 +
    1.52 +static void
    1.53 +PND_destroy(SDL_VideoDevice * device)
    1.54 +{
    1.55 +    SDL_VideoData *phdata = (SDL_VideoData *) device->driverdata;
    1.56 +
    1.57 +    if (device->driverdata != NULL) {
    1.58 +        device->driverdata = NULL;
    1.59 +    }
    1.60 +}
    1.61 +
    1.62 +static SDL_VideoDevice *
    1.63 +PND_create()
    1.64 +{
    1.65 +    SDL_VideoDevice *device;
    1.66 +    SDL_VideoData *phdata;
    1.67 +    int status;
    1.68 +
    1.69 +    /* Check if pandora could be initialized */
    1.70 +    status = PND_available();
    1.71 +    if (status == 0) {
    1.72 +        /* PND could not be used */
    1.73 +        return NULL;
    1.74 +    }
    1.75 +
    1.76 +    /* Initialize SDL_VideoDevice structure */
    1.77 +    device = (SDL_VideoDevice *) SDL_calloc(1, sizeof(SDL_VideoDevice));
    1.78 +    if (device == NULL) {
    1.79 +        SDL_OutOfMemory();
    1.80 +        return NULL;
    1.81 +    }
    1.82 +
    1.83 +    /* Initialize internal Pandora specific data */
    1.84 +    phdata = (SDL_VideoData *) SDL_calloc(1, sizeof(SDL_VideoData));
    1.85 +    if (phdata == NULL) {
    1.86 +        SDL_OutOfMemory();
    1.87 +        SDL_free(device);
    1.88 +        return NULL;
    1.89 +    }
    1.90 +
    1.91 +    device->driverdata = phdata;
    1.92 +
    1.93 +    phdata->egl_initialized = SDL_TRUE;
    1.94 +
    1.95 +
    1.96 +    /* Setup amount of available displays and current display */
    1.97 +    device->num_displays = 1;
    1.98 +    device->current_display = 1;
    1.99 +
   1.100 +    /* Set device free function */
   1.101 +    device->free = PND_destroy;
   1.102 +
   1.103 +    /* Setup all functions which we can handle */
   1.104 +    device->VideoInit = PND_videoinit;
   1.105 +    device->VideoQuit = PND_videoquit;
   1.106 +    device->GetDisplayModes = PND_getdisplaymodes;
   1.107 +    device->SetDisplayMode = PND_setdisplaymode;
   1.108 +    device->SetDisplayPalette = PND_setdisplaypalette;
   1.109 +    device->GetDisplayPalette = PND_getdisplaypalette;
   1.110 +    device->SetDisplayGammaRamp = PND_setdisplaygammaramp;
   1.111 +    device->GetDisplayGammaRamp = PND_getdisplaygammaramp;
   1.112 +    device->CreateWindow = PND_createwindow;
   1.113 +    device->CreateWindowFrom = PND_createwindowfrom;
   1.114 +    device->SetWindowTitle = PND_setwindowtitle;
   1.115 +    device->SetWindowIcon = PND_setwindowicon;
   1.116 +    device->SetWindowPosition = PND_setwindowposition;
   1.117 +    device->SetWindowSize = PND_setwindowsize;
   1.118 +    device->ShowWindow = PND_showwindow;
   1.119 +    device->HideWindow = PND_hidewindow;
   1.120 +    device->RaiseWindow = PND_raisewindow;
   1.121 +    device->MaximizeWindow = PND_maximizewindow;
   1.122 +    device->MinimizeWindow = PND_minimizewindow;
   1.123 +    device->RestoreWindow = PND_restorewindow;
   1.124 +    device->SetWindowGrab = PND_setwindowgrab;
   1.125 +    device->DestroyWindow = PND_destroywindow;
   1.126 +    device->GetWindowWMInfo = PND_getwindowwminfo;
   1.127 +    device->GL_LoadLibrary = PND_gl_loadlibrary;
   1.128 +    device->GL_GetProcAddress = PND_gl_getprocaddres;
   1.129 +    device->GL_UnloadLibrary = PND_gl_unloadlibrary;
   1.130 +    device->GL_CreateContext = PND_gl_createcontext;
   1.131 +    device->GL_MakeCurrent = PND_gl_makecurrent;
   1.132 +    device->GL_SetSwapInterval = PND_gl_setswapinterval;
   1.133 +    device->GL_GetSwapInterval = PND_gl_getswapinterval;
   1.134 +    device->GL_SwapWindow = PND_gl_swapwindow;
   1.135 +    device->GL_DeleteContext = PND_gl_deletecontext;
   1.136 +    device->PumpEvents = PND_PumpEvents;
   1.137 +
   1.138 +    return device;
   1.139 +}
   1.140 +
   1.141 +VideoBootStrap PND_bootstrap = {
   1.142 +    "pandora",
   1.143 +    "SDL Pandora Video Driver",
   1.144 +    PND_available,
   1.145 +    PND_create
   1.146 +};
   1.147 +
   1.148 +/*****************************************************************************/
   1.149 +/* SDL Video and Display initialization/handling functions                   */
   1.150 +/*****************************************************************************/
   1.151 +int
   1.152 +PND_videoinit(_THIS)
   1.153 +{
   1.154 +    SDL_VideoDisplay display;
   1.155 +    SDL_DisplayMode current_mode;
   1.156 +
   1.157 +    SDL_zero(current_mode);
   1.158 +    current_mode.w = 800;
   1.159 +    current_mode.h = 480;
   1.160 +    current_mode.refresh_rate = 60;
   1.161 +    current_mode.format = SDL_PIXELFORMAT_RGB565;
   1.162 +    current_mode.driverdata = NULL;
   1.163 +
   1.164 +    SDL_zero(display);
   1.165 +    display.desktop_mode = current_mode;
   1.166 +    display.current_mode = current_mode;
   1.167 +    display.driverdata = NULL;
   1.168 +
   1.169 +    SDL_AddVideoDisplay(&display);
   1.170 +
   1.171 +    return 1;
   1.172 +}
   1.173 +
   1.174 +void
   1.175 +PND_videoquit(_THIS)
   1.176 +{
   1.177 +
   1.178 +}
   1.179 +
   1.180 +void
   1.181 +PND_getdisplaymodes(_THIS)
   1.182 +{
   1.183 +
   1.184 +}
   1.185 +
   1.186 +int
   1.187 +PND_setdisplaymode(_THIS, SDL_DisplayMode * mode)
   1.188 +{
   1.189 +    return 0;
   1.190 +}
   1.191 +
   1.192 +int
   1.193 +PND_setdisplaypalette(_THIS, SDL_Palette * palette)
   1.194 +{
   1.195 +    SDL_DisplayData *didata =
   1.196 +        (SDL_DisplayData *) SDL_CurrentDisplay.driverdata;
   1.197 +
   1.198 +    /* Setting display palette operation has been failed */
   1.199 +    return -1;
   1.200 +}
   1.201 +
   1.202 +int
   1.203 +PND_getdisplaypalette(_THIS, SDL_Palette * palette)
   1.204 +{
   1.205 +    SDL_DisplayData *didata =
   1.206 +        (SDL_DisplayData *) SDL_CurrentDisplay.driverdata;
   1.207 +
   1.208 +    /* Getting display palette operation has been failed */
   1.209 +    return -1;
   1.210 +}
   1.211 +
   1.212 +int
   1.213 +PND_setdisplaygammaramp(_THIS, Uint16 * ramp)
   1.214 +{
   1.215 +    SDL_DisplayData *didata =
   1.216 +        (SDL_DisplayData *) SDL_CurrentDisplay.driverdata;
   1.217 +
   1.218 +    /* Setting display gamma ramp operation has been failed */
   1.219 +    return -1;
   1.220 +}
   1.221 +
   1.222 +int
   1.223 +PND_getdisplaygammaramp(_THIS, Uint16 * ramp)
   1.224 +{
   1.225 +    /* Getting display gamma ramp operation has been failed */
   1.226 +    return -1;
   1.227 +}
   1.228 +
   1.229 +int
   1.230 +PND_createwindow(_THIS, SDL_Window * window)
   1.231 +{
   1.232 +    SDL_VideoData *phdata = (SDL_VideoData *) _this->driverdata;
   1.233 +
   1.234 +    SDL_WindowData *wdata;
   1.235 +
   1.236 +    uint32_t winargc = 0;
   1.237 +    int32_t status;
   1.238 +
   1.239 +
   1.240 +    /* Allocate window internal data */
   1.241 +    wdata = (SDL_WindowData *) SDL_calloc(1, sizeof(SDL_WindowData));
   1.242 +    if (wdata == NULL) {
   1.243 +        SDL_OutOfMemory();
   1.244 +        return -1;
   1.245 +    }
   1.246 +
   1.247 +    /* Setup driver data for this window */
   1.248 +    window->driverdata = wdata;
   1.249 +
   1.250 +    /* Check if window must support OpenGL ES rendering */
   1.251 +    if ((window->flags & SDL_WINDOW_OPENGL) == SDL_WINDOW_OPENGL) {
   1.252 +
   1.253 +        EGLBoolean initstatus;
   1.254 +
   1.255 +        /* Mark this window as OpenGL ES compatible */
   1.256 +        wdata->uses_gles = SDL_TRUE;
   1.257 +
   1.258 +        /* Create connection to OpenGL ES */
   1.259 +        if (phdata->egl_display == EGL_NO_DISPLAY) {
   1.260 +            phdata->egl_display = eglGetDisplay((NativeDisplayType) 0);
   1.261 +            if (phdata->egl_display == EGL_NO_DISPLAY) {
   1.262 +                SDL_SetError("PND: Can't get connection to OpenGL ES");
   1.263 +                return -1;
   1.264 +            }
   1.265 +
   1.266 +            initstatus = eglInitialize(phdata->egl_display, NULL, NULL);
   1.267 +            if (initstatus != EGL_TRUE) {
   1.268 +                SDL_SetError("PND: Can't init OpenGL ES library");
   1.269 +                return -1;
   1.270 +            }
   1.271 +        }
   1.272 +
   1.273 +        phdata->egl_refcount++;
   1.274 +    }
   1.275 +
   1.276 +    /* Window has been successfully created */
   1.277 +    return 0;
   1.278 +}
   1.279 +
   1.280 +int
   1.281 +PND_createwindowfrom(_THIS, SDL_Window * window, const void *data)
   1.282 +{
   1.283 +    return -1;
   1.284 +}
   1.285 +
   1.286 +void
   1.287 +PND_setwindowtitle(_THIS, SDL_Window * window)
   1.288 +{
   1.289 +}
   1.290 +void
   1.291 +PND_setwindowicon(_THIS, SDL_Window * window, SDL_Surface * icon)
   1.292 +{
   1.293 +}
   1.294 +void
   1.295 +PND_setwindowposition(_THIS, SDL_Window * window)
   1.296 +{
   1.297 +}
   1.298 +void
   1.299 +PND_setwindowsize(_THIS, SDL_Window * window)
   1.300 +{
   1.301 +}
   1.302 +void
   1.303 +PND_showwindow(_THIS, SDL_Window * window)
   1.304 +{
   1.305 +}
   1.306 +void
   1.307 +PND_hidewindow(_THIS, SDL_Window * window)
   1.308 +{
   1.309 +}
   1.310 +void
   1.311 +PND_raisewindow(_THIS, SDL_Window * window)
   1.312 +{
   1.313 +}
   1.314 +void
   1.315 +PND_maximizewindow(_THIS, SDL_Window * window)
   1.316 +{
   1.317 +}
   1.318 +void
   1.319 +PND_minimizewindow(_THIS, SDL_Window * window)
   1.320 +{
   1.321 +}
   1.322 +void
   1.323 +PND_restorewindow(_THIS, SDL_Window * window)
   1.324 +{
   1.325 +}
   1.326 +void
   1.327 +PND_setwindowgrab(_THIS, SDL_Window * window)
   1.328 +{
   1.329 +}
   1.330 +void
   1.331 +PND_destroywindow(_THIS, SDL_Window * window)
   1.332 +{
   1.333 +}
   1.334 +
   1.335 +/*****************************************************************************/
   1.336 +/* SDL Window Manager function                                               */
   1.337 +/*****************************************************************************/
   1.338 +SDL_bool
   1.339 +PND_getwindowwminfo(_THIS, SDL_Window * window, struct SDL_SysWMinfo *info)
   1.340 +{
   1.341 +    if (info->version.major <= SDL_MAJOR_VERSION) {
   1.342 +        return SDL_TRUE;
   1.343 +    } else {
   1.344 +        SDL_SetError("application not compiled with SDL %d.%d\n",
   1.345 +                     SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
   1.346 +        return SDL_FALSE;
   1.347 +    }
   1.348 +
   1.349 +    /* Failed to get window manager information */
   1.350 +    return SDL_FALSE;
   1.351 +}
   1.352 +
   1.353 +/*****************************************************************************/
   1.354 +/* SDL OpenGL/OpenGL ES functions                                            */
   1.355 +/*****************************************************************************/
   1.356 +int
   1.357 +PND_gl_loadlibrary(_THIS, const char *path)
   1.358 +{
   1.359 +    SDL_VideoData *phdata = (SDL_VideoData *) _this->driverdata;
   1.360 +
   1.361 +    /* Check if OpenGL ES library is specified for GF driver */
   1.362 +    if (path == NULL) {
   1.363 +        path = SDL_getenv("SDL_OPENGL_LIBRARY");
   1.364 +        if (path == NULL) {
   1.365 +            path = SDL_getenv("SDL_OPENGLES_LIBRARY");
   1.366 +        }
   1.367 +    }
   1.368 +
   1.369 +    /* Check if default library loading requested */
   1.370 +    if (path == NULL) {
   1.371 +        /* Already linked with GF library which provides egl* subset of  */
   1.372 +        /* functions, use Common profile of OpenGL ES library by default */
   1.373 +        path = "/usr/lib/libGLES_CM.so";
   1.374 +    }
   1.375 +
   1.376 +    /* Load dynamic library */
   1.377 +    _this->gl_config.dll_handle = SDL_LoadObject(path);
   1.378 +    if (!_this->gl_config.dll_handle) {
   1.379 +        /* Failed to load new GL ES library */
   1.380 +        SDL_SetError("PND: Failed to locate OpenGL ES library");
   1.381 +        return -1;
   1.382 +    }
   1.383 +
   1.384 +    /* Store OpenGL ES library path and name */
   1.385 +    SDL_strlcpy(_this->gl_config.driver_path, path,
   1.386 +                SDL_arraysize(_this->gl_config.driver_path));
   1.387 +
   1.388 +    /* New OpenGL ES library is loaded */
   1.389 +    return 0;
   1.390 +}
   1.391 +
   1.392 +void *
   1.393 +PND_gl_getprocaddres(_THIS, const char *proc)
   1.394 +{
   1.395 +    SDL_VideoData *phdata = (SDL_VideoData *) _this->driverdata;
   1.396 +    void *function_address;
   1.397 +
   1.398 +    /* Try to get function address through the egl interface */
   1.399 +    function_address = eglGetProcAddress(proc);
   1.400 +    if (function_address != NULL) {
   1.401 +        return function_address;
   1.402 +    }
   1.403 +
   1.404 +    /* Then try to get function in the OpenGL ES library */
   1.405 +    if (_this->gl_config.dll_handle) {
   1.406 +        function_address =
   1.407 +            SDL_LoadFunction(_this->gl_config.dll_handle, proc);
   1.408 +        if (function_address != NULL) {
   1.409 +            return function_address;
   1.410 +        }
   1.411 +    }
   1.412 +
   1.413 +    /* Failed to get GL ES function address pointer */
   1.414 +    SDL_SetError("PND: Cannot locate OpenGL ES function name");
   1.415 +    return NULL;
   1.416 +}
   1.417 +
   1.418 +void
   1.419 +PND_gl_unloadlibrary(_THIS)
   1.420 +{
   1.421 +    SDL_VideoData *phdata = (SDL_VideoData *) _this->driverdata;
   1.422 +
   1.423 +    if (phdata->egl_initialized == SDL_TRUE) {
   1.424 +        /* Unload OpenGL ES library */
   1.425 +        if (_this->gl_config.dll_handle) {
   1.426 +            SDL_UnloadObject(_this->gl_config.dll_handle);
   1.427 +            _this->gl_config.dll_handle = NULL;
   1.428 +        }
   1.429 +    } else {
   1.430 +        SDL_SetError("PND: GF initialization failed, no OpenGL ES support");
   1.431 +    }
   1.432 +}
   1.433 +
   1.434 +SDL_GLContext
   1.435 +PND_gl_createcontext(_THIS, SDL_Window * window)
   1.436 +{
   1.437 +    SDL_VideoData *phdata = (SDL_VideoData *) _this->driverdata;
   1.438 +    SDL_WindowData *wdata = (SDL_WindowData *) window->driverdata;
   1.439 +    SDL_DisplayData *didata =
   1.440 +        (SDL_DisplayData *) SDL_CurrentDisplay.driverdata;
   1.441 +    EGLBoolean status;
   1.442 +    int32_t gfstatus;
   1.443 +    EGLint configs;
   1.444 +    uint32_t attr_pos;
   1.445 +    EGLint attr_value;
   1.446 +    EGLint cit;
   1.447 +
   1.448 +    /* Check if EGL was initialized */
   1.449 +    if (phdata->egl_initialized != SDL_TRUE) {
   1.450 +        SDL_SetError("PND: EGL initialization failed, no OpenGL ES support");
   1.451 +        return NULL;
   1.452 +    }
   1.453 +
   1.454 +    /* Prepare attributes list to pass them to OpenGL ES */
   1.455 +    attr_pos = 0;
   1.456 +    wdata->gles_attributes[attr_pos++] = EGL_SURFACE_TYPE;
   1.457 +    wdata->gles_attributes[attr_pos++] = EGL_WINDOW_BIT;
   1.458 +    wdata->gles_attributes[attr_pos++] = EGL_RED_SIZE;
   1.459 +    wdata->gles_attributes[attr_pos++] = _this->gl_config.red_size;
   1.460 +    wdata->gles_attributes[attr_pos++] = EGL_GREEN_SIZE;
   1.461 +    wdata->gles_attributes[attr_pos++] = _this->gl_config.green_size;
   1.462 +    wdata->gles_attributes[attr_pos++] = EGL_BLUE_SIZE;
   1.463 +    wdata->gles_attributes[attr_pos++] = _this->gl_config.blue_size;
   1.464 +    wdata->gles_attributes[attr_pos++] = EGL_ALPHA_SIZE;
   1.465 +
   1.466 +    /* Setup alpha size in bits */
   1.467 +    if (_this->gl_config.alpha_size) {
   1.468 +        wdata->gles_attributes[attr_pos++] = _this->gl_config.alpha_size;
   1.469 +    } else {
   1.470 +        wdata->gles_attributes[attr_pos++] = EGL_DONT_CARE;
   1.471 +    }
   1.472 +
   1.473 +    /* Setup color buffer size */
   1.474 +    if (_this->gl_config.buffer_size) {
   1.475 +        wdata->gles_attributes[attr_pos++] = EGL_BUFFER_SIZE;
   1.476 +        wdata->gles_attributes[attr_pos++] = _this->gl_config.buffer_size;
   1.477 +    } else {
   1.478 +        wdata->gles_attributes[attr_pos++] = EGL_BUFFER_SIZE;
   1.479 +        wdata->gles_attributes[attr_pos++] = EGL_DONT_CARE;
   1.480 +    }
   1.481 +
   1.482 +    /* Setup depth buffer bits */
   1.483 +    wdata->gles_attributes[attr_pos++] = EGL_DEPTH_SIZE;
   1.484 +    wdata->gles_attributes[attr_pos++] = _this->gl_config.depth_size;
   1.485 +
   1.486 +    /* Setup stencil bits */
   1.487 +    if (_this->gl_config.stencil_size) {
   1.488 +        wdata->gles_attributes[attr_pos++] = EGL_STENCIL_SIZE;
   1.489 +        wdata->gles_attributes[attr_pos++] = _this->gl_config.buffer_size;
   1.490 +    } else {
   1.491 +        wdata->gles_attributes[attr_pos++] = EGL_STENCIL_SIZE;
   1.492 +        wdata->gles_attributes[attr_pos++] = EGL_DONT_CARE;
   1.493 +    }
   1.494 +
   1.495 +    /* Set number of samples in multisampling */
   1.496 +    if (_this->gl_config.multisamplesamples) {
   1.497 +        wdata->gles_attributes[attr_pos++] = EGL_SAMPLES;
   1.498 +        wdata->gles_attributes[attr_pos++] =
   1.499 +            _this->gl_config.multisamplesamples;
   1.500 +    }
   1.501 +
   1.502 +    /* Multisample buffers, OpenGL ES 1.0 spec defines 0 or 1 buffer */
   1.503 +    if (_this->gl_config.multisamplebuffers) {
   1.504 +        wdata->gles_attributes[attr_pos++] = EGL_SAMPLE_BUFFERS;
   1.505 +        wdata->gles_attributes[attr_pos++] =
   1.506 +            _this->gl_config.multisamplebuffers;
   1.507 +    }
   1.508 +
   1.509 +    /* Finish attributes list */
   1.510 +    wdata->gles_attributes[attr_pos] = EGL_NONE;
   1.511 +
   1.512 +    /* Request first suitable framebuffer configuration */
   1.513 +    status = eglChooseConfig(phdata->egl_display, wdata->gles_attributes,
   1.514 +                             wdata->gles_configs, 1, &configs);
   1.515 +    if (status != EGL_TRUE) {
   1.516 +        SDL_SetError("PND: Can't find closest configuration for OpenGL ES");
   1.517 +        return NULL;
   1.518 +    }
   1.519 +
   1.520 +    /* Check if nothing has been found, try "don't care" settings */
   1.521 +    if (configs == 0) {
   1.522 +        int32_t it;
   1.523 +        int32_t jt;
   1.524 +        GLint depthbits[4] = { 32, 24, 16, EGL_DONT_CARE };
   1.525 +
   1.526 +        for (it = 0; it < 4; it++) {
   1.527 +            for (jt = 16; jt >= 0; jt--) {
   1.528 +                /* Don't care about color buffer bits, use what exist */
   1.529 +                /* Replace previous set data with EGL_DONT_CARE       */
   1.530 +                attr_pos = 0;
   1.531 +                wdata->gles_attributes[attr_pos++] = EGL_SURFACE_TYPE;
   1.532 +                wdata->gles_attributes[attr_pos++] = EGL_WINDOW_BIT;
   1.533 +                wdata->gles_attributes[attr_pos++] = EGL_RED_SIZE;
   1.534 +                wdata->gles_attributes[attr_pos++] = EGL_DONT_CARE;
   1.535 +                wdata->gles_attributes[attr_pos++] = EGL_GREEN_SIZE;
   1.536 +                wdata->gles_attributes[attr_pos++] = EGL_DONT_CARE;
   1.537 +                wdata->gles_attributes[attr_pos++] = EGL_BLUE_SIZE;
   1.538 +                wdata->gles_attributes[attr_pos++] = EGL_DONT_CARE;
   1.539 +                wdata->gles_attributes[attr_pos++] = EGL_ALPHA_SIZE;
   1.540 +                wdata->gles_attributes[attr_pos++] = EGL_DONT_CARE;
   1.541 +                wdata->gles_attributes[attr_pos++] = EGL_BUFFER_SIZE;
   1.542 +                wdata->gles_attributes[attr_pos++] = EGL_DONT_CARE;
   1.543 +
   1.544 +                /* Try to find requested or smallest depth */
   1.545 +                if (_this->gl_config.depth_size) {
   1.546 +                    wdata->gles_attributes[attr_pos++] = EGL_DEPTH_SIZE;
   1.547 +                    wdata->gles_attributes[attr_pos++] = depthbits[it];
   1.548 +                } else {
   1.549 +                    wdata->gles_attributes[attr_pos++] = EGL_DEPTH_SIZE;
   1.550 +                    wdata->gles_attributes[attr_pos++] = EGL_DONT_CARE;
   1.551 +                }
   1.552 +
   1.553 +                if (_this->gl_config.stencil_size) {
   1.554 +                    wdata->gles_attributes[attr_pos++] = EGL_STENCIL_SIZE;
   1.555 +                    wdata->gles_attributes[attr_pos++] = jt;
   1.556 +                } else {
   1.557 +                    wdata->gles_attributes[attr_pos++] = EGL_STENCIL_SIZE;
   1.558 +                    wdata->gles_attributes[attr_pos++] = EGL_DONT_CARE;
   1.559 +                }
   1.560 +
   1.561 +                wdata->gles_attributes[attr_pos++] = EGL_SAMPLES;
   1.562 +                wdata->gles_attributes[attr_pos++] = EGL_DONT_CARE;
   1.563 +                wdata->gles_attributes[attr_pos++] = EGL_SAMPLE_BUFFERS;
   1.564 +                wdata->gles_attributes[attr_pos++] = EGL_DONT_CARE;
   1.565 +                wdata->gles_attributes[attr_pos] = EGL_NONE;
   1.566 +
   1.567 +                /* Request first suitable framebuffer configuration */
   1.568 +                status =
   1.569 +                    eglChooseConfig(phdata->egl_display,
   1.570 +                                    wdata->gles_attributes,
   1.571 +                                    wdata->gles_configs, 1, &configs);
   1.572 +
   1.573 +                if (status != EGL_TRUE) {
   1.574 +                    SDL_SetError
   1.575 +                        ("PND: Can't find closest configuration for OpenGL ES");
   1.576 +                    return NULL;
   1.577 +                }
   1.578 +                if (configs != 0) {
   1.579 +                    break;
   1.580 +                }
   1.581 +            }
   1.582 +            if (configs != 0) {
   1.583 +                break;
   1.584 +            }
   1.585 +        }
   1.586 +
   1.587 +        /* No available configs */
   1.588 +        if (configs == 0) {
   1.589 +            SDL_SetError("PND: Can't find any configuration for OpenGL ES");
   1.590 +            return NULL;
   1.591 +        }
   1.592 +    }
   1.593 +
   1.594 +    /* Initialize config index */
   1.595 +    wdata->gles_config = 0;
   1.596 +
   1.597 +    /* Now check each configuration to find out the best */
   1.598 +    for (cit = 0; cit < configs; cit++) {
   1.599 +        uint32_t stencil_found;
   1.600 +        uint32_t depth_found;
   1.601 +
   1.602 +        stencil_found = 0;
   1.603 +        depth_found = 0;
   1.604 +
   1.605 +        if (_this->gl_config.stencil_size) {
   1.606 +            status =
   1.607 +                eglGetConfigAttrib(phdata->egl_display,
   1.608 +                                   wdata->gles_configs[cit], EGL_STENCIL_SIZE,
   1.609 +                                   &attr_value);
   1.610 +            if (status == EGL_TRUE) {
   1.611 +                if (attr_value != 0) {
   1.612 +                    stencil_found = 1;
   1.613 +                }
   1.614 +            }
   1.615 +        } else {
   1.616 +            stencil_found = 1;
   1.617 +        }
   1.618 +
   1.619 +        if (_this->gl_config.depth_size) {
   1.620 +            status =
   1.621 +                eglGetConfigAttrib(phdata->egl_display,
   1.622 +                                   wdata->gles_configs[cit], EGL_DEPTH_SIZE,
   1.623 +                                   &attr_value);
   1.624 +            if (status == EGL_TRUE) {
   1.625 +                if (attr_value != 0) {
   1.626 +                    depth_found = 1;
   1.627 +                }
   1.628 +            }
   1.629 +        } else {
   1.630 +            depth_found = 1;
   1.631 +        }
   1.632 +
   1.633 +        /* Exit from loop if found appropriate configuration */
   1.634 +        if ((depth_found != 0) && (stencil_found != 0)) {
   1.635 +            break;
   1.636 +        }
   1.637 +    }
   1.638 +
   1.639 +    /* If best could not be found, use first */
   1.640 +    if (cit == configs) {
   1.641 +        cit = 0;
   1.642 +    }
   1.643 +    wdata->gles_config = cit;
   1.644 +
   1.645 +    /* Create OpenGL ES context */
   1.646 +    wdata->gles_context =
   1.647 +        eglCreateContext(phdata->egl_display,
   1.648 +                         wdata->gles_configs[wdata->gles_config], NULL, NULL);
   1.649 +    if (wdata->gles_context == EGL_NO_CONTEXT) {
   1.650 +        SDL_SetError("PND: OpenGL ES context creation has been failed");
   1.651 +        return NULL;
   1.652 +    }
   1.653 +
   1.654 +    wdata->gles_surface =
   1.655 +        eglCreateWindowSurface(phdata->egl_display,
   1.656 +                               wdata->gles_configs[wdata->gles_config],
   1.657 +                               (NativeWindowType) 0, NULL);
   1.658 +    if (wdata->gles_surface == 0) {
   1.659 +        SDL_SetError("Error : eglCreateWindowSurface failed;\n");
   1.660 +        return NULL;
   1.661 +    }
   1.662 +
   1.663 +    /* Make just created context current */
   1.664 +    status =
   1.665 +        eglMakeCurrent(phdata->egl_display, wdata->gles_surface,
   1.666 +                       wdata->gles_surface, wdata->gles_context);
   1.667 +    if (status != EGL_TRUE) {
   1.668 +        /* Destroy OpenGL ES surface */
   1.669 +        eglDestroySurface(phdata->egl_display, wdata->gles_surface);
   1.670 +        eglDestroyContext(phdata->egl_display, wdata->gles_context);
   1.671 +        wdata->gles_context = EGL_NO_CONTEXT;
   1.672 +        SDL_SetError("PND: Can't set OpenGL ES context on creation");
   1.673 +        return NULL;
   1.674 +    }
   1.675 +
   1.676 +    _this->gl_config.accelerated = 1;
   1.677 +
   1.678 +    /* Always clear stereo enable, since OpenGL ES do not supports stereo */
   1.679 +    _this->gl_config.stereo = 0;
   1.680 +
   1.681 +    /* Get back samples and samplebuffers configurations. Rest framebuffer */
   1.682 +    /* parameters could be obtained through the OpenGL ES API              */
   1.683 +    status =
   1.684 +        eglGetConfigAttrib(phdata->egl_display,
   1.685 +                           wdata->gles_configs[wdata->gles_config],
   1.686 +                           EGL_SAMPLES, &attr_value);
   1.687 +    if (status == EGL_TRUE) {
   1.688 +        _this->gl_config.multisamplesamples = attr_value;
   1.689 +    }
   1.690 +    status =
   1.691 +        eglGetConfigAttrib(phdata->egl_display,
   1.692 +                           wdata->gles_configs[wdata->gles_config],
   1.693 +                           EGL_SAMPLE_BUFFERS, &attr_value);
   1.694 +    if (status == EGL_TRUE) {
   1.695 +        _this->gl_config.multisamplebuffers = attr_value;
   1.696 +    }
   1.697 +
   1.698 +    /* Get back stencil and depth buffer sizes */
   1.699 +    status =
   1.700 +        eglGetConfigAttrib(phdata->egl_display,
   1.701 +                           wdata->gles_configs[wdata->gles_config],
   1.702 +                           EGL_DEPTH_SIZE, &attr_value);
   1.703 +    if (status == EGL_TRUE) {
   1.704 +        _this->gl_config.depth_size = attr_value;
   1.705 +    }
   1.706 +    status =
   1.707 +        eglGetConfigAttrib(phdata->egl_display,
   1.708 +                           wdata->gles_configs[wdata->gles_config],
   1.709 +                           EGL_STENCIL_SIZE, &attr_value);
   1.710 +    if (status == EGL_TRUE) {
   1.711 +        _this->gl_config.stencil_size = attr_value;
   1.712 +    }
   1.713 +
   1.714 +    /* Under PND OpenGL ES output can't be double buffered */
   1.715 +    _this->gl_config.double_buffer = 0;
   1.716 +
   1.717 +    /* GL ES context was successfully created */
   1.718 +    return wdata->gles_context;
   1.719 +}
   1.720 +
   1.721 +int
   1.722 +PND_gl_makecurrent(_THIS, SDL_Window * window, SDL_GLContext context)
   1.723 +{
   1.724 +    SDL_VideoData *phdata = (SDL_VideoData *) _this->driverdata;
   1.725 +    SDL_WindowData *wdata;
   1.726 +    EGLBoolean status;
   1.727 +
   1.728 +    if (phdata->egl_initialized != SDL_TRUE) {
   1.729 +        SDL_SetError("PND: GF initialization failed, no OpenGL ES support");
   1.730 +        return -1;
   1.731 +    }
   1.732 +
   1.733 +    if ((window == NULL) && (context == NULL)) {
   1.734 +        status =
   1.735 +            eglMakeCurrent(phdata->egl_display, EGL_NO_SURFACE,
   1.736 +                           EGL_NO_SURFACE, EGL_NO_CONTEXT);
   1.737 +        if (status != EGL_TRUE) {
   1.738 +            /* Failed to set current GL ES context */
   1.739 +            SDL_SetError("PND: Can't set OpenGL ES context");
   1.740 +            return -1;
   1.741 +        }
   1.742 +    } else {
   1.743 +        wdata = (SDL_WindowData *) window->driverdata;
   1.744 +        if (wdata->gles_surface == EGL_NO_SURFACE) {
   1.745 +            SDL_SetError
   1.746 +                ("PND: OpenGL ES surface is not initialized for this window");
   1.747 +            return -1;
   1.748 +        }
   1.749 +        if (wdata->gles_context == EGL_NO_CONTEXT) {
   1.750 +            SDL_SetError
   1.751 +                ("PND: OpenGL ES context is not initialized for this window");
   1.752 +            return -1;
   1.753 +        }
   1.754 +        if (wdata->gles_context != context) {
   1.755 +            SDL_SetError
   1.756 +                ("PND: OpenGL ES context is not belong to this window");
   1.757 +            return -1;
   1.758 +        }
   1.759 +        status =
   1.760 +            eglMakeCurrent(phdata->egl_display, wdata->gles_surface,
   1.761 +                           wdata->gles_surface, wdata->gles_context);
   1.762 +        if (status != EGL_TRUE) {
   1.763 +            /* Failed to set current GL ES context */
   1.764 +            SDL_SetError("PND: Can't set OpenGL ES context");
   1.765 +            return -1;
   1.766 +        }
   1.767 +    }
   1.768 +    return 0;
   1.769 +}
   1.770 +
   1.771 +int
   1.772 +PND_gl_setswapinterval(_THIS, int interval)
   1.773 +{
   1.774 +    SDL_VideoData *phdata = (SDL_VideoData *) _this->driverdata;
   1.775 +    EGLBoolean status;
   1.776 +
   1.777 +    if (phdata->egl_initialized != SDL_TRUE) {
   1.778 +        SDL_SetError("PND: EGL initialization failed, no OpenGL ES support");
   1.779 +        return -1;
   1.780 +    }
   1.781 +
   1.782 +    /* Check if OpenGL ES connection has been initialized */
   1.783 +    if (phdata->egl_display != EGL_NO_DISPLAY) {
   1.784 +        /* Set swap OpenGL ES interval */
   1.785 +        status = eglSwapInterval(phdata->egl_display, interval);
   1.786 +        if (status == EGL_TRUE) {
   1.787 +            /* Return success to upper level */
   1.788 +            phdata->swapinterval = interval;
   1.789 +            return 0;
   1.790 +        }
   1.791 +    }
   1.792 +
   1.793 +    /* Failed to set swap interval */
   1.794 +    SDL_SetError("PND: Cannot set swap interval");
   1.795 +    return -1;
   1.796 +}
   1.797 +
   1.798 +int
   1.799 +PND_gl_getswapinterval(_THIS)
   1.800 +{
   1.801 +    SDL_VideoData *phdata = (SDL_VideoData *) _this->driverdata;
   1.802 +
   1.803 +    if (phdata->egl_initialized != SDL_TRUE) {
   1.804 +        SDL_SetError("PND: GLES initialization failed, no OpenGL ES support");
   1.805 +        return -1;
   1.806 +    }
   1.807 +
   1.808 +    /* Return default swap interval value */
   1.809 +    return phdata->swapinterval;
   1.810 +}
   1.811 +
   1.812 +void
   1.813 +PND_gl_swapwindow(_THIS, SDL_Window * window)
   1.814 +{
   1.815 +    SDL_VideoData *phdata = (SDL_VideoData *) _this->driverdata;
   1.816 +    SDL_WindowData *wdata = (SDL_WindowData *) window->driverdata;
   1.817 +    SDL_DisplayData *didata =
   1.818 +        (SDL_DisplayData *) SDL_CurrentDisplay.driverdata;
   1.819 +
   1.820 +
   1.821 +    if (phdata->egl_initialized != SDL_TRUE) {
   1.822 +        SDL_SetError("PND: GLES initialization failed, no OpenGL ES support");
   1.823 +        return;
   1.824 +    }
   1.825 +
   1.826 +    /* Many applications do not uses glFinish(), so we call it for them */
   1.827 +    glFinish();
   1.828 +
   1.829 +    /* Wait until OpenGL ES rendering is completed */
   1.830 +    eglWaitGL();
   1.831 +
   1.832 +    eglSwapBuffers(phdata->egl_display, wdata->gles_surface);
   1.833 +}
   1.834 +
   1.835 +void
   1.836 +PND_gl_deletecontext(_THIS, SDL_GLContext context)
   1.837 +{
   1.838 +    SDL_VideoData *phdata = (SDL_VideoData *) _this->driverdata;
   1.839 +    EGLBoolean status;
   1.840 +
   1.841 +    if (phdata->egl_initialized != SDL_TRUE) {
   1.842 +        SDL_SetError("PND: GLES initialization failed, no OpenGL ES support");
   1.843 +        return;
   1.844 +    }
   1.845 +
   1.846 +    /* Check if OpenGL ES connection has been initialized */
   1.847 +    if (phdata->egl_display != EGL_NO_DISPLAY) {
   1.848 +        if (context != EGL_NO_CONTEXT) {
   1.849 +            status = eglDestroyContext(phdata->egl_display, context);
   1.850 +            if (status != EGL_TRUE) {
   1.851 +                /* Error during OpenGL ES context destroying */
   1.852 +                SDL_SetError("PND: OpenGL ES context destroy error");
   1.853 +                return;
   1.854 +            }
   1.855 +        }
   1.856 +    }
   1.857 +
   1.858 +    return;
   1.859 +}
   1.860 +
   1.861 +/* vi: set ts=4 sw=4 expandtab: */