src/video/pandora/SDL_pandora.c
author Sam Lantinga <slouken@libsdl.org>
Tue, 11 Aug 2009 13:45:01 +0000
changeset 3235 d35b649858e0
parent 3161 494559cc723b
child 3238 96492d29034a
permissions -rw-r--r--
David Carre to Sam

Hello sam, me again.

I'v fixed another bug in the pandora code, it's on the no-X videodriver, i forgot to add some code to destroy the window so it was impossible to reload SDL inside the same application (eglTerminate).

You'll find the svn diff attached.

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