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 1256:a9d29fe74bf3
prev1251:b8ab59d39756
next1258:f8a9c0fd2abb
author nkeynes
date Sun Mar 04 21:10:12 2012 +1000 (8 years ago)
permissions -rw-r--r--
last change Move glsl loading into common gl code, and set a display capability flag
file annotate diff log raw
nkeynes@1245
     1
/**
nkeynes@1245
     2
 * $Id$
nkeynes@1245
     3
 *
nkeynes@1245
     4
 * Window management using EGL.
nkeynes@1245
     5
 *
nkeynes@1245
     6
 * Copyright (c) 2012 Nathan Keynes.
nkeynes@1245
     7
 *
nkeynes@1245
     8
 * This program is free software; you can redistribute it and/or modify
nkeynes@1245
     9
 * it under the terms of the GNU General Public License as published by
nkeynes@1245
    10
 * the Free Software Foundation; either version 2 of the License, or
nkeynes@1245
    11
 * (at your option) any later version.
nkeynes@1245
    12
 *
nkeynes@1245
    13
 * This program is distributed in the hope that it will be useful,
nkeynes@1245
    14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
nkeynes@1245
    15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
nkeynes@1245
    16
 * GNU General Public License for more details.
nkeynes@1245
    17
 */
nkeynes@1245
    18
nkeynes@1245
    19
#include "lxdream.h"
nkeynes@1245
    20
#include "display.h"
nkeynes@1245
    21
#include "video_egl.h"
nkeynes@1245
    22
#include "video_gl.h"
nkeynes@1245
    23
#include "pvr2/pvr2.h"
nkeynes@1245
    24
#include "pvr2/glutil.h"
nkeynes@1245
    25
nkeynes@1245
    26
static const char *getEGLErrorString( EGLint code )
nkeynes@1245
    27
{
nkeynes@1245
    28
    switch( code ) {
nkeynes@1245
    29
    case EGL_SUCCESS: return "OK";
nkeynes@1245
    30
    case EGL_NOT_INITIALIZED: return "EGL not initialized";
nkeynes@1245
    31
    case EGL_BAD_ACCESS: return "Bad access";
nkeynes@1245
    32
    case EGL_BAD_ALLOC: return "Allocation failed";
nkeynes@1245
    33
    case EGL_BAD_ATTRIBUTE: return "Bad attribute";
nkeynes@1245
    34
    case EGL_BAD_CONTEXT: return "Bad context";
nkeynes@1245
    35
    case EGL_BAD_CONFIG: return "Bad config";
nkeynes@1245
    36
    case EGL_BAD_CURRENT_SURFACE: return "Bad current surface";
nkeynes@1245
    37
    case EGL_BAD_DISPLAY: return "Bad display";
nkeynes@1245
    38
    case EGL_BAD_MATCH: return "Bad match";
nkeynes@1245
    39
    case EGL_BAD_PARAMETER: return "Bad parameter";
nkeynes@1245
    40
    case EGL_BAD_NATIVE_PIXMAP: return "Bad native pixmap";
nkeynes@1245
    41
    case EGL_BAD_NATIVE_WINDOW: return "Bad native window";
nkeynes@1245
    42
    default: return "Unknown error";
nkeynes@1245
    43
    }
nkeynes@1245
    44
}
nkeynes@1245
    45
nkeynes@1245
    46
nkeynes@1245
    47
static void logEGLError(const char *msg)
nkeynes@1245
    48
{
nkeynes@1245
    49
    EGLint error = eglGetError();
nkeynes@1245
    50
    const char *errorStr = getEGLErrorString(error);
nkeynes@1245
    51
nkeynes@1245
    52
    ERROR( "%s: %s (%x)", msg, errorStr, error );
nkeynes@1245
    53
}
nkeynes@1245
    54
nkeynes@1245
    55
