filename | src/drivers/video_egl.c |
changeset | 1287:dac8f363f1fe |
prev | 1275:83b15705cdde |
author | nkeynes |
date | Sat Jan 26 14:00:48 2013 +1000 (11 years ago) |
permissions | -rw-r--r-- |
last change | Change glib includes to #include <glib.h> rather than the individual headers, as recent glib versions are breaking on this |
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 };
.