add some VideCore/R-pi support code
authornotaz <notasas@gmail.com>
Sat, 22 Dec 2012 01:10:53 +0000 (03:10 +0200)
committernotaz <notasas@gmail.com>
Sun, 23 Dec 2012 00:14:35 +0000 (02:14 +0200)
gl.c
gl.h
gl_platform.c [new file with mode: 0644]
gl_platform.h [new file with mode: 0644]
plat_sdl.c

diff --git a/gl.c b/gl.c
index 92b39f7..44e0dd5 100644 (file)
--- a/gl.c
+++ b/gl.c
@@ -3,6 +3,7 @@
 
 #include <EGL/egl.h>
 #include <GLES/gl.h>
+#include "gl_platform.h"
 #include "gl.h"
 
 static EGLDisplay edpy;
@@ -29,7 +30,7 @@ static int gles_have_error(const char *name)
        return 0;
 }
 
-int gl_init(void *display, void *window)
+int gl_init(void *display, void *window, int *quirks)
 {
        EGLConfig ecfg = NULL;
        GLuint texture_name = 0;
@@ -42,6 +43,12 @@ int gl_init(void *display, void *window)
                EGL_NONE
        };
 
+       ret = gl_platform_init(&display, &window, quirks);
+       if (ret != 0) {
+               fprintf(stderr, "gl_platform_init failed with %d\n", ret);
+               goto out;
+       }
+
        tmp_texture_mem = calloc(1, 1024 * 512 * 2);
        if (tmp_texture_mem == NULL) {
                fprintf(stderr, "OOM\n");
@@ -177,4 +184,6 @@ void gl_finish(void)
        esfc = EGL_NO_SURFACE;
        eglTerminate(edpy);
        edpy = EGL_NO_DISPLAY;
+
+       gl_platform_finish();
 }
diff --git a/gl.h b/gl.h
index 9925dac..83b9e41 100644 (file)
--- a/gl.h
+++ b/gl.h
@@ -1,13 +1,23 @@
 #ifdef HAVE_GLES
 
-int gl_init(void *display, void *window);
+int gl_init(void *display, void *window, int *quirks);
 int gl_flip(const void *fb, int w, int h);
 void gl_finish(void);
 
 #else
 
-static __inline int gl_init(void *display, void *window) { return -1; }
-static __inline int gl_flip(const void *fb, int w, int h) { return -1; }
-static __inline void gl_finish(void) {}
+static __inline int gl_init(void *display, void *window, int *quirks)
+{
+  return -1;
+}
+static __inline int gl_flip(const void *fb, int w, int h)
+{
+  return -1;
+}
+static __inline void gl_finish(void)
+{
+}
 
 #endif