static const EGLint RGB888_attributes[] = {
nkeynes@1245
    56
        EGL_RED_SIZE,       8,
nkeynes@1245
    57
        EGL_GREEN_SIZE,     8,
nkeynes@1245
    58
        EGL_BLUE_SIZE,      8,
nkeynes@1245
    59
        EGL_DEPTH_SIZE,     16,
nkeynes@1245
    60
        EGL_STENCIL_SIZE,   8,
nkeynes@1245
    61
        EGL_SURFACE_TYPE,   EGL_WINDOW_BIT,
nkeynes@1245
    62
        EGL_RENDERABLE_TYPE,EGL_OPENGL_ES2_BIT,
nkeynes@1245
    63
        EGL_NONE, EGL_NONE };
nkeynes@1245
    64
nkeynes@1245
    65
static const EGLint RGB565_attributes[] = {
nkeynes@1245
    66
        EGL_RED_SIZE,       5,
nkeynes@1245
    67
        EGL_GREEN_SIZE,     6,
nkeynes@1245
    68
        EGL_BLUE_SIZE,      5,
nkeynes@1245
    69
        EGL_DEPTH_SIZE,     16,
nkeynes@1245
    70
        EGL_STENCIL_SIZE,   8,
nkeynes@1245
    71
        EGL_SURFACE_TYPE,   EGL_WINDOW_BIT,
nkeynes@1245
    72
        EGL_RENDERABLE_TYPE,EGL_OPENGL_ES2_BIT,
nkeynes@1245
    73
        EGL_NONE, EGL_NONE };
nkeynes@1245
    74
nkeynes@1245
    75
static const EGLint context_attributes[] = {
nkeynes@1245
    76
        EGL_CONTEXT_CLIENT_VERSION, 2,
nkeynes@1245
    77
        EGL_NONE, EGL_NONE };
nkeynes@1245
    78
nkeynes@1245
    79
static EGLDisplay display;
nkeynes@1245
    80
static EGLContext context = EGL_NO_CONTEXT;
nkeynes@1245
    81
static EGLSurface surface = EGL_NO_SURFACE;
nkeynes@1245
    82
static gboolean fbo_created = FALSE;
nkeynes@1245
    83
nkeynes@1245
    84
