d07c171f |
1 | /** |
2 | * |
3 | * EGLPORT.C |
4 | * Copyright (C) 2011-2013 Scott R. Smith |
5 | * |
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy |
7 | * of this software and associated documentation files (the "Software"), to deal |
8 | * in the Software without restriction, including without limitation the rights |
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
10 | * copies of the Software, and to permit persons to whom the Software is |
11 | * furnished to do so, subject to the following conditions: |
12 | * |
13 | * The above copyright notice and this permission notice shall be included in |
14 | * all copies or substantial portions of the Software. |
15 | * |
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
22 | * THE SOFTWARE. |
23 | * |
24 | */ |
25 | |
26 | #include "eglport.h" |
27 | |
28 | #include <stdio.h> |
29 | #include <stdlib.h> |
30 | |
31 | #define USE_EGL_SDL 1 |
32 | #define USE_GLES1 1 |
33 | |
34 | #if defined(USE_EGL_SDL) |
35 | #include "SDL.h" |
36 | #include "SDL_syswm.h" |
37 | SDL_SysWMinfo sysWmInfo; /** Holds our X Display/Window information */ |
38 | #endif /* USE_EGL_SDL */ |
39 | |
40 | #if defined(PANDORA) /* Pandora VSync Support */ |
41 | #include <unistd.h> |
42 | #include <fcntl.h> |
43 | #include <sys/ioctl.h> |
44 | #include <linux/fb.h> |
45 | |
46 | #ifndef FBIO_WAITFORVSYNC |
47 | #define FBIO_WAITFORVSYNC _IOW('F', 0x20, __u32) |
48 | #endif |
49 | int fbdev = -1; |
50 | |
51 | #elif defined(RPI) |
52 | #include "bcm_host.h" |
53 | #endif /* PANDORA */ |
54 | |
55 | enum EGL_RENDER_T { |
56 | RENDER_RAW=0, /** Sets render mode to raw or framebuffer mode. */ |
57 | RENDER_SDL, /** Sets render mode to X11/SDL mode. */ |
58 | RENDER_TOTAL |
59 | }; |
60 | |
61 | enum EGL_SETTINGS_T { |
62 | CFG_MODE=0, /** Render mode for EGL 0=RAW 1=SDL. */ |
63 | CFG_VSYNC, /** Controls system vsync if available. */ |
64 | CFG_FSAA, /** Number of samples for full screen AA. 0 is off, 2/4 samples. */ |
65 | CFG_FPS, /** Calculate and report frame per second. */ |
66 | CFG_RED_SIZE, /** Number of bits of Red in the color buffer. */ |
67 | CFG_GREEN_SIZE, /** Number of bits of Green in the color buffer. */ |
68 | CFG_BLUE_SIZE, /** Number of bits of Blue in the color buffer. */ |
69 | CFG_ALPHA_SIZE, /** Number of bits of Alpha in the color buffer. */ |
70 | CFG_DEPTH_SIZE, /** Number of bits of Z in the depth buffer. */ |
71 | CFG_BUFFER_SIZE, /** The total color component bits in the color buffer. */ |
72 | CFG_STENCIL_SIZE, /** Number of bits of Stencil in the stencil buffer. */ |
73 | CFG_TOTAL /** Total number of settings. */ |
74 | }; |
75 | |
76 | NativeDisplayType nativeDisplay = 0; /** Reference to the systems native display */ |
77 | NativeWindowType nativeWindow = 0; /** Reference to the systems native window */ |
78 | EGLint eglSettings[CFG_TOTAL]; /** Stores setting values. */ |
79 | EGLDisplay eglDisplay = NULL; /** Reference to the EGL display */ |
80 | EGLConfig eglConfig = NULL; /** Reference to the EGL config */ |
81 | EGLContext eglContext = NULL; /** Reference to the EGL context */ |
82 | EGLSurface eglSurface = NULL; /** Reference to the EGL surface */ |
83 | |
84 | #define totalConfigsIn 5 /** Total number of configurations to request */ |
85 | EGLint totalConfigsFound = 0; /** Total number of configurations matching attributes */ |
86 | EGLConfig eglConfigs[totalConfigsIn]; /** Structure containing references to matching configurations */ |
87 | |
88 | uint32_t fpsCount = 0; /** Total number of frames counted */ |
89 | uint32_t fpsTime = 0; /** Start time of frame count measurment */ |
90 | |
91 | int8_t eglColorbits = 0; |
92 | int8_t eglDepthbits = 0; |
93 | int8_t eglStencilbits = 0; |
94 | |
95 | |
96 | /** Private API */ |
97 | void OpenCfg ( const char* file ); |
98 | int8_t ConfigureEGL ( EGLConfig config ); |
99 | int8_t FindEGLConfigs ( void ); |
100 | int8_t CheckEGLErrors ( const char* file, uint16_t line ); |
101 | |
102 | int8_t GetNativeDisplay ( void ); |
103 | int8_t GetNativeWindow ( uint16_t width, uint16_t height ); |
104 | void FreeNativeDisplay ( void ); |
105 | void FreeNativeWindow ( void ); |
106 | |
107 | void Platform_Open ( void ); |
108 | void Platform_Close ( void ); |
109 | void Platform_VSync ( void ); |
110 | uint32_t Platform_GetTicks ( void ); |
111 | |
112 | /** @brief Release all EGL and system resources |
113 | */ |
114 | void EGL_Close( void ) |
115 | { |
116 | /* Release EGL resources */ |
117 | if (eglDisplay != NULL) |
118 | { |
119 | peglMakeCurrent( eglDisplay, NULL, NULL, EGL_NO_CONTEXT ); |
120 | if (eglContext != NULL) { |
121 | peglDestroyContext( eglDisplay, eglContext ); |
122 | } |
123 | if (eglSurface != NULL) { |
124 | peglDestroySurface( eglDisplay, eglSurface ); |
125 | } |
126 | peglTerminate( eglDisplay ); |
127 | } |
128 | |
129 | eglSurface = NULL; |
130 | eglContext = NULL; |
131 | eglDisplay = NULL; |
132 | |
133 | eglColorbits = 0; |
134 | eglDepthbits = 0; |
135 | eglStencilbits = 0; |
136 | |
137 | /* Release platform resources */ |
138 | FreeNativeWindow(); |
139 | FreeNativeDisplay(); |
140 | Platform_Close(); |
141 | |
142 | CheckEGLErrors( __FILE__, __LINE__ ); |
143 | |
144 | printf( "EGLport: Closed\n" ); |
145 | } |
146 | |
147 | /** @brief Swap the surface buffer onto the display |
148 | */ |
149 | void EGL_SwapBuffers( void ) |
150 | { |
151 | if (eglSettings[CFG_VSYNC] != 0) { |
152 | Platform_VSync(); |
153 | } |
154 | |
155 | peglSwapBuffers( eglDisplay, eglSurface ); |
156 | |
157 | if (eglSettings[CFG_FPS] != 0) { |
158 | fpsCount++; |
159 | |
160 | if (fpsTime - Platform_GetTicks() >= 1000) |
161 | { |
162 | printf( "EGLport: %d fps\n", fpsCount ); |
163 | fpsTime = Platform_GetTicks(); |
164 | fpsCount = 0; |
165 | } |
166 | } |
167 | } |
168 | |
169 | /** @brief Obtain the system display and initialize EGL |
170 | * @param width : desired pixel width of the window (not used by all platforms) |
171 | * @param height : desired pixel height of the window (not used by all platforms) |
172 | * @return : 0 if the function passed, else 1 |
173 | */ |
174 | int8_t EGL_Open( uint16_t width, uint16_t height ) |
175 | { |
176 | EGLint eglMajorVer, eglMinorVer; |
177 | EGLBoolean result; |
178 | uint32_t configIndex = 0; |
179 | const char* output; |
180 | |
181 | static const EGLint contextAttribs[] = |
182 | { |
183 | #if defined(USE_GLES2) |
184 | EGL_CONTEXT_CLIENT_VERSION, 2, |
185 | #endif |
186 | EGL_NONE |
187 | }; |
188 | |
189 | #if defined(DEBUG) |
190 | printf( "EGLport Warning: DEBUG is enabled which may effect performance\n" ); |
191 | #endif |
192 | |
193 | /* Check that system is not open */ |
194 | if (eglDisplay != NULL || eglContext != NULL || eglSurface != NULL) |
195 | { |
196 | printf( "EGLport ERROR: EGL system is already open!\n" ); |
197 | return 1; |
198 | } |
199 | |
200 | /* Check for the cfg file to alternative settings */ |
201 | OpenCfg( "eglport.cfg" ); |
202 | |
203 | /* Setup any platform specific bits */ |
204 | Platform_Open(); |
205 | |
206 | printf( "EGLport: Opening EGL display\n" ); |
207 | if (GetNativeDisplay() != 0) |
208 | { |
209 | printf( "EGLport ERROR: Unable to obtain native display!\n" ); |
210 | return 1; |
211 | } |
212 | |
213 | eglDisplay = peglGetDisplay( nativeDisplay ); |
214 | if (eglDisplay == EGL_NO_DISPLAY) |
215 | { |
216 | CheckEGLErrors( __FILE__, __LINE__ ); |
217 | printf( "EGLport ERROR: Unable to create EGL display.\n" ); |
218 | return 1; |
219 | } |
220 | |
221 | printf( "EGLport: Initializing\n" ); |
222 | result = peglInitialize( eglDisplay, &eglMajorVer, &eglMinorVer ); |
223 | if (result != EGL_TRUE ) |
224 | { |
225 | CheckEGLErrors( __FILE__, __LINE__ ); |
226 | printf( "EGLport ERROR: Unable to initialize EGL display.\n" ); |
227 | return 1; |
228 | } |
229 | |
230 | /* Get EGL Library Information */ |
231 | printf( "EGL Implementation Version: Major %d Minor %d\n", eglMajorVer, eglMinorVer ); |
232 | output = peglQueryString( eglDisplay, EGL_VENDOR ); |
233 | printf( "EGL_VENDOR: %s\n", output ); |
234 | output = peglQueryString( eglDisplay, EGL_VERSION ); |
235 | printf( "EGL_VERSION: %s\n", output ); |
236 | output = peglQueryString( eglDisplay, EGL_EXTENSIONS ); |
237 | printf( "EGL_EXTENSIONS: %s\n", output ); |
238 | |
239 | if (FindEGLConfigs() != 0) |
240 | { |
241 | printf( "EGLport ERROR: Unable to configure EGL. See previous error.\n" ); |
242 | return 1; |
243 | } |
244 | |
245 | printf( "EGLport: Using Config %d\n", configIndex ); |
246 | #if defined(EGL_VERSION_1_2) |
247 | /* Bind GLES and create the context */ |
248 | printf( "EGLport: Binding API\n" ); |
249 | result = peglBindAPI( EGL_OPENGL_ES_API ); |
250 | if ( result == EGL_FALSE ) |
251 | { |
252 | CheckEGLErrors( __FILE__, __LINE__ ); |
253 | printf( "EGLport ERROR: Could not bind EGL API.\n" ); |
254 | return 1; |
255 | } |
256 | #endif /* EGL_VERSION_1_2 */ |
257 | |
258 | printf( "EGLport: Creating Context\n" ); |
259 | eglContext = peglCreateContext( eglDisplay, eglConfigs[configIndex], NULL, contextAttribs ); |
260 | if (eglContext == EGL_NO_CONTEXT) |
261 | { |
262 | CheckEGLErrors( __FILE__, __LINE__ ); |
263 | printf( "EGLport ERROR: Unable to create GLES context!\n"); |
264 | return 1; |
265 | } |
266 | |
267 | printf( "EGLport: Creating window surface\n" ); |
268 | if (GetNativeWindow( width, height ) != 0) |
269 | { |
270 | printf( "EGLport ERROR: Unable to obtain native window!\n" ); |
271 | return 1; |
272 | } |
273 | |
274 | eglSurface = peglCreateWindowSurface( eglDisplay, eglConfigs[configIndex], nativeWindow, 0 ); |
275 | if (eglSurface == EGL_NO_SURFACE) |
276 | { |
277 | CheckEGLErrors( __FILE__, __LINE__ ); |
278 | printf( "EGLport ERROR: Unable to create EGL surface!\n" ); |
279 | return 1; |
280 | } |
281 | |
282 | printf( "EGLport: Making Current\n" ); |
283 | result = peglMakeCurrent( eglDisplay, eglSurface, eglSurface, eglContext ); |
284 | if (result != EGL_TRUE) |
285 | { |
286 | CheckEGLErrors( __FILE__, __LINE__ ); |
287 | printf( "EGLport ERROR: Unable to make GLES context current\n" ); |
288 | return 1; |
289 | } |
290 | |
291 | { |
292 | EGLint color, depth, stencil; |
293 | eglGetConfigAttrib(eglDisplay, eglConfigs[configIndex], EGL_BUFFER_SIZE, &color); |
294 | eglGetConfigAttrib(eglDisplay, eglConfigs[configIndex], EGL_DEPTH_SIZE, &depth); |
295 | eglGetConfigAttrib(eglDisplay, eglConfigs[configIndex], EGL_STENCIL_SIZE, &stencil); |
296 | eglColorbits = (color==16)?5:8; //quick hack |
297 | eglDepthbits = depth; |
298 | eglStencilbits = stencil; |
299 | } |
300 | |
301 | printf( "EGLport: Setting swap interval\n" ); |
302 | peglSwapInterval( eglDisplay, (eglSettings[CFG_VSYNC] > 0) ? 1 : 0 ); |
303 | |
304 | printf( "EGLport: Complete\n" ); |
305 | |
306 | CheckEGLErrors( __FILE__, __LINE__ ); |
307 | |
308 | return 0; |
309 | } |
310 | |
311 | /** @brief Read settings that configure how to use EGL |
312 | * @param file : name of the config file |
313 | */ |
314 | void OpenCfg ( const char* file ) |
315 | { |
316 | #define MAX_STRING 20 |
317 | #define MAX_SIZE 100 |
318 | uint8_t i; |
319 | FILE* fp = NULL; |
320 | char* location = NULL; |
321 | char eglStrings[CFG_TOTAL][MAX_STRING]; |
322 | char buffer[MAX_SIZE]; |
323 | |
324 | strncpy( eglStrings[CFG_MODE], "egl_mode=", MAX_STRING ); |
325 | strncpy( eglStrings[CFG_VSYNC], "use_vsync=", MAX_STRING ); |
326 | strncpy( eglStrings[CFG_FSAA], "use_fsaa=", MAX_STRING ); |
327 | strncpy( eglStrings[CFG_RED_SIZE], "size_red=", MAX_STRING ); |
328 | strncpy( eglStrings[CFG_GREEN_SIZE], "size_green=", MAX_STRING ); |
329 | strncpy( eglStrings[CFG_BLUE_SIZE], "size_blue=", MAX_STRING ); |
330 | strncpy( eglStrings[CFG_ALPHA_SIZE], "size_alpha=", MAX_STRING ); |
331 | strncpy( eglStrings[CFG_DEPTH_SIZE], "size_depth=", MAX_STRING ); |
332 | strncpy( eglStrings[CFG_BUFFER_SIZE], "size_buffer=", MAX_STRING ); |
333 | strncpy( eglStrings[CFG_STENCIL_SIZE], "size_stencil=", MAX_STRING ); |
334 | |
335 | /* Set defaults */ |
336 | #if defined(USE_EGL_SDL) |
337 | eglSettings[CFG_MODE] = RENDER_SDL; |
338 | #else |
339 | eglSettings[CFG_MODE] = RENDER_RAW; |
340 | #endif |
341 | eglSettings[CFG_VSYNC] = 0; |
342 | eglSettings[CFG_FSAA] = 0; |
343 | eglSettings[CFG_FPS] = 0; |
344 | eglSettings[CFG_RED_SIZE] = 5; |
345 | eglSettings[CFG_GREEN_SIZE] = 6; |
346 | eglSettings[CFG_BLUE_SIZE] = 5; |
347 | eglSettings[CFG_ALPHA_SIZE] = 0; |
348 | eglSettings[CFG_DEPTH_SIZE] = 16; |
349 | eglSettings[CFG_BUFFER_SIZE] = 16; |
350 | eglSettings[CFG_STENCIL_SIZE] = 0; |
351 | |
352 | /* Parse INI file */ |
353 | fp = fopen( file, "r"); |
354 | if (fp != NULL) |
355 | { |
356 | while (fgets( buffer, MAX_SIZE, fp ) != NULL) |
357 | { |
358 | for (i=0; i<CFG_TOTAL; i++) |
359 | { |
360 | location = strstr( buffer, eglStrings[i] ); |
361 | if (location != NULL) |
362 | { |
363 | eglSettings[i] = atol( location+strlen( eglStrings[i] ) ); |
364 | printf( "EGLport: %s set to %d.\n", eglStrings[i], eglSettings[i] ); |
365 | break; |
366 | } |
367 | } |
368 | } |
369 | |
370 | fclose( fp ); |
371 | } |
372 | else |
373 | { |
374 | printf( "EGL ERROR: Unable to read ini settings from file '%s'. Using defaults\n", file ); |
375 | } |
376 | } |
377 | |
378 | /** @brief Find a EGL configuration tht matches the defined attributes |
379 | * @return : 0 if the function passed, else 1 |
380 | */ |
381 | int8_t FindEGLConfigs( void ) |
382 | { |
383 | EGLBoolean result; |
384 | int attrib = 0; |
385 | EGLint ConfigAttribs[23]; |
386 | |
387 | ConfigAttribs[attrib++] = EGL_RED_SIZE; /* 1 */ |
388 | ConfigAttribs[attrib++] = eglSettings[CFG_RED_SIZE]; /* 2 */ |
389 | ConfigAttribs[attrib++] = EGL_GREEN_SIZE; /* 3 */ |
390 | ConfigAttribs[attrib++] = eglSettings[CFG_GREEN_SIZE]; /* 4 */ |
391 | ConfigAttribs[attrib++] = EGL_BLUE_SIZE; /* 5 */ |
392 | ConfigAttribs[attrib++] = eglSettings[CFG_BLUE_SIZE]; /* 6 */ |
393 | ConfigAttribs[attrib++] = EGL_ALPHA_SIZE; /* 7 */ |
394 | ConfigAttribs[attrib++] = eglSettings[CFG_ALPHA_SIZE]; /* 8 */ |
395 | ConfigAttribs[attrib++] = EGL_DEPTH_SIZE; /* 9 */ |
396 | ConfigAttribs[attrib++] = eglSettings[CFG_DEPTH_SIZE]; /* 10 */ |
397 | ConfigAttribs[attrib++] = EGL_BUFFER_SIZE; /* 11 */ |
398 | ConfigAttribs[attrib++] = eglSettings[CFG_BUFFER_SIZE]; /* 12 */ |
399 | ConfigAttribs[attrib++] = EGL_STENCIL_SIZE; /* 13 */ |
400 | ConfigAttribs[attrib++] = eglSettings[CFG_STENCIL_SIZE]; /* 14 */ |
401 | ConfigAttribs[attrib++] = EGL_SURFACE_TYPE; /* 15 */ |
402 | ConfigAttribs[attrib++] = EGL_WINDOW_BIT; /* 16 */ |
403 | #if defined(EGL_VERSION_1_2) |
404 | ConfigAttribs[attrib++] = EGL_RENDERABLE_TYPE; /* 17 */ |
405 | #if defined(USE_GLES1) |
406 | ConfigAttribs[attrib++] = EGL_OPENGL_ES_BIT; |
407 | #elif defined(USE_GLES2) |
408 | ConfigAttribs[attrib++] = EGL_OPENGL_ES2_BIT; /* 18 */ |
409 | #endif /* USE_GLES1 */ |
410 | #endif /* EGL_VERSION_1_2 */ |
411 | ConfigAttribs[attrib++] = EGL_SAMPLE_BUFFERS; /* 19 */ |
412 | ConfigAttribs[attrib++] = (eglSettings[CFG_FSAA] > 0) ? 1 : 0; /* 20 */ |
413 | ConfigAttribs[attrib++] = EGL_SAMPLES; /* 21 */ |
414 | ConfigAttribs[attrib++] = eglSettings[CFG_FSAA]; /* 22 */ |
415 | ConfigAttribs[attrib++] = EGL_NONE; /* 23 */ |
416 | |
417 | result = peglChooseConfig( eglDisplay, ConfigAttribs, eglConfigs, totalConfigsIn, &totalConfigsFound ); |
418 | if (result != EGL_TRUE || totalConfigsFound == 0) |
419 | { |
420 | CheckEGLErrors( __FILE__, __LINE__ ); |
421 | printf( "EGLport ERROR: Unable to query for available configs, found %d.\n", totalConfigsFound ); |
422 | return 1; |
423 | } |
424 | printf( "EGLport: Found %d available configs\n", totalConfigsFound ); |
425 | |
426 | return 0; |
427 | } |
428 | |
429 | /** @brief Error checking function |
430 | * @param file : string reference that contains the source file that the check is occuring in |
431 | * @param line : numeric reference that contains the line number that the check is occuring in |
432 | * @return : 0 if the function passed, else 1 |
433 | */ |
434 | int8_t CheckEGLErrors( const char* file, uint16_t line ) |
435 | { |
436 | EGLenum error; |
437 | const char* errortext; |
438 | const char* description; |
439 | |
440 | error = eglGetError(); |
441 | |
442 | if (error != EGL_SUCCESS && error != 0) |
443 | { |
444 | switch (error) |
445 | { |
446 | case EGL_NOT_INITIALIZED: |
447 | errortext = "EGL_NOT_INITIALIZED."; |
448 | description = "EGL is not or could not be initialized, for the specified display."; |
449 | break; |
450 | case EGL_BAD_ACCESS: |
451 | errortext = "EGL_BAD_ACCESS EGL"; |
452 | description = "cannot access a requested resource (for example, a context is bound in another thread)."; |
453 | break; |
454 | case EGL_BAD_ALLOC: |
455 | errortext = "EGL_BAD_ALLOC EGL"; |
456 | description = "failed to allocate resources for the requested operation."; |
457 | break; |
458 | case EGL_BAD_ATTRIBUTE: |
459 | errortext = "EGL_BAD_ATTRIBUTE"; |
460 | description = "An unrecognized attribute or attribute value was passed in anattribute list."; |
461 | break; |
462 | case EGL_BAD_CONFIG: |
463 | errortext = "EGL_BAD_CONFIG"; |
464 | description = "An EGLConfig argument does not name a valid EGLConfig."; |
465 | break; |
466 | case EGL_BAD_CONTEXT: |
467 | errortext = "EGL_BAD_CONTEXT"; |
468 | description = "An EGLContext argument does not name a valid EGLContext."; |
469 | break; |
470 | case EGL_BAD_CURRENT_SURFACE: |
471 | errortext = "EGL_BAD_CURRENT_SURFACE"; |
472 | description = "The current surface of the calling thread is a window, pbuffer,or pixmap that is no longer valid."; |
473 | break; |
474 | case EGL_BAD_DISPLAY: |
475 | errortext = "EGL_BAD_DISPLAY"; |
476 | description = "An EGLDisplay argument does not name a valid EGLDisplay."; |
477 | break; |
478 | case EGL_BAD_MATCH: |
479 | errortext = "EGL_BAD_MATCH"; |
480 | description = "Arguments are inconsistent; for example, an otherwise valid context requires buffers (e.g. depth or stencil) not allocated by an otherwise valid surface."; |
481 | break; |
482 | case EGL_BAD_NATIVE_PIXMAP: |
483 | errortext = "EGL_BAD_NATIVE_PIXMAP"; |
484 | description = "An EGLNativePixmapType argument does not refer to a validnative pixmap."; |
485 | break; |
486 | case EGL_BAD_NATIVE_WINDOW: |
487 | errortext = "EGL_BAD_NATIVE_WINDOW"; |
488 | description = "An EGLNativeWindowType argument does not refer to a validnative window."; |
489 | break; |
490 | case EGL_BAD_PARAMETER: |
491 | errortext = "EGL_BAD_PARAMETER"; |
492 | description = "One or more argument values are invalid."; |
493 | break; |
494 | case EGL_BAD_SURFACE: |
495 | errortext = "EGL_BAD_SURFACE"; |
496 | description = "An EGLSurface argument does not name a valid surface (window,pbuffer, or pixmap) configured for rendering"; |
497 | break; |
498 | case EGL_CONTEXT_LOST: |
499 | errortext = "EGL_CONTEXT_LOST"; |
500 | description = "A power management event has occurred. The application mustdestroy all contexts and reinitialise client API state and objects to continue rendering."; |
501 | break; |
502 | default: |
503 | errortext = "Unknown EGL Error"; |
504 | description = ""; |
505 | break; |
506 | } |
507 | |
508 | printf( "EGLport ERROR: EGL Error detected in file %s at line %d: %s (0x%X)\n Description: %s\n", file, line, errortext, error, description ); |
509 | return 1; |
510 | } |
511 | |
512 | return 0; |
513 | } |
514 | |
515 | /** @brief Obtain a reference to the system's native display |
516 | * @param window : pointer to save the display reference |
517 | * @return : 0 if the function passed, else 1 |
518 | */ |
519 | int8_t GetNativeDisplay( void ) |
520 | { |
521 | if (eglSettings[CFG_MODE] == RENDER_RAW) /* RAW FB mode */ |
522 | { |
523 | printf( "EGLport: Using EGL_DEFAULT_DISPLAY\n" ); |
524 | nativeDisplay = EGL_DEFAULT_DISPLAY; |
525 | } |
526 | else if (eglSettings[CFG_MODE] == RENDER_SDL) /* SDL/X11 mode */ |
527 | { |
528 | #if defined(USE_EGL_SDL) |
529 | printf( "EGLport: Opening SDL/X11 display\n" ); |
530 | SDL_VERSION(&sysWmInfo.version); |
531 | SDL_GetWMInfo(&sysWmInfo); |
532 | nativeDisplay = (EGLNativeDisplayType)sysWmInfo.info.x11.display; |
533 | |
534 | if (nativeDisplay == 0) |
535 | { |
536 | printf( "EGLport ERROR: unable to get display!\n" ); |
537 | return 1; |
538 | } |
539 | #else |
540 | printf( "EGLport ERROR: SDL mode was not enabled in this compile!\n" ); |
541 | #endif |
542 | } |
543 | |
544 | return 0; |
545 | } |
546 | |
547 | /** @brief Obtain a reference to the system's native window |
548 | * @param width : desired pixel width of the window (not used by all platforms) |
549 | * @param height : desired pixel height of the window (not used by all platforms) |
550 | * @return : 0 if the function passed, else 1 |
551 | */ |
552 | int8_t GetNativeWindow( uint16_t width, uint16_t height ) |
553 | { |
554 | nativeWindow = 0; |
555 | |
556 | #if defined(WIZ) || defined(CAANOO) |
557 | |
558 | nativeWindow = (NativeWindowType)malloc(16*1024); |
559 | |
560 | if(nativeWindow == NULL) { |
561 | printf( "EGLport ERROR: Memory for window Failed\n" ); |
562 | return 1; |
563 | } |
564 | |
565 | #elif defined(RPI) |
566 | |
567 | EGLBoolean result; |
568 | uint32_t screen_width, screen_height; |
569 | static EGL_DISPMANX_WINDOW_T nativewindow; |
570 | DISPMANX_ELEMENT_HANDLE_T dispman_element; |
571 | DISPMANX_DISPLAY_HANDLE_T dispman_display; |
572 | DISPMANX_UPDATE_HANDLE_T dispman_update; |
573 | VC_RECT_T dst_rect; |
574 | VC_RECT_T src_rect; |
575 | |
576 | /* create an EGL window surface */ |
577 | result = graphics_get_display_size(0 /* LCD */, &screen_width, &screen_height); |
578 | if(result < 0) { |
579 | printf( "EGLport ERROR: RPi graphicget_display_size failed\n" ); |
580 | return 1; |
581 | } |
582 | |
583 | dst_rect.x = 0; |
584 | dst_rect.y = 0; |
585 | dst_rect.width = screen_width; |
586 | dst_rect.height = screen_height; |
587 | |
588 | src_rect.x = 0; |
589 | src_rect.y = 0; |
590 | src_rect.width = width << 16; |
591 | src_rect.height = height << 16; |
592 | |
593 | dispman_display = vc_dispmanx_display_open( 0 /* LCD */); |
594 | dispman_update = vc_dispmanx_update_start( 0 ); |
595 | dispman_element = vc_dispmanx_element_add ( dispman_update, dispman_display, |
596 | 0 /*layer*/, &dst_rect, 0 /*src*/, |
597 | &src_rect, DISPMANX_PROTECTION_NONE, (VC_DISPMANX_ALPHA_T*)0 /*alpha*/, (DISPMANX_CLAMP_T*)0 /*clamp*/, (DISPMANX_TRANSFORM_T)0 /*transform*/); |
598 | |
599 | nativewindow.element = dispman_element; |
600 | nativewindow.width = screen_width; |
601 | nativewindow.height = screen_height; |
602 | vc_dispmanx_update_submit_sync( dispman_update ); |
603 | |
604 | nativeWindow = (NativeWindowType)&nativewindow; |
605 | |
606 | #else /* default */ |
607 | |
608 | if (eglSettings[CFG_MODE] == RENDER_RAW) /* RAW FB mode */ |
609 | { |
610 | nativeWindow = 0; |
611 | } |
612 | else if(eglSettings[CFG_MODE] == RENDER_SDL) /* SDL/X11 mode */ |
613 | { |
614 | #if defined(USE_EGL_SDL) |
615 | /* SDL_GetWMInfo is populated when display was opened */ |
616 | nativeWindow = (NativeWindowType)sysWmInfo.info.x11.window; |
617 | |
618 | if (nativeWindow == 0) |
619 | { |
620 | printf( "EGLport ERROR: unable to get window!\n" ); |
621 | return 1; |
622 | } |
623 | #else |
624 | printf( "EGLport ERROR: SDL mode was not enabled in this compile!\n" ); |
625 | #endif |
626 | } |
627 | else |
628 | { |
629 | printf( "EGLport ERROR: Unknown EGL render mode %d!\n", eglSettings[CFG_MODE] ); |
630 | return 1; |
631 | } |
632 | |
633 | #endif /* WIZ / CAANOO */ |
634 | |
635 | return 0; |
636 | } |
637 | |
638 | /** @brief Release the system's native display |
639 | */ |
640 | void FreeNativeDisplay( void ) |
641 | { |
642 | } |
643 | |
644 | /** @brief Release the system's native window |
645 | */ |
646 | void FreeNativeWindow( void ) |
647 | { |
648 | #if defined(WIZ) || defined(CAANOO) |
649 | if (nativeWindow != NULL) { |
650 | free( nativeWindow ); |
651 | } |
652 | nativeWindow = NULL; |
653 | #endif /* WIZ / CAANOO */ |
654 | } |
655 | |
656 | /** @brief Open any system specific resources |
657 | */ |
658 | void Platform_Open( void ) |
659 | { |
660 | #if defined(PANDORA) |
661 | /* Pandora VSync */ |
662 | fbdev = open( "/dev/fb0", O_RDONLY /* O_RDWR */ ); |
663 | if ( fbdev < 0 ) { |
664 | printf( "EGLport ERROR: Couldn't open /dev/fb0 for Pandora Vsync\n" ); |
665 | } |
666 | #elif defined(RPI) |
667 | bcm_host_init(); |
668 | #endif /* PANDORA */ |
669 | } |
670 | |
671 | /** @brief Release any system specific resources |
672 | */ |
673 | void Platform_Close( void ) |
674 | { |
675 | #if defined(PANDORA) |
676 | /* Pandora VSync */ |
677 | close( fbdev ); |
678 | fbdev = -1; |
679 | #endif /* PANDORA */ |
680 | } |
681 | |
682 | /** @brief Check the systems vsync state |
683 | */ |
684 | void Platform_VSync( void ) |
685 | { |
686 | #if defined(PANDORA) |
687 | /* Pandora VSync */ |
688 | if (fbdev >= 0) { |
689 | int arg = 0; |
690 | ioctl( fbdev, FBIO_WAITFORVSYNC, &arg ); |
691 | } |
692 | #endif /* PANDORA */ |
693 | } |
694 | |
695 | /** @brief Get the system tick time (ms) |
696 | */ |
697 | uint32_t Platform_GetTicks( void ) |
698 | { |
699 | uint32_t ticks = 0; |
700 | #if defined(USE_EGL_SDL) |
701 | ticks = SDL_GetTicks(); |
702 | #else |
703 | printf( "EGLport ERROR: SDL mode was not enabled in this compile!\n" ); |
704 | #endif |
705 | return ticks; |
706 | } |