drm/gl context stuff
[mupen64plus-pandora.git] / source / mupen64plus-core / src / api / eglport.cpp
CommitLineData
451ab91e 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_GLES2 1
33
34#if defined(USE_EGL_SDL)
35#include "SDL.h"
36#include "SDL_syswm.h"
37SDL_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
49int fbdev = -1;
50
51#elif defined(RPI)
52#include "bcm_host.h"
53#endif /* PANDORA */
54
55enum 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
61enum 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
76NativeDisplayType nativeDisplay = 0; /** Reference to the systems native display */
77NativeWindowType nativeWindow = 0; /** Reference to the systems native window */
78EGLint eglSettings[CFG_TOTAL]; /** Stores setting values. */
79EGLDisplay eglDisplay = NULL; /** Reference to the EGL display */
80EGLConfig eglConfig = NULL; /** Reference to the EGL config */
81EGLContext eglContext = NULL; /** Reference to the EGL context */
82EGLSurface eglSurface = NULL; /** Reference to the EGL surface */
83
84#define totalConfigsIn 5 /** Total number of configurations to request */
85EGLint totalConfigsFound = 0; /** Total number of configurations matching attributes */
86EGLConfig eglConfigs[totalConfigsIn]; /** Structure containing references to matching configurations */
87
88uint32_t fpsCount = 0; /** Total number of frames counted */
89uint32_t fpsTime = 0; /** Start time of frame count measurment */
90
91int8_t eglColorbits = 0;
92int8_t eglDepthbits = 0;
93int8_t eglStencilbits = 0;
94
95
96/** Private API */
97void OpenCfg ( const char* file );
98int8_t ConfigureEGL ( EGLConfig config );
99int8_t FindEGLConfigs ( void );
100int8_t CheckEGLErrors ( const char* file, uint16_t line );
101
102int8_t GetNativeDisplay ( void );
103int8_t GetNativeWindow ( uint16_t width, uint16_t height );
104void FreeNativeDisplay ( void );
105void FreeNativeWindow ( void );
106
107void Platform_Open ( void );
108void Platform_Close ( void );
109void Platform_VSync ( void );
110uint32_t Platform_GetTicks ( void );
111
daa7f9a3 112static void drm_do_swap(void);
113
451ab91e 114/** @brief Release all EGL and system resources
115 */
116void EGL_Close( void )
117{
118 /* Release EGL resources */
119 if (eglDisplay != NULL)
120 {
121 peglMakeCurrent( eglDisplay, NULL, NULL, EGL_NO_CONTEXT );
122 if (eglContext != NULL) {
123 peglDestroyContext( eglDisplay, eglContext );
124 }
125 if (eglSurface != NULL) {
126 peglDestroySurface( eglDisplay, eglSurface );
127 }
128 peglTerminate( eglDisplay );
129 }
130
131 eglSurface = NULL;
132 eglContext = NULL;
133 eglDisplay = NULL;
134
135 eglColorbits = 0;
136 eglDepthbits = 0;
137 eglStencilbits = 0;
138
139 /* Release platform resources */
140 FreeNativeWindow();
141 FreeNativeDisplay();
142 Platform_Close();
143
144 CheckEGLErrors( __FILE__, __LINE__ );
145
146 printf( "EGLport: Closed\n" );
147}
148
149/** @brief Swap the surface buffer onto the display
150 */
151void EGL_SwapBuffers( void )
152{
153 if (eglSettings[CFG_VSYNC] != 0) {
154 Platform_VSync();
155 }
156
157 peglSwapBuffers( eglDisplay, eglSurface );
daa7f9a3 158 drm_do_swap();
451ab91e 159
160 if (eglSettings[CFG_FPS] != 0) {
161 fpsCount++;
162
163 if (fpsTime - Platform_GetTicks() >= 1000)
164 {
165 printf( "EGLport: %d fps\n", fpsCount );
166 fpsTime = Platform_GetTicks();
167 fpsCount = 0;
168 }
169 }
170}
171
172/** @brief Obtain the system display and initialize EGL
173 * @param width : desired pixel width of the window (not used by all platforms)
174 * @param height : desired pixel height of the window (not used by all platforms)
175 * @return : 0 if the function passed, else 1
176 */
177int8_t EGL_Open( uint16_t width, uint16_t height )
178{
179 EGLint eglMajorVer, eglMinorVer;
180 EGLBoolean result;
181 uint32_t configIndex = 0;
182 const char* output;
183
184 static const EGLint contextAttribs[] =
185 {
186#if defined(USE_GLES2)
187 EGL_CONTEXT_CLIENT_VERSION, 2,
188#endif
189 EGL_NONE
190 };
191
192#if defined(DEBUG)
193 printf( "EGLport Warning: DEBUG is enabled which may effect performance\n" );
194#endif
195
196 /* Check that system is not open */
197 if (eglDisplay != NULL || eglContext != NULL || eglSurface != NULL)
198 {
199 printf( "EGLport ERROR: EGL system is already open!\n" );
200 return 1;
201 }
202
203 /* Check for the cfg file to alternative settings */
204 OpenCfg( "eglport.cfg" );
205
206 /* Setup any platform specific bits */
207 Platform_Open();
208
209 printf( "EGLport: Opening EGL display\n" );
210 if (GetNativeDisplay() != 0)
211 {
212 printf( "EGLport ERROR: Unable to obtain native display!\n" );
213 return 1;
214 }
215
216 eglDisplay = peglGetDisplay( nativeDisplay );
217 if (eglDisplay == EGL_NO_DISPLAY)
218 {
219 CheckEGLErrors( __FILE__, __LINE__ );
220 printf( "EGLport ERROR: Unable to create EGL display.\n" );
221 return 1;
222 }
223
224 printf( "EGLport: Initializing\n" );
225 result = peglInitialize( eglDisplay, &eglMajorVer, &eglMinorVer );
226 if (result != EGL_TRUE )
227 {
228 CheckEGLErrors( __FILE__, __LINE__ );
229 printf( "EGLport ERROR: Unable to initialize EGL display.\n" );
230 return 1;
231 }
232
233 /* Get EGL Library Information */
234 printf( "EGL Implementation Version: Major %d Minor %d\n", eglMajorVer, eglMinorVer );
235 output = peglQueryString( eglDisplay, EGL_VENDOR );
236 printf( "EGL_VENDOR: %s\n", output );
237 output = peglQueryString( eglDisplay, EGL_VERSION );
238 printf( "EGL_VERSION: %s\n", output );
239 output = peglQueryString( eglDisplay, EGL_EXTENSIONS );
240 printf( "EGL_EXTENSIONS: %s\n", output );
241
242 if (FindEGLConfigs() != 0)
243 {
244 printf( "EGLport ERROR: Unable to configure EGL. See previous error.\n" );
245 return 1;
246 }
247
248 printf( "EGLport: Using Config %d\n", configIndex );
249#if defined(EGL_VERSION_1_2)
250 /* Bind GLES and create the context */
251 printf( "EGLport: Binding API\n" );
252 result = peglBindAPI( EGL_OPENGL_ES_API );
253 if ( result == EGL_FALSE )
254 {
255 CheckEGLErrors( __FILE__, __LINE__ );
256 printf( "EGLport ERROR: Could not bind EGL API.\n" );
257 return 1;
258 }
259#endif /* EGL_VERSION_1_2 */
260
261 printf( "EGLport: Creating Context\n" );
262 eglContext = peglCreateContext( eglDisplay, eglConfigs[configIndex], NULL, contextAttribs );
263 if (eglContext == EGL_NO_CONTEXT)
264 {
265 CheckEGLErrors( __FILE__, __LINE__ );
266 printf( "EGLport ERROR: Unable to create GLES context!\n");
267 return 1;
268 }
269
270 printf( "EGLport: Creating window surface\n" );
271 if (GetNativeWindow( width, height ) != 0)
272 {
273 printf( "EGLport ERROR: Unable to obtain native window!\n" );
274 return 1;
275 }
276
277 eglSurface = peglCreateWindowSurface( eglDisplay, eglConfigs[configIndex], nativeWindow, 0 );
278 if (eglSurface == EGL_NO_SURFACE)
279 {
280 CheckEGLErrors( __FILE__, __LINE__ );
281 printf( "EGLport ERROR: Unable to create EGL surface!\n" );
282 return 1;
283 }
284
285 printf( "EGLport: Making Current\n" );
286 result = peglMakeCurrent( eglDisplay, eglSurface, eglSurface, eglContext );
287 if (result != EGL_TRUE)
288 {
289 CheckEGLErrors( __FILE__, __LINE__ );
290 printf( "EGLport ERROR: Unable to make GLES context current\n" );
291 return 1;
292 }
293
294 {
295 EGLint color, depth, stencil;
296 eglGetConfigAttrib(eglDisplay, eglConfigs[configIndex], EGL_BUFFER_SIZE, &color);
297 eglGetConfigAttrib(eglDisplay, eglConfigs[configIndex], EGL_DEPTH_SIZE, &depth);
298 eglGetConfigAttrib(eglDisplay, eglConfigs[configIndex], EGL_STENCIL_SIZE, &stencil);
299 eglColorbits = (color==16)?5:8; //quick hack
300 eglDepthbits = depth;
301 eglStencilbits = stencil;
302 }
303
304 printf( "EGLport: Setting swap interval\n" );
305 peglSwapInterval( eglDisplay, (eglSettings[CFG_VSYNC] > 0) ? 1 : 0 );
306
307 printf( "EGLport: Complete\n" );
308
309 CheckEGLErrors( __FILE__, __LINE__ );
310
311 return 0;
312}
313
314/** @brief Read settings that configure how to use EGL
315 * @param file : name of the config file
316 */
317void OpenCfg ( const char* file )
318{
319 #define MAX_STRING 20
320 #define MAX_SIZE 100
321 uint8_t i;
322 FILE* fp = NULL;
323 char* location = NULL;
324 char eglStrings[CFG_TOTAL][MAX_STRING];
325 char buffer[MAX_SIZE];
326
327 strncpy( eglStrings[CFG_MODE], "egl_mode=", MAX_STRING );
328 strncpy( eglStrings[CFG_VSYNC], "use_vsync=", MAX_STRING );
329 strncpy( eglStrings[CFG_FSAA], "use_fsaa=", MAX_STRING );
330 strncpy( eglStrings[CFG_RED_SIZE], "size_red=", MAX_STRING );
331 strncpy( eglStrings[CFG_GREEN_SIZE], "size_green=", MAX_STRING );
332 strncpy( eglStrings[CFG_BLUE_SIZE], "size_blue=", MAX_STRING );
333 strncpy( eglStrings[CFG_ALPHA_SIZE], "size_alpha=", MAX_STRING );
334 strncpy( eglStrings[CFG_DEPTH_SIZE], "size_depth=", MAX_STRING );
335 strncpy( eglStrings[CFG_BUFFER_SIZE], "size_buffer=", MAX_STRING );
336 strncpy( eglStrings[CFG_STENCIL_SIZE], "size_stencil=", MAX_STRING );
337
338 /* Set defaults */
06190a2d 339//#if defined(USE_EGL_SDL)
340// eglSettings[CFG_MODE] = RENDER_SDL;
341//#else
451ab91e 342 eglSettings[CFG_MODE] = RENDER_RAW;
06190a2d 343//#endif
451ab91e 344 eglSettings[CFG_VSYNC] = 0;
345 eglSettings[CFG_FSAA] = 0;
346 eglSettings[CFG_FPS] = 0;
347 eglSettings[CFG_RED_SIZE] = 5;
348 eglSettings[CFG_GREEN_SIZE] = 6;
349 eglSettings[CFG_BLUE_SIZE] = 5;
350 eglSettings[CFG_ALPHA_SIZE] = 0;
351 eglSettings[CFG_DEPTH_SIZE] = 16;
352 eglSettings[CFG_BUFFER_SIZE] = 16;
353 eglSettings[CFG_STENCIL_SIZE] = 0;
354
355 /* Parse INI file */
356 fp = fopen( file, "r");
357 if (fp != NULL)
358 {
359 while (fgets( buffer, MAX_SIZE, fp ) != NULL)
360 {
361 for (i=0; i<CFG_TOTAL; i++)
362 {
363 location = strstr( buffer, eglStrings[i] );
364 if (location != NULL)
365 {
366 eglSettings[i] = atol( location+strlen( eglStrings[i] ) );
367 printf( "EGLport: %s set to %d.\n", eglStrings[i], eglSettings[i] );
368 break;
369 }
370 }
371 }
372
373 fclose( fp );
374 }
375 else
376 {
06190a2d 377 printf( "EGL NOTICE: Unable to read ini settings from file '%s'. Using defaults\n", file );
451ab91e 378 }
379}
380
381/** @brief Find a EGL configuration tht matches the defined attributes
382 * @return : 0 if the function passed, else 1
383 */
384int8_t FindEGLConfigs( void )
385{
386 EGLBoolean result;
387 int attrib = 0;
388 EGLint ConfigAttribs[23];
389
390 ConfigAttribs[attrib++] = EGL_RED_SIZE; /* 1 */
391 ConfigAttribs[attrib++] = eglSettings[CFG_RED_SIZE]; /* 2 */
392 ConfigAttribs[attrib++] = EGL_GREEN_SIZE; /* 3 */
393 ConfigAttribs[attrib++] = eglSettings[CFG_GREEN_SIZE]; /* 4 */
394 ConfigAttribs[attrib++] = EGL_BLUE_SIZE; /* 5 */
395 ConfigAttribs[attrib++] = eglSettings[CFG_BLUE_SIZE]; /* 6 */
396 ConfigAttribs[attrib++] = EGL_ALPHA_SIZE; /* 7 */
397 ConfigAttribs[attrib++] = eglSettings[CFG_ALPHA_SIZE]; /* 8 */
398 ConfigAttribs[attrib++] = EGL_DEPTH_SIZE; /* 9 */
399 ConfigAttribs[attrib++] = eglSettings[CFG_DEPTH_SIZE]; /* 10 */
400 ConfigAttribs[attrib++] = EGL_BUFFER_SIZE; /* 11 */
401 ConfigAttribs[attrib++] = eglSettings[CFG_BUFFER_SIZE]; /* 12 */
402 ConfigAttribs[attrib++] = EGL_STENCIL_SIZE; /* 13 */
403 ConfigAttribs[attrib++] = eglSettings[CFG_STENCIL_SIZE]; /* 14 */
404 ConfigAttribs[attrib++] = EGL_SURFACE_TYPE; /* 15 */
405 ConfigAttribs[attrib++] = EGL_WINDOW_BIT; /* 16 */
406#if defined(EGL_VERSION_1_2)
407 ConfigAttribs[attrib++] = EGL_RENDERABLE_TYPE; /* 17 */
408#if defined(USE_GLES1)
409 ConfigAttribs[attrib++] = EGL_OPENGL_ES_BIT;
410#elif defined(USE_GLES2)
411 ConfigAttribs[attrib++] = EGL_OPENGL_ES2_BIT; /* 18 */
412#endif /* USE_GLES1 */
413#endif /* EGL_VERSION_1_2 */
414 ConfigAttribs[attrib++] = EGL_SAMPLE_BUFFERS; /* 19 */
415 ConfigAttribs[attrib++] = (eglSettings[CFG_FSAA] > 0) ? 1 : 0; /* 20 */
416 ConfigAttribs[attrib++] = EGL_SAMPLES; /* 21 */
417 ConfigAttribs[attrib++] = eglSettings[CFG_FSAA]; /* 22 */
418 ConfigAttribs[attrib++] = EGL_NONE; /* 23 */
419
420 result = peglChooseConfig( eglDisplay, ConfigAttribs, eglConfigs, totalConfigsIn, &totalConfigsFound );
421 if (result != EGL_TRUE || totalConfigsFound == 0)
422 {
423 CheckEGLErrors( __FILE__, __LINE__ );
424 printf( "EGLport ERROR: Unable to query for available configs, found %d.\n", totalConfigsFound );
425 return 1;
426 }
427 printf( "EGLport: Found %d available configs\n", totalConfigsFound );
428
429 return 0;
430}
431
432/** @brief Error checking function
433 * @param file : string reference that contains the source file that the check is occuring in
434 * @param line : numeric reference that contains the line number that the check is occuring in
435 * @return : 0 if the function passed, else 1
436 */
437int8_t CheckEGLErrors( const char* file, uint16_t line )
438{
439 EGLenum error;
440 const char* errortext;
441 const char* description;
442
443 error = eglGetError();
444
445 if (error != EGL_SUCCESS && error != 0)
446 {
447 switch (error)
448 {
449 case EGL_NOT_INITIALIZED:
450 errortext = "EGL_NOT_INITIALIZED.";
451 description = "EGL is not or could not be initialized, for the specified display.";
452 break;
453 case EGL_BAD_ACCESS:
454 errortext = "EGL_BAD_ACCESS EGL";
455 description = "cannot access a requested resource (for example, a context is bound in another thread).";
456 break;
457 case EGL_BAD_ALLOC:
458 errortext = "EGL_BAD_ALLOC EGL";
459 description = "failed to allocate resources for the requested operation.";
460 break;
461 case EGL_BAD_ATTRIBUTE:
462 errortext = "EGL_BAD_ATTRIBUTE";
463 description = "An unrecognized attribute or attribute value was passed in anattribute list.";
464 break;
465 case EGL_BAD_CONFIG:
466 errortext = "EGL_BAD_CONFIG";
467 description = "An EGLConfig argument does not name a valid EGLConfig.";
468 break;
469 case EGL_BAD_CONTEXT:
470 errortext = "EGL_BAD_CONTEXT";
471 description = "An EGLContext argument does not name a valid EGLContext.";
472 break;
473 case EGL_BAD_CURRENT_SURFACE:
474 errortext = "EGL_BAD_CURRENT_SURFACE";
475 description = "The current surface of the calling thread is a window, pbuffer,or pixmap that is no longer valid.";
476 break;
477 case EGL_BAD_DISPLAY:
478 errortext = "EGL_BAD_DISPLAY";
479 description = "An EGLDisplay argument does not name a valid EGLDisplay.";
480 break;
481 case EGL_BAD_MATCH:
482 errortext = "EGL_BAD_MATCH";
483 description = "Arguments are inconsistent; for example, an otherwise valid context requires buffers (e.g. depth or stencil) not allocated by an otherwise valid surface.";
484 break;
485 case EGL_BAD_NATIVE_PIXMAP:
486 errortext = "EGL_BAD_NATIVE_PIXMAP";
487 description = "An EGLNativePixmapType argument does not refer to a validnative pixmap.";
488 break;
489 case EGL_BAD_NATIVE_WINDOW:
490 errortext = "EGL_BAD_NATIVE_WINDOW";
491 description = "An EGLNativeWindowType argument does not refer to a validnative window.";
492 break;
493 case EGL_BAD_PARAMETER:
494 errortext = "EGL_BAD_PARAMETER";
495 description = "One or more argument values are invalid.";
496 break;
497 case EGL_BAD_SURFACE:
498 errortext = "EGL_BAD_SURFACE";
499 description = "An EGLSurface argument does not name a valid surface (window,pbuffer, or pixmap) configured for rendering";
500 break;
501 case EGL_CONTEXT_LOST:
502 errortext = "EGL_CONTEXT_LOST";
503 description = "A power management event has occurred. The application mustdestroy all contexts and reinitialise client API state and objects to continue rendering.";
504 break;
505 default:
506 errortext = "Unknown EGL Error";
507 description = "";
508 break;
509 }
510
511 printf( "EGLport ERROR: EGL Error detected in file %s at line %d: %s (0x%X)\n Description: %s\n", file, line, errortext, error, description );
512 return 1;
513 }
514
515 return 0;
516}
517
daa7f9a3 518#if 0
519
451ab91e 520/** @brief Obtain a reference to the system's native display
521 * @param window : pointer to save the display reference
522 * @return : 0 if the function passed, else 1
523 */
524int8_t GetNativeDisplay( void )
525{
526 if (eglSettings[CFG_MODE] == RENDER_RAW) /* RAW FB mode */
527 {
528 printf( "EGLport: Using EGL_DEFAULT_DISPLAY\n" );
529 nativeDisplay = EGL_DEFAULT_DISPLAY;
530 }
531 else if (eglSettings[CFG_MODE] == RENDER_SDL) /* SDL/X11 mode */
532 {
533#if defined(USE_EGL_SDL)
534 printf( "EGLport: Opening SDL/X11 display\n" );
535 SDL_VERSION(&sysWmInfo.version);
536 SDL_GetWMInfo(&sysWmInfo);
537 nativeDisplay = (EGLNativeDisplayType)sysWmInfo.info.x11.display;
538
539 if (nativeDisplay == 0)
540 {
541 printf( "EGLport ERROR: unable to get display!\n" );
542 return 1;
543 }
544#else
545 printf( "EGLport ERROR: SDL mode was not enabled in this compile!\n" );
546#endif
547 }
548
549 return 0;
550}
551
552/** @brief Obtain a reference to the system's native window
553 * @param width : desired pixel width of the window (not used by all platforms)
554 * @param height : desired pixel height of the window (not used by all platforms)
555 * @return : 0 if the function passed, else 1
556 */
557int8_t GetNativeWindow( uint16_t width, uint16_t height )
558{
559 nativeWindow = 0;
560
561#if defined(WIZ) || defined(CAANOO)
562
563 nativeWindow = (NativeWindowType)malloc(16*1024);
564
565 if(nativeWindow == NULL) {
566 printf( "EGLport ERROR: Memory for window Failed\n" );
567 return 1;
568 }
569
570#elif defined(RPI)
571
572 EGLBoolean result;
573 uint32_t screen_width, screen_height;
574 static EGL_DISPMANX_WINDOW_T nativewindow;
575 DISPMANX_ELEMENT_HANDLE_T dispman_element;
576 DISPMANX_DISPLAY_HANDLE_T dispman_display;
577 DISPMANX_UPDATE_HANDLE_T dispman_update;
578 VC_RECT_T dst_rect;
579 VC_RECT_T src_rect;
580
581 /* create an EGL window surface */
582 result = graphics_get_display_size(0 /* LCD */, &screen_width, &screen_height);
583 if(result < 0) {
584 printf( "EGLport ERROR: RPi graphicget_display_size failed\n" );
585 return 1;
586 }
587
588 dst_rect.x = 0;
589 dst_rect.y = 0;
590 dst_rect.width = screen_width;
591 dst_rect.height = screen_height;
592
593 src_rect.x = 0;
594 src_rect.y = 0;
595 src_rect.width = width << 16;
596 src_rect.height = height << 16;
597
598 dispman_display = vc_dispmanx_display_open( 0 /* LCD */);
599 dispman_update = vc_dispmanx_update_start( 0 );
600 dispman_element = vc_dispmanx_element_add ( dispman_update, dispman_display,
601 0 /*layer*/, &dst_rect, 0 /*src*/,
602 &src_rect, DISPMANX_PROTECTION_NONE, (VC_DISPMANX_ALPHA_T*)0 /*alpha*/, (DISPMANX_CLAMP_T*)0 /*clamp*/, (DISPMANX_TRANSFORM_T)0 /*transform*/);
603
604 nativewindow.element = dispman_element;
605 nativewindow.width = screen_width;
606 nativewindow.height = screen_height;
607 vc_dispmanx_update_submit_sync( dispman_update );
608
609 nativeWindow = (NativeWindowType)&nativewindow;
610
611#else /* default */
612
613 if (eglSettings[CFG_MODE] == RENDER_RAW) /* RAW FB mode */
614 {
615 nativeWindow = 0;
616 }
617 else if(eglSettings[CFG_MODE] == RENDER_SDL) /* SDL/X11 mode */
618 {
619#if defined(USE_EGL_SDL)
620 /* SDL_GetWMInfo is populated when display was opened */
621 nativeWindow = (NativeWindowType)sysWmInfo.info.x11.window;
622
623 if (nativeWindow == 0)
624 {
625 printf( "EGLport ERROR: unable to get window!\n" );
626 return 1;
627 }
628#else
629 printf( "EGLport ERROR: SDL mode was not enabled in this compile!\n" );
630#endif
631 }
632 else
633 {
634 printf( "EGLport ERROR: Unknown EGL render mode %d!\n", eglSettings[CFG_MODE] );
635 return 1;
636 }
637
638#endif /* WIZ / CAANOO */
639
640 return 0;
641}
642
daa7f9a3 643#else
644
645#include <xf86drm.h>
646#include <xf86drmMode.h>
647#include <gbm.h>
648#include <errno.h>
649
650static struct {
651 struct gbm_device *dev;
652 struct gbm_surface *surface;
653} gbm;
654
655static struct {
656 int fd;
657 uint32_t crtc_id;
658 uint32_t connector_id;
659 //struct gbm_bo *bo;
660} drm;
661
662int8_t GetNativeDisplay( void )
663{
664 drmModeRes *resources;
665 drmModeConnector *connector;
666 drmModeEncoder *encoder;
667 drmModeCrtc *crtc;
668 int i;
669
670 errno = 0;
671
672 /* init drm */
673 drm.fd = drmOpen("omapdrm", NULL);
674 if (drm.fd < 0) {
675 perror("DRM: drmOpen omapdrm");
676 exit(1);
677 }
678
679 resources = drmModeGetResources(drm.fd);
680 if (resources == NULL) {
681 perror("DRM: drmModeGetResources");
682 exit(1);
683 }
684
685 /* find a connected connector: */
686 for (i = 0; i < resources->count_connectors; i++) {
687 connector = drmModeGetConnector(drm.fd, resources->connectors[i]);
688 if (connector->connection == DRM_MODE_CONNECTED)
689 break;
690 drmModeFreeConnector(connector);
691 connector = NULL;
692 }
693
694 if (connector == NULL) {
695 fprintf(stderr, "DRM: no connected connector\n");
696 exit(1);
697 }
698
699 encoder = drmModeGetEncoder(drm.fd, connector->encoder_id);
700 if (encoder == NULL) {
701 fprintf(stderr, "DRM: drmModeGetEncoder failed\n");
702 exit(1);
703 }
704
705 crtc = drmModeGetCrtc(drm.fd, encoder->crtc_id);
706 if (crtc == NULL) {
707 fprintf(stderr, "DRM: drmModeGetCrtc failed\n");
708 exit(1);
709 }
710
711 drm.crtc_id = encoder->crtc_id;
712 drm.connector_id = connector->connector_id;
713
714 /* init gbm */
715 gbm.dev = gbm_create_device(drm.fd);
716 if (gbm.dev == NULL) {
717 fprintf(stderr, "DRM: gbm_create_device failed\n");
718 exit(1);
719 }
720
721 gbm.surface = gbm_surface_create(gbm.dev,
722 crtc->width, crtc->height,
723 GBM_FORMAT_XRGB8888,
724 GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
725 if (!gbm.surface) {
726 fprintf(stderr, "DRM: failed to create gbm surface\n");
727 exit(1);
728 }
729
730 nativeDisplay = (EGLNativeDisplayType)gbm.dev;
731 nativeWindow = (NativeWindowType)gbm.surface;
732
733#if 0
734 drm.bo = gbm_surface_lock_front_buffer(gbm.surface);
735 if (drm.bo == NULL) {
736 fprintf(stderr, "DRM: no initial bo?\n");
737 exit(1);
738 }
739#endif
740
741 //ret = drmModeSetCrtc(drm.fd, drm.crtc_id, fb->fb_id, 0, 0,
742 // &drm.connector_id, 1, drm.mode);
743
744 return 0;
745}
746
747int8_t GetNativeWindow( uint16_t width, uint16_t height )
748{
749 /* already have nativeWindow, ignore width, height */
750 return 0;
751}
752
753static void
754drm_fb_destroy_callback(struct gbm_bo *bo, void *data)
755{
756 uint32_t fb_id = (uint32_t)(long)data;
757
758 if (fb_id)
759 drmModeRmFB(drm.fd, fb_id);
760}
761
762static uint32_t drm_fb_get_from_bo(struct gbm_bo *bo)
763{
764 uint32_t fb_id = (uint32_t)(long)gbm_bo_get_user_data(bo);
765 uint32_t width, height, stride, handle;
766 int ret;
767
768 if (fb_id)
769 return fb_id;
770
771 width = gbm_bo_get_width(bo);
772 height = gbm_bo_get_height(bo);
773 stride = gbm_bo_get_stride(bo);
774 handle = gbm_bo_get_handle(bo).u32;
775
776 ret = drmModeAddFB(drm.fd, width, height, 24, 32, stride, handle, &fb_id);
777 if (ret) {
778 printf("failed to create fb: %s\n", strerror(errno));
779 return 0;
780 }
781
782 gbm_bo_set_user_data(bo, (void *)(long)fb_id, drm_fb_destroy_callback);
783
784 return fb_id;
785}
786
787static void page_flip_handler(int fd, unsigned int frame,
788 unsigned int sec, unsigned int usec, void *data)
789{
790 int *waiting_for_flip = (int *)data;
791 *waiting_for_flip = 0;
792}
793
794/* to be called after eglSwapBuffers */
795static void drm_do_swap(void)
796{
797 drmEventContext evctx = { 0, };
798 int waiting_for_flip = 1;
799 struct gbm_bo *bo;
800 uint32_t fb_id;
801 fd_set fds;
802 int ret;
803
804 bo = gbm_surface_lock_front_buffer(gbm.surface);
805 fb_id = drm_fb_get_from_bo(bo);
806
807 ret = drmModePageFlip(drm.fd, drm.crtc_id, fb_id,
808 DRM_MODE_PAGE_FLIP_EVENT, &waiting_for_flip);
809 if (ret)
810 fprintf(stderr, "page flip error: %d %d\n", ret, errno);
811
812 FD_ZERO(&fds);
813 //FD_SET(0, &fds);
814 FD_SET(drm.fd, &fds);
815
816 evctx.version = DRM_EVENT_CONTEXT_VERSION;
817 evctx.page_flip_handler = page_flip_handler;
818
819 while (waiting_for_flip) {
820 ret = select(drm.fd + 1, &fds, NULL, NULL, NULL);
821 if (ret <= 0) {
822 perror("select");
823 return;
824#if 0
825 } else if (FD_ISSET(0, &fds)) {
826 printf("user interrupted!\n");
827 exit(1); // ?
828#endif
829 }
830 drmHandleEvent(drm.fd, &evctx);
831 }
832
833 gbm_surface_release_buffer(gbm.surface, bo);
834}
835
836#endif
837
451ab91e 838/** @brief Release the system's native display
839 */
840void FreeNativeDisplay( void )
841{
842}
843
844/** @brief Release the system's native window
845 */
846void FreeNativeWindow( void )
847{
848#if defined(WIZ) || defined(CAANOO)
849 if (nativeWindow != NULL) {
850 free( nativeWindow );
851 }
852 nativeWindow = NULL;
853#endif /* WIZ / CAANOO */
854}
855
856/** @brief Open any system specific resources
857 */
858void Platform_Open( void )
859{
860#if defined(PANDORA)
861 /* Pandora VSync */
862 fbdev = open( "/dev/fb0", O_RDONLY /* O_RDWR */ );
863 if ( fbdev < 0 ) {
864 printf( "EGLport ERROR: Couldn't open /dev/fb0 for Pandora Vsync\n" );
865 }
866#elif defined(RPI)
867 bcm_host_init();
868#endif /* PANDORA */
869}
870
871/** @brief Release any system specific resources
872 */
873void Platform_Close( void )
874{
875#if defined(PANDORA)
876 /* Pandora VSync */
877 close( fbdev );
878 fbdev = -1;
879#endif /* PANDORA */
880}
881
882/** @brief Check the systems vsync state
883 */
884void Platform_VSync( void )
885{
886#if defined(PANDORA)
887 /* Pandora VSync */
888 if (fbdev >= 0) {
889 int arg = 0;
890 ioctl( fbdev, FBIO_WAITFORVSYNC, &arg );
891 }
892#endif /* PANDORA */
893}
894
895/** @brief Get the system tick time (ms)
896 */
897uint32_t Platform_GetTicks( void )
898{
899 uint32_t ticks = 0;
900#if defined(USE_EGL_SDL)
901 ticks = SDL_GetTicks();
902#else
903 printf( "EGLport ERROR: SDL mode was not enabled in this compile!\n" );
904#endif
905 return ticks;
906}
daa7f9a3 907
908// vim:ts=4:sw=4:expandtab