4 * Copyright (C) 2011-2013 Scott R. Smith
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:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
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
34 #if defined(USE_EGL_SDL)
36 #include "SDL_syswm.h"
37 SDL_SysWMinfo sysWmInfo; /** Holds our X Display/Window information */
38 #endif /* USE_EGL_SDL */
40 #if defined(PANDORA) /* Pandora VSync Support */
43 #include <sys/ioctl.h>
46 #ifndef FBIO_WAITFORVSYNC
47 #define FBIO_WAITFORVSYNC _IOW('F', 0x20, __u32)
56 RENDER_RAW=0, /** Sets render mode to raw or framebuffer mode. */
57 RENDER_SDL, /** Sets render mode to X11/SDL mode. */
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. */
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 */
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 */
88 uint32_t fpsCount = 0; /** Total number of frames counted */
89 uint32_t fpsTime = 0; /** Start time of frame count measurment */
91 int8_t eglColorbits = 0;
92 int8_t eglDepthbits = 0;
93 int8_t eglStencilbits = 0;
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 );
102 int8_t GetNativeDisplay ( void );
103 int8_t GetNativeWindow ( uint16_t width, uint16_t height );
104 void FreeNativeDisplay ( void );
105 void FreeNativeWindow ( void );
107 void Platform_Open ( void );
108 void Platform_Close ( void );
109 void Platform_VSync ( void );
110 uint32_t Platform_GetTicks ( void );
112 static void drm_do_swap(void);
114 /** @brief Release all EGL and system resources
116 void EGL_Close( void )
118 /* Release EGL resources */
119 if (eglDisplay != NULL)
121 peglMakeCurrent( eglDisplay, NULL, NULL, EGL_NO_CONTEXT );
122 if (eglContext != NULL) {
123 peglDestroyContext( eglDisplay, eglContext );
125 if (eglSurface != NULL) {
126 peglDestroySurface( eglDisplay, eglSurface );
128 peglTerminate( eglDisplay );
139 /* Release platform resources */
144 CheckEGLErrors( __FILE__, __LINE__ );
146 printf( "EGLport: Closed\n" );
149 /** @brief Swap the surface buffer onto the display
151 void EGL_SwapBuffers( void )
153 if (eglSettings[CFG_VSYNC] != 0) {
157 peglSwapBuffers( eglDisplay, eglSurface );
160 if (eglSettings[CFG_FPS] != 0) {
163 if (fpsTime - Platform_GetTicks() >= 1000)
165 printf( "EGLport: %d fps\n", fpsCount );
166 fpsTime = Platform_GetTicks();
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
177 int8_t EGL_Open( uint16_t width, uint16_t height )
179 EGLint eglMajorVer, eglMinorVer;
181 uint32_t configIndex = 0;
184 static const EGLint contextAttribs[] =
186 #if defined(USE_GLES2)
187 EGL_CONTEXT_CLIENT_VERSION, 2,
193 printf( "EGLport Warning: DEBUG is enabled which may effect performance\n" );
196 /* Check that system is not open */
197 if (eglDisplay != NULL || eglContext != NULL || eglSurface != NULL)
199 printf( "EGLport ERROR: EGL system is already open!\n" );
203 /* Check for the cfg file to alternative settings */
204 OpenCfg( "eglport.cfg" );
206 /* Setup any platform specific bits */
209 printf( "EGLport: Opening EGL display\n" );
210 if (GetNativeDisplay() != 0)
212 printf( "EGLport ERROR: Unable to obtain native display!\n" );
216 eglDisplay = peglGetDisplay( nativeDisplay );
217 if (eglDisplay == EGL_NO_DISPLAY)
219 CheckEGLErrors( __FILE__, __LINE__ );
220 printf( "EGLport ERROR: Unable to create EGL display.\n" );
224 printf( "EGLport: Initializing\n" );
225 result = peglInitialize( eglDisplay, &eglMajorVer, &eglMinorVer );
226 if (result != EGL_TRUE )
228 CheckEGLErrors( __FILE__, __LINE__ );
229 printf( "EGLport ERROR: Unable to initialize EGL display.\n" );
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 );
242 if (FindEGLConfigs() != 0)
244 printf( "EGLport ERROR: Unable to configure EGL. See previous error.\n" );
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 )
255 CheckEGLErrors( __FILE__, __LINE__ );
256 printf( "EGLport ERROR: Could not bind EGL API.\n" );
259 #endif /* EGL_VERSION_1_2 */
261 printf( "EGLport: Creating Context\n" );
262 eglContext = peglCreateContext( eglDisplay, eglConfigs[configIndex], NULL, contextAttribs );
263 if (eglContext == EGL_NO_CONTEXT)
265 CheckEGLErrors( __FILE__, __LINE__ );
266 printf( "EGLport ERROR: Unable to create GLES context!\n");
270 printf( "EGLport: Creating window surface\n" );
271 if (GetNativeWindow( width, height ) != 0)
273 printf( "EGLport ERROR: Unable to obtain native window!\n" );
277 eglSurface = peglCreateWindowSurface( eglDisplay, eglConfigs[configIndex], nativeWindow, 0 );
278 if (eglSurface == EGL_NO_SURFACE)
280 CheckEGLErrors( __FILE__, __LINE__ );
281 printf( "EGLport ERROR: Unable to create EGL surface!\n" );
285 printf( "EGLport: Making Current\n" );
286 result = peglMakeCurrent( eglDisplay, eglSurface, eglSurface, eglContext );
287 if (result != EGL_TRUE)
289 CheckEGLErrors( __FILE__, __LINE__ );
290 printf( "EGLport ERROR: Unable to make GLES context current\n" );
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;
304 printf( "EGLport: Setting swap interval\n" );
305 peglSwapInterval( eglDisplay, (eglSettings[CFG_VSYNC] > 0) ? 1 : 0 );
307 printf( "EGLport: Complete\n" );
309 CheckEGLErrors( __FILE__, __LINE__ );
314 /** @brief Read settings that configure how to use EGL
315 * @param file : name of the config file
317 void OpenCfg ( const char* file )
319 #define MAX_STRING 20
323 char* location = NULL;
324 char eglStrings[CFG_TOTAL][MAX_STRING];
325 char buffer[MAX_SIZE];
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 );
339 //#if defined(USE_EGL_SDL)
340 // eglSettings[CFG_MODE] = RENDER_SDL;
342 eglSettings[CFG_MODE] = RENDER_RAW;
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;
356 fp = fopen( file, "r");
359 while (fgets( buffer, MAX_SIZE, fp ) != NULL)
361 for (i=0; i<CFG_TOTAL; i++)
363 location = strstr( buffer, eglStrings[i] );
364 if (location != NULL)
366 eglSettings[i] = atol( location+strlen( eglStrings[i] ) );
367 printf( "EGLport: %s set to %d.\n", eglStrings[i], eglSettings[i] );
377 printf( "EGL NOTICE: Unable to read ini settings from file '%s'. Using defaults\n", file );
381 /** @brief Find a EGL configuration tht matches the defined attributes
382 * @return : 0 if the function passed, else 1
384 int8_t FindEGLConfigs( void )
388 EGLint ConfigAttribs[23];
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 */
420 result = peglChooseConfig( eglDisplay, ConfigAttribs, eglConfigs, totalConfigsIn, &totalConfigsFound );
421 if (result != EGL_TRUE || totalConfigsFound == 0)
423 CheckEGLErrors( __FILE__, __LINE__ );
424 printf( "EGLport ERROR: Unable to query for available configs, found %d.\n", totalConfigsFound );
427 printf( "EGLport: Found %d available configs\n", totalConfigsFound );
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
437 int8_t CheckEGLErrors( const char* file, uint16_t line )
440 const char* errortext;
441 const char* description;
443 error = eglGetError();
445 if (error != EGL_SUCCESS && error != 0)
449 case EGL_NOT_INITIALIZED:
450 errortext = "EGL_NOT_INITIALIZED.";
451 description = "EGL is not or could not be initialized, for the specified display.";
454 errortext = "EGL_BAD_ACCESS EGL";
455 description = "cannot access a requested resource (for example, a context is bound in another thread).";
458 errortext = "EGL_BAD_ALLOC EGL";
459 description = "failed to allocate resources for the requested operation.";
461 case EGL_BAD_ATTRIBUTE:
462 errortext = "EGL_BAD_ATTRIBUTE";
463 description = "An unrecognized attribute or attribute value was passed in anattribute list.";
466 errortext = "EGL_BAD_CONFIG";
467 description = "An EGLConfig argument does not name a valid EGLConfig.";
469 case EGL_BAD_CONTEXT:
470 errortext = "EGL_BAD_CONTEXT";
471 description = "An EGLContext argument does not name a valid EGLContext.";
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.";
477 case EGL_BAD_DISPLAY:
478 errortext = "EGL_BAD_DISPLAY";
479 description = "An EGLDisplay argument does not name a valid EGLDisplay.";
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.";
485 case EGL_BAD_NATIVE_PIXMAP:
486 errortext = "EGL_BAD_NATIVE_PIXMAP";
487 description = "An EGLNativePixmapType argument does not refer to a validnative pixmap.";
489 case EGL_BAD_NATIVE_WINDOW:
490 errortext = "EGL_BAD_NATIVE_WINDOW";
491 description = "An EGLNativeWindowType argument does not refer to a validnative window.";
493 case EGL_BAD_PARAMETER:
494 errortext = "EGL_BAD_PARAMETER";
495 description = "One or more argument values are invalid.";
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";
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.";
506 errortext = "Unknown EGL Error";
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 );
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
524 int8_t GetNativeDisplay( void )
526 if (eglSettings[CFG_MODE] == RENDER_RAW) /* RAW FB mode */
528 printf( "EGLport: Using EGL_DEFAULT_DISPLAY\n" );
529 nativeDisplay = EGL_DEFAULT_DISPLAY;
531 else if (eglSettings[CFG_MODE] == RENDER_SDL) /* SDL/X11 mode */
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;
539 if (nativeDisplay == 0)
541 printf( "EGLport ERROR: unable to get display!\n" );
545 printf( "EGLport ERROR: SDL mode was not enabled in this compile!\n" );
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
557 int8_t GetNativeWindow( uint16_t width, uint16_t height )
561 #if defined(WIZ) || defined(CAANOO)
563 nativeWindow = (NativeWindowType)malloc(16*1024);
565 if(nativeWindow == NULL) {
566 printf( "EGLport ERROR: Memory for window Failed\n" );
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;
581 /* create an EGL window surface */
582 result = graphics_get_display_size(0 /* LCD */, &screen_width, &screen_height);
584 printf( "EGLport ERROR: RPi graphicget_display_size failed\n" );
590 dst_rect.width = screen_width;
591 dst_rect.height = screen_height;
595 src_rect.width = width << 16;
596 src_rect.height = height << 16;
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*/);
604 nativewindow.element = dispman_element;
605 nativewindow.width = screen_width;
606 nativewindow.height = screen_height;
607 vc_dispmanx_update_submit_sync( dispman_update );
609 nativeWindow = (NativeWindowType)&nativewindow;
613 if (eglSettings[CFG_MODE] == RENDER_RAW) /* RAW FB mode */
617 else if(eglSettings[CFG_MODE] == RENDER_SDL) /* SDL/X11 mode */
619 #if defined(USE_EGL_SDL)
620 /* SDL_GetWMInfo is populated when display was opened */
621 nativeWindow = (NativeWindowType)sysWmInfo.info.x11.window;
623 if (nativeWindow == 0)
625 printf( "EGLport ERROR: unable to get window!\n" );
629 printf( "EGLport ERROR: SDL mode was not enabled in this compile!\n" );
634 printf( "EGLport ERROR: Unknown EGL render mode %d!\n", eglSettings[CFG_MODE] );
638 #endif /* WIZ / CAANOO */
646 #include <xf86drmMode.h>
651 struct gbm_device *dev;
652 struct gbm_surface *surface;
658 uint32_t connector_id;
662 int8_t GetNativeDisplay( void )
664 drmModeRes *resources;
665 drmModeConnector *connector;
666 drmModeEncoder *encoder;
673 drm.fd = drmOpen("omapdrm", NULL);
675 perror("DRM: drmOpen omapdrm");
679 resources = drmModeGetResources(drm.fd);
680 if (resources == NULL) {
681 perror("DRM: drmModeGetResources");
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)
690 drmModeFreeConnector(connector);
694 if (connector == NULL) {
695 fprintf(stderr, "DRM: no connected connector\n");
699 encoder = drmModeGetEncoder(drm.fd, connector->encoder_id);
700 if (encoder == NULL) {
701 fprintf(stderr, "DRM: drmModeGetEncoder failed\n");
705 crtc = drmModeGetCrtc(drm.fd, encoder->crtc_id);
707 fprintf(stderr, "DRM: drmModeGetCrtc failed\n");
711 drm.crtc_id = encoder->crtc_id;
712 drm.connector_id = connector->connector_id;
715 gbm.dev = gbm_create_device(drm.fd);
716 if (gbm.dev == NULL) {
717 fprintf(stderr, "DRM: gbm_create_device failed\n");
721 gbm.surface = gbm_surface_create(gbm.dev,
722 crtc->width, crtc->height,
724 GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
726 fprintf(stderr, "DRM: failed to create gbm surface\n");
730 nativeDisplay = (EGLNativeDisplayType)gbm.dev;
731 nativeWindow = (NativeWindowType)gbm.surface;
734 drm.bo = gbm_surface_lock_front_buffer(gbm.surface);
735 if (drm.bo == NULL) {
736 fprintf(stderr, "DRM: no initial bo?\n");
741 //ret = drmModeSetCrtc(drm.fd, drm.crtc_id, fb->fb_id, 0, 0,
742 // &drm.connector_id, 1, drm.mode);
747 int8_t GetNativeWindow( uint16_t width, uint16_t height )
749 /* already have nativeWindow, ignore width, height */
754 drm_fb_destroy_callback(struct gbm_bo *bo, void *data)
756 uint32_t fb_id = (uint32_t)(long)data;
759 drmModeRmFB(drm.fd, fb_id);
762 static uint32_t drm_fb_get_from_bo(struct gbm_bo *bo)
764 uint32_t fb_id = (uint32_t)(long)gbm_bo_get_user_data(bo);
765 uint32_t width, height, stride, handle;
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;
776 ret = drmModeAddFB(drm.fd, width, height, 24, 32, stride, handle, &fb_id);
778 printf("failed to create fb: %s\n", strerror(errno));
782 gbm_bo_set_user_data(bo, (void *)(long)fb_id, drm_fb_destroy_callback);
787 static void page_flip_handler(int fd, unsigned int frame,
788 unsigned int sec, unsigned int usec, void *data)
790 int *waiting_for_flip = (int *)data;
791 *waiting_for_flip = 0;
794 /* to be called after eglSwapBuffers */
795 static void drm_do_swap(void)
797 drmEventContext evctx = { 0, };
798 int waiting_for_flip = 1;
804 bo = gbm_surface_lock_front_buffer(gbm.surface);
805 fb_id = drm_fb_get_from_bo(bo);
807 ret = drmModePageFlip(drm.fd, drm.crtc_id, fb_id,
808 DRM_MODE_PAGE_FLIP_EVENT, &waiting_for_flip);
810 fprintf(stderr, "page flip error: %d %d\n", ret, errno);
814 FD_SET(drm.fd, &fds);
816 evctx.version = DRM_EVENT_CONTEXT_VERSION;
817 evctx.page_flip_handler = page_flip_handler;
819 while (waiting_for_flip) {
820 ret = select(drm.fd + 1, &fds, NULL, NULL, NULL);
825 } else if (FD_ISSET(0, &fds)) {
826 printf("user interrupted!\n");
830 drmHandleEvent(drm.fd, &evctx);
833 gbm_surface_release_buffer(gbm.surface, bo);
838 /** @brief Release the system's native display
840 void FreeNativeDisplay( void )
844 /** @brief Release the system's native window
846 void FreeNativeWindow( void )
848 #if defined(WIZ) || defined(CAANOO)
849 if (nativeWindow != NULL) {
850 free( nativeWindow );
853 #endif /* WIZ / CAANOO */
856 /** @brief Open any system specific resources
858 void Platform_Open( void )
862 fbdev = open( "/dev/fb0", O_RDONLY /* O_RDWR */ );
864 printf( "EGLport ERROR: Couldn't open /dev/fb0 for Pandora Vsync\n" );
871 /** @brief Release any system specific resources
873 void Platform_Close( void )
882 /** @brief Check the systems vsync state
884 void Platform_VSync( void )
890 ioctl( fbdev, FBIO_WAITFORVSYNC, &arg );
895 /** @brief Get the system tick time (ms)
897 uint32_t Platform_GetTicks( void )
900 #if defined(USE_EGL_SDL)
901 ticks = SDL_GetTicks();
903 printf( "EGLport ERROR: SDL mode was not enabled in this compile!\n" );
908 // vim:ts=4:sw=4:expandtab