PANDORA: Make GLES context compatible with latest driver (FB only, no X11)
[mupen64plus-pandora.git] / source / rice_gles / src / eglport.c
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 NOTICE: 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 }