drm/gl context stuff drm
authornotaz <notasas@gmail.com>
Wed, 13 Aug 2014 14:04:10 +0000 (16:04 +0200)
committernotaz <notasas@gmail.com>
Wed, 13 Aug 2014 14:04:10 +0000 (16:04 +0200)
source/mupen64plus-core/src/api/eglport.cpp

index c1494ff..c95a785 100755 (executable)
@@ -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 <xf86drm.h>
+#include <xf86drmMode.h>
+#include <gbm.h>
+#include <errno.h>
+
+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