+
+#define GL_QUIRK_ACTIVATE_RECREATE 1
diff --git a/gl_platform.c b/gl_platform.c
new file mode 100644 (file)
index 0000000..74eea8f
--- /dev/null
@@ -0,0 +1,120 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <EGL/egl.h>
+#include <GLES/gl.h>
+
+#include "gl.h"
+#include "gl_platform.h"
+
+#ifdef VCOS_VERSION
+
+/*
+ * hacks for Broadcom VideoCore / Raspberry Pi..
+ * Why do I have to do this proprietary API stuff,
+ * couldn't they implement EGL properly? D:
+ */
+#include <bcm_host.h>
+#include <X11/Xlib.h>
+
+static Display *x11display;
+static Window x11window;
+static DISPMANX_DISPLAY_HANDLE_T m_dispmanDisplay;
+static EGL_DISPMANX_WINDOW_T m_nativeWindow;
+
+static void get_window_rect(VC_RECT_T *rect)
+{
+       XWindowAttributes xattrs_root;
+       uint32_t disp_w = 0, disp_h = 0;
+       int dx = 0, dy = 0;
+       unsigned int dw = 0, dh = 0, dummy;
+       Window root, dummyw;
+
+       graphics_get_display_size(0, &disp_w, &disp_h);
+       if (disp_w == 0 || disp_h == 0)
+               fprintf(stderr, "ERROR: graphics_get_display_size is broken\n");
+
+       // default to fullscreen
+       rect->x = rect->y = 0;
+       rect->width = disp_w;
+       rect->height = disp_h;
+
+       if (x11display == NULL || x11window == 0)
+               return; // use fullscreen
+
+       XGetGeometry(x11display, x11window, &root, &dx, &dy, &dw, &dh,
+               &dummy, &dummy);
+       XGetWindowAttributes(x11display, root, &xattrs_root);
+
+       if (dw == xattrs_root.width && dh == xattrs_root.height)
+               return; // use fullscreen
+
+       XTranslateCoordinates(x11display, x11window, root,
+               dx, dy, &dx, &dy, &dummyw);
+
+       // how to deal with that weird centering thing?
+       // this is not quite right..
+       dx += (disp_w - xattrs_root.width) / 2;
+       dy += (disp_h - xattrs_root.height) / 2;
+
+       rect->x = dx;
+       rect->y = dy;
+       rect->width = dw;
+       rect->height = dh;
+}
+
+static void submit_rect(void)
+{
+       DISPMANX_UPDATE_HANDLE_T m_dispmanUpdate;
+       DISPMANX_ELEMENT_HANDLE_T m_dispmanElement;
+       VC_RECT_T srcRect = { 0, }; // unused, but we segfault without passing it??
+       VC_RECT_T dstRect;
+
+       get_window_rect(&dstRect);
+
+       m_dispmanDisplay = vc_dispmanx_display_open(0);
+       m_dispmanUpdate = vc_dispmanx_update_start(0);
+
+       m_dispmanElement = vc_dispmanx_element_add(m_dispmanUpdate,
+               m_dispmanDisplay, 0, &dstRect, 0, &srcRect,
+               DISPMANX_PROTECTION_NONE, 0, 0, DISPMANX_NO_ROTATE);
+
+       m_nativeWindow.element = m_dispmanElement;
+       m_nativeWindow.width = dstRect.width;
+       m_nativeWindow.height = dstRect.height;
+
+       vc_dispmanx_update_submit_sync(m_dispmanUpdate);
+}
+
+int gl_platform_init(void **display, void **window, int *quirks)
+{
+       x11display = *display;
+       x11window = (Window)*window;
+
+       bcm_host_init();
+       submit_rect();
+
+       *display = EGL_DEFAULT_DISPLAY;
+       *window = &m_nativeWindow;
+       *quirks |= GL_QUIRK_ACTIVATE_RECREATE;
+
+       return 0;
+}
+
+void gl_platform_finish(void)
+{
+       vc_dispmanx_display_close(m_dispmanDisplay);
+       bcm_host_deinit();
+}
+
+#else
+
+int gl_platform_init(void **display, void **window, int *quirks)
+{
+       return 0;
+}
+
+void gl_platform_finish(void)
+{
+}
+
+#endif
diff --git a/gl_platform.h b/gl_platform.h
new file mode 100644 (file)
index 0000000..3e0bbb1
--- /dev/null
@@ -0,0 +1,2 @@
+int gl_platform_init(void **display, void **window, int *quirks);
+void gl_platform_finish(void);
index 609d267..2508d1c 100644 (file)
@@ -30,6 +30,7 @@ static int fs_w, fs_h;
 static int old_fullscreen;
 static int vout_mode_overlay = -1, vout_mode_gl = -1;
 static void *display, *window;
+static int gl_quirks;
 
 /* w, h is layer resolution */
 int plat_sdl_change_video_mode(int w, int h, int force)
@@ -96,7 +97,7 @@ int plat_sdl_change_video_mode(int w, int h, int force)
     }
   }
   else if (plat_target.vout_method == vout_mode_gl) {
-    plat_sdl_gl_active = (gl_init(display, window) == 0);
+    plat_sdl_gl_active = (gl_init(display, window, &gl_quirks) == 0);
     if (!plat_sdl_gl_active) {
       fprintf(stderr, "warning: could not init GL.\n");
       plat_target.vout_method = 0;
@@ -139,6 +140,10 @@ void plat_sdl_event_handler(void *event_)
         SDL_DisplayYUVOverlay(plat_sdl_overlay, &dstrect);
       }
       else if (plat_sdl_gl_active) {
+        if (gl_quirks & GL_QUIRK_ACTIVATE_RECREATE) {
+          gl_finish();
+          plat_sdl_gl_active = (gl_init(display, window, &gl_quirks) == 0);
+        }
         gl_flip(NULL, 0, 0);
       }
       // else SDL takes care of it
@@ -220,7 +225,7 @@ int plat_sdl_init(void)
   display = wminfo.info.x11.display;
   window = (void *)wminfo.info.x11.window;
 
-  ret = gl_init(display, window);
+  ret = gl_init(display, window, &gl_quirks);
   if (ret == 0) {
     gl_works = 1;
     gl_finish();