gboolean video_egl_set_window(EGLNativeWindowType window, int width, int height, int format)
nkeynes@1245
    85
{
nkeynes@1245
    86
    EGLConfig config;
nkeynes@1245
    87
    EGLint num_config, major = 0, minor = 0;
nkeynes@1245
    88
    const EGLint *attribute_list;
nkeynes@1245
    89
nkeynes@1245
    90
    display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
nkeynes@1245
    91
    if( eglInitialize(display, &major, &minor) != EGL_TRUE ) {
nkeynes@1245
    92
        logEGLError( "Unable to initialise EGL display" );
nkeynes@1245
    93
        return FALSE;
nkeynes@1245
    94
    }
nkeynes@1245
    95
nkeynes@1245
    96
    if( format == COLFMT_RGB565 || format == COLFMT_BGRA1555 ) {
nkeynes@1245
    97
        attribute_list = RGB565_attributes;
nkeynes@1245
    98
    } else {
nkeynes@1245
    99
        attribute_list = RGB888_attributes;
nkeynes@1245
   100
    }
nkeynes@1245
   101
nkeynes@1245
   102
nkeynes@1245
   103
    eglChooseConfig(display, attribute_list, &config, 1, &num_config);
nkeynes@1245
   104
nkeynes@1245
   105
    context = eglCreateContext(display, config, EGL_NO_CONTEXT, context_attributes);
nkeynes@1245
   106
    if( context == EGL_NO_CONTEXT ) {
nkeynes@1245
   107
        logEGLError( "Unable to create EGL context" );
nkeynes@1245
   108
        video_egl_clear_window();
nkeynes@1245
   109
        return FALSE;
nkeynes@1245
   110
    }
nkeynes@1245
   111
nkeynes@1245
   112
    surface = eglCreateWindowSurface(display, config, window, NULL);
nkeynes@1245
   113
    if( surface == EGL_NO_SURFACE ) {
nkeynes@1245
   114
        logEGLError( "Unable to create EGL surface" );
nkeynes@1245
   115
        video_egl_clear_window();
nkeynes@1245
   116
        return FALSE;
nkeynes@1245
   117
    }
nkeynes@1245
   118
nkeynes@1245
   119
    if( eglMakeCurrent( display, surface, surface, context ) == EGL_FALSE ) {
nkeynes@1245
   120
        video_egl_clear_window();
nkeynes@1245
   121
        return FALSE;
nkeynes@1245
   122
    }
nkeynes@1245
   123
nkeynes@1245
   124
    if( gl_fbo_is_supported() ) {
nkeynes@1251
   125
        display_egl_driver.capabilities.has_gl = TRUE;
nkeynes@1251
   126
        display_egl_driver.capabilities.depth_bits = 16; /* TODO: get from config info */
nkeynes@1245
   127
        gl_fbo_init(&display_egl_driver);
nkeynes@1245
   128
        gl_vbo_init(&display_egl_driver);
nkeynes@1256
   129
        glsl_init(&display_egl_driver);
nkeynes@1245
   130
        fbo_created = TRUE;
nkeynes@1245
   131
    } else {
nkeynes@1245
   132
        ERROR( "Display does not support FBO" );
nkeynes@1245
   133
        video_egl_clear_window();
nkeynes@1245
   134
        return FALSE;
nkeynes@1245
   135
    }
nkeynes@1251
   136
    gl_set_video_size(width, height, 0);
nkeynes@1245
   137
    pvr2_setup_gl_context();
nkeynes@1245
   138
    INFO( "Initialised EGL %d.%d\n", major, minor );
nkeynes@1245
   139
    return TRUE;
nkeynes@1245
   140
}
nkeynes@1245
   141
nkeynes@1245
   142
void video_egl_clear_window()
nkeynes@1245
   143
{
nkeynes@1245
   144
    if( fbo_created ) {
nkeynes@1245
   145
        gl_fbo_shutdown();
nkeynes@1245
   146
        fbo_created = FALSE;
nkeynes@1245
   147
    }
nkeynes@1245
   148
    eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
nkeynes@1245
   149
    if( surface != EGL_NO_SURFACE )  {
nkeynes@1245
   150
        eglDestroySurface(display, surface);
nkeynes@1245
   151
        surface = EGL_NO_SURFACE;
nkeynes@1245
   152
    }
nkeynes@1245
   153
    if( context != EGL_NO_CONTEXT ) {
nkeynes@1245
   154
        eglDestroyContext(display, context);
nkeynes@1245
   155
        context = EGL_NO_CONTEXT;
nkeynes@1245
   156
    }
nkeynes@1245
   157
    eglTerminate(display);
nkeynes@1245
   158
}
nkeynes@1245
   159
nkeynes@1251
   160
static void video_egl_swap_buffers()
nkeynes@1251
   161
{
nkeynes@1251
   162
    eglSwapBuffers(display, surface);
nkeynes@1251
   163
}
nkeynes@1245
   164
nkeynes@1245
   165
nkeynes@1245
   166
/**
nkeynes@1245
   167
 * Minimal init and shutdown. The real work is done from set_window
nkeynes@1245
   168
 */
nkeynes@1245
   169
struct display_driver display_egl_driver = {
nkeynes@1245
   170
        "egl", N_("OpenGLES driver"), NULL, NULL,
nkeynes@1245
   171
        NULL, NULL, NULL,
nkeynes@1245
   172
        NULL, NULL, NULL, NULL,
nkeynes@1245
   173
        gl_load_frame_buffer, gl_display_render_buffer, gl_display_blank,
nkeynes@1251
   174
        video_egl_swap_buffers, gl_read_render_buffer, NULL, NULL
nkeynes@1245
   175
};
.