Search
lxdream.org :: lxdream/src/drivers/video_egl.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/drivers/video_egl.c
changeset 1287:dac8f363f1fe
prev1275:83b15705cdde
author nkeynes
date Fri May 29 18:47:05 2015 +1000 (7 years ago)
permissions -rw-r--r--
last change Fix test case
view annotate diff log raw
     1 /**
     2  * $Id$
     3  *
     4  * Window management using EGL.
     5  *
     6  * Copyright (c) 2012 Nathan Keynes.
     7  *
     8  * This program is free software; you can redistribute it and/or modify
     9  * it under the terms of the GNU General Public License as published by
    10  * the Free Software Foundation; either version 2 of the License, or
    11  * (at your option) any later version.
    12  *
    13  * This program is distributed in the hope that it will be useful,
    14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    16  * GNU General Public License for more details.
    17  */
    19 #include "lxdream.h"
    20 #include "display.h"
    21 #include "video_egl.h"
    22 #include "video_gl.h"
    23 #include "pvr2/pvr2.h"
    24 #include "pvr2/glutil.h"
    26 static const char *getEGLErrorString( EGLint code )
    27 {
    28     switch( code ) {
    29     case EGL_SUCCESS: return "OK";
    30     case EGL_NOT_INITIALIZED: return "EGL not initialized";
    31     case EGL_BAD_ACCESS: return "Bad access";
    32     case EGL_BAD_ALLOC: return "Allocation failed";
    33     case EGL_BAD_ATTRIBUTE: return "Bad attribute";
    34     case EGL_BAD_CONTEXT: return "Bad context";
    35     case EGL_BAD_CONFIG: return "Bad config";
    36     case EGL_BAD_CURRENT_SURFACE: return "Bad current surface";
    37     case EGL_BAD_DISPLAY: return "Bad display";
    38     case EGL_BAD_MATCH: return "Bad match";
    39     case EGL_BAD_PARAMETER: return "Bad parameter";
    40     case EGL_BAD_NATIVE_PIXMAP: return "Bad native pixmap";
    41     case EGL_BAD_NATIVE_WINDOW: return "Bad native window";
    42     default: return "Unknown error";
    43     }
    44 }
    47 static void logEGLError(const char *msg)
    48 {
    49     EGLint error = eglGetError();
    50     const char *errorStr = getEGLErrorString(error);
    52     ERROR( "%s: %s (%x)", msg, errorStr, error );
    53 }
    55 static const EGLint RGB888_attributes[] = {
    56         EGL_RED_SIZE,       8,
    57         EGL_GREEN_SIZE,     8,
    58         EGL_BLUE_SIZE,      8,
    59         EGL_DEPTH_SIZE,     16,
    60         EGL_STENCIL_SIZE,   8,
    61         EGL_SURFACE_TYPE,   EGL_WINDOW_BIT,
    62         EGL_RENDERABLE_TYPE,EGL_OPENGL_ES2_BIT,
    63         EGL_NONE, EGL_NONE };
    65 static const EGLint RGB565_attributes[] = {
    66         EGL_RED_SIZE,       5,
    67         EGL_GREEN_SIZE,     6,
    68         EGL_BLUE_SIZE,      5,
    69         EGL_DEPTH_SIZE,     16,
    70         EGL_STENCIL_SIZE,   8,
    71         EGL_SURFACE_TYPE,   EGL_WINDOW_BIT,
    72         EGL_RENDERABLE_TYPE,EGL_OPENGL_ES2_BIT,
    73         EGL_NONE, EGL_NONE };
    75 static const EGLint alt_attributes[] = {
    76         EGL_DEPTH_SIZE,     16,
    77         EGL_STENCIL_SIZE,   8,
    78         EGL_SURFACE_TYPE,   EGL_WINDOW_BIT,
    79         EGL_RENDERABLE_TYPE,EGL_OPENGL_ES2_BIT,
    80         EGL_NONE, EGL_NONE };
    82 static const EGLint context_attributes[] = {
    83         EGL_CONTEXT_CLIENT_VERSION, 2,
    84         EGL_NONE, EGL_NONE };
    86 static EGLDisplay display = EGL_NO_DISPLAY;
    87 static EGLContext context = EGL_NO_CONTEXT;
    88 static EGLSurface surface = EGL_NO_SURFACE;
    89 static gboolean fbo_created = FALSE;
    91 static void video_egl_swap_buffers();
    92 static int video_egl_major = 0, video_egl_minor = 0;
    94 gboolean video_egl_init()
    95 {
    96     display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
    97     if( eglInitialize(display, &video_egl_major, &video_egl_minor) != EGL_TRUE ) {
    98         logEGLError( "Unable to initialise EGL display" );
    99         return FALSE;
   100     }
   101     return TRUE;
   102 }
   104 gboolean video_egl_init_context( EGLNativeWindowType window, int format )
   105 {
   106     EGLConfig config;
   107     EGLint num_config;
   108     const EGLint *attribute_list;
   110     if( format == COLFMT_RGB565 || format == COLFMT_BGRA1555 ) {
   111         attribute_list = RGB565_attributes;
   112     } else {
   113         attribute_list = RGB888_attributes;
   114     }
   115     eglChooseConfig(display, attribute_list, &config, 1, &num_config);
   117     surface = eglCreateWindowSurface(display, config, window, NULL);
   118     if( surface == EGL_NO_SURFACE ) {
   119         /* Try alternate config in case of failure. This provides a workaround for
   120          * the Nokia N900 where eglCreateWindowSurface fails when color attributes
   121          * are specified. (bug report: https://bugs.maemo.org/show_bug.cgi?id=9335)
   122          */
   123         eglChooseConfig(display, alt_attributes, &config, 1, &num_config);
   124         surface = eglCreateWindowSurface(display, config, window, NULL);
   126         if( surface == EGL_NO_SURFACE ) {
   127             logEGLError( "Unable to create EGL surface" );
   128             video_egl_shutdown();
   129             return FALSE;
   130         }
   131     }
   133     context = eglCreateContext(display, config, EGL_NO_CONTEXT, context_attributes);
   134     if( context == EGL_NO_CONTEXT ) {
   135         logEGLError( "Unable to create EGL context" );
   136         video_egl_shutdown();
   137         return FALSE;
   138     }
   142     if( eglMakeCurrent( display, surface, surface, context ) == EGL_FALSE ) {
   143         logEGLError( "Unable to make EGL context current" );
   144         video_egl_shutdown();
   145         return FALSE;
   146     }
   148     return TRUE;
   149 }
   151 gboolean video_egl_init_driver( display_driver_t driver )
   152 {
   153     driver->swap_buffers = video_egl_swap_buffers;
   154     driver->capabilities.depth_bits = 16; /* TODO: get from config info */
   155     if( !gl_init_driver(driver, TRUE) ) {
   156         video_egl_shutdown();
   157         return FALSE;
   158     }
   159     fbo_created = TRUE;
   160     return TRUE;
   161 }
   163 void video_egl_shutdown()
   164 {
   165     if( fbo_created ) {
   166         pvr2_shutdown_gl_context();
   167         gl_fbo_shutdown();
   168         fbo_created = FALSE;
   169     }
   170     eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
   171     if( surface != EGL_NO_SURFACE )  {
   172         eglDestroySurface(display, surface);
   173         surface = EGL_NO_SURFACE;
   174     }
   175     if( context != EGL_NO_CONTEXT ) {
   176         eglDestroyContext(display, context);
   177         context = EGL_NO_CONTEXT;
   178     }
   179     if( display != EGL_NO_DISPLAY ) {
   180         eglTerminate(display);
   181         display = EGL_NO_DISPLAY;
   182     }
   183 }
   185 gboolean video_egl_set_window(EGLNativeWindowType window, int width, int height, int format)
   186 {
   187     if( ! video_egl_init() ||
   188             ! video_egl_init_context( window, format ) ||
   189             ! video_egl_init_driver( &display_egl_driver ) ) {
   190         return FALSE;
   191     }
   192     gl_set_video_size(width, height, 0);
   193     pvr2_setup_gl_context();
   194     INFO( "Initialised EGL %d.%d", video_egl_major, video_egl_minor );
   195     return TRUE;
   196 }
   198 void video_egl_clear_window()
   199 {
   200     video_egl_shutdown();
   201     INFO( "Terminated EGL" );
   202 }
   204 static void video_egl_swap_buffers()
   205 {
   206     eglSwapBuffers(display, surface);
   207 }
   210 /**
   211  * Minimal init and shutdown. The real work is done from set_window
   212  */
   213 struct display_driver display_egl_driver = {
   214         "egl", N_("OpenGLES driver"), NULL, NULL,
   215         NULL, NULL, NULL,
   216         NULL, NULL, NULL, NULL,
   217         gl_load_frame_buffer, gl_display_render_buffer, gl_display_blank,
   218         video_egl_swap_buffers, gl_read_render_buffer, NULL, NULL
   219 };
.