From daa7f9a3c3de741eb09e04ec97704bca7bc18ab6 Mon Sep 17 00:00:00 2001 From: notaz Date: Wed, 13 Aug 2014 16:04:10 +0200 Subject: [PATCH] drm/gl context stuff --- source/mupen64plus-core/src/api/eglport.cpp | 202 ++++++++++++++++++++ 1 file changed, 202 insertions(+) diff --git a/source/mupen64plus-core/src/api/eglport.cpp b/source/mupen64plus-core/src/api/eglport.cpp index c1494ff..c95a785 100755 --- a/source/mupen64plus-core/src/api/eglport.cpp +++ b/source/mupen64plus-core/src/api/eglport.cpp @@ -109,6 +109,8 @@ void Platform_Close ( void ); void Platform_VSync ( void ); uint32_t Platform_GetTicks ( void ); +static void drm_do_swap(void); + /** @brief Release all EGL and system resources */ void EGL_Close( void ) @@ -153,6 +155,7 @@ void EGL_SwapBuffers( void ) } peglSwapBuffers( eglDisplay, eglSurface ); + drm_do_swap(); if (eglSettings[CFG_FPS] != 0) { fpsCount++; @@ -512,6 +515,8 @@ int8_t CheckEGLErrors( const char* file, uint16_t line ) return 0; } +#if 0 + /** @brief Obtain a reference to the system's native display * @param window : pointer to save the display reference * @return : 0 if the function passed, else 1 @@ -635,6 +640,201 @@ int8_t GetNativeWindow( uint16_t width, uint16_t height ) return 0; } +#else + +#include +#include +#include +#include + +static struct { + struct gbm_device *dev; + struct gbm_surface *surface; +} gbm; + +static struct { + int fd; + uint32_t crtc_id; + uint32_t connector_id; + //struct gbm_bo *bo; +} drm; + +int8_t GetNativeDisplay( void ) +{ + drmModeRes *resources; + drmModeConnector *connector; + drmModeEncoder *encoder; + drmModeCrtc *crtc; + int i; + + errno = 0; + + /* init drm */ + drm.fd = drmOpen("omapdrm", NULL); + if (drm.fd < 0) { + perror("DRM: drmOpen omapdrm"); + exit(1); + } + + resources = drmModeGetResources(drm.fd); + if (resources == NULL) { + perror("DRM: drmModeGetResources"); + exit(1); + } + + /* find a connected connector: */ + for (i = 0; i < resources->count_connectors; i++) { + connector = drmModeGetConnector(drm.fd, resources->connectors[i]); + if (connector->connection == DRM_MODE_CONNECTED) + break; + drmModeFreeConnector(connector); + connector = NULL; + } + + if (connector == NULL) { + fprintf(stderr, "DRM: no connected connector\n"); + exit(1); + } + + encoder = drmModeGetEncoder(drm.fd, connector->encoder_id); + if (encoder == NULL) { + fprintf(stderr, "DRM: drmModeGetEncoder failed\n"); + exit(1); + } + + crtc = drmModeGetCrtc(drm.fd, encoder->crtc_id); + if (crtc == NULL) { + fprintf(stderr, "DRM: drmModeGetCrtc failed\n"); + exit(1); + } + + drm.crtc_id = encoder->crtc_id; + drm.connector_id = connector->connector_id; + + /* init gbm */ + gbm.dev = gbm_create_device(drm.fd); + if (gbm.dev == NULL) { + fprintf(stderr, "DRM: gbm_create_device failed\n"); + exit(1); + } + + gbm.surface = gbm_surface_create(gbm.dev, + crtc->width, crtc->height, + GBM_FORMAT_XRGB8888, + GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING); + if (!gbm.surface) { + fprintf(stderr, "DRM: failed to create gbm surface\n"); + exit(1); + } + + nativeDisplay = (EGLNativeDisplayType)gbm.dev; + nativeWindow = (NativeWindowType)gbm.surface; + +#if 0 + drm.bo = gbm_surface_lock_front_buffer(gbm.surface); + if (drm.bo == NULL) { + fprintf(stderr, "DRM: no initial bo?\n"); + exit(1); + } +#endif + + //ret = drmModeSetCrtc(drm.fd, drm.crtc_id, fb->fb_id, 0, 0, + // &drm.connector_id, 1, drm.mode); + + return 0; +} + +int8_t GetNativeWindow( uint16_t width, uint16_t height ) +{ + /* already have nativeWindow, ignore width, height */ + return 0; +} + +static void +drm_fb_destroy_callback(struct gbm_bo *bo, void *data) +{ + uint32_t fb_id = (uint32_t)(long)data; + + if (fb_id) + drmModeRmFB(drm.fd, fb_id); +} + +static uint32_t drm_fb_get_from_bo(struct gbm_bo *bo) +{ + uint32_t fb_id = (uint32_t)(long)gbm_bo_get_user_data(bo); + uint32_t width, height, stride, handle; + int ret; + + if (fb_id) + return fb_id; + + width = gbm_bo_get_width(bo); + height = gbm_bo_get_height(bo); + stride = gbm_bo_get_stride(bo); + handle = gbm_bo_get_handle(bo).u32; + + ret = drmModeAddFB(drm.fd, width, height, 24, 32, stride, handle, &fb_id); + if (ret) { + printf("failed to create fb: %s\n", strerror(errno)); + return 0; + } + + gbm_bo_set_user_data(bo, (void *)(long)fb_id, drm_fb_destroy_callback); + + return fb_id; +} + +static void page_flip_handler(int fd, unsigned int frame, + unsigned int sec, unsigned int usec, void *data) +{ + int *waiting_for_flip = (int *)data; + *waiting_for_flip = 0; +} + +/* to be called after eglSwapBuffers */ +static void drm_do_swap(void) +{ + drmEventContext evctx = { 0, }; + int waiting_for_flip = 1; + struct gbm_bo *bo; + uint32_t fb_id; + fd_set fds; + int ret; + + bo = gbm_surface_lock_front_buffer(gbm.surface); + fb_id = drm_fb_get_from_bo(bo); + + ret = drmModePageFlip(drm.fd, drm.crtc_id, fb_id, + DRM_MODE_PAGE_FLIP_EVENT, &waiting_for_flip); + if (ret) + fprintf(stderr, "page flip error: %d %d\n", ret, errno); + + FD_ZERO(&fds); + //FD_SET(0, &fds); + FD_SET(drm.fd, &fds); + + evctx.version = DRM_EVENT_CONTEXT_VERSION; + evctx.page_flip_handler = page_flip_handler; + + while (waiting_for_flip) { + ret = select(drm.fd + 1, &fds, NULL, NULL, NULL); + if (ret <= 0) { + perror("select"); + return; +#if 0 + } else if (FD_ISSET(0, &fds)) { + printf("user interrupted!\n"); + exit(1); // ? +#endif + } + drmHandleEvent(drm.fd, &evctx); + } + + gbm_surface_release_buffer(gbm.surface, bo); +} + +#endif + /** @brief Release the system's native display */ void FreeNativeDisplay( void ) @@ -704,3 +904,5 @@ uint32_t Platform_GetTicks( void ) #endif return ticks; } + +// vim:ts=4:sw=4:expandtab -- 2.39.2