gl: clear w, h on reinit
[libpicofe.git] / gl_platform.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <EGL/egl.h>
4 #include <GLES/gl.h>
5
6 #include "gl.h"
7 #include "gl_platform.h"
8
9 #ifdef VCOS_VERSION
10
11 /*
12  * hacks for Broadcom VideoCore / Raspberry Pi..
13  * Why do I have to do this proprietary API stuff,
14  * couldn't they implement EGL properly? D:
15  */
16 #include <bcm_host.h>
17 #include <X11/Xlib.h>
18 #include <dlfcn.h>
19
20 static Display *x11display;
21 static Window x11window;
22 static DISPMANX_DISPLAY_HANDLE_T m_dispmanDisplay;
23 static EGL_DISPMANX_WINDOW_T m_nativeWindow;
24
25 static void *x11lib;
26 #define FPTR(f) typeof(f) * p##f
27 static FPTR(XGetGeometry);
28 static FPTR(XGetWindowAttributes);
29 static FPTR(XTranslateCoordinates);
30
31 static void get_window_rect(VC_RECT_T *rect)
32 {
33         XWindowAttributes xattrs_root;
34         uint32_t disp_w = 0, disp_h = 0;
35         int dx = 0, dy = 0;
36         unsigned int dw = 0, dh = 0, dummy;
37         Window root, dummyw;
38
39         graphics_get_display_size(0, &disp_w, &disp_h);
40         if (disp_w == 0 || disp_h == 0)
41                 fprintf(stderr, "ERROR: graphics_get_display_size is broken\n");
42
43         // default to fullscreen
44         rect->x = rect->y = 0;
45         rect->width = disp_w;
46         rect->height = disp_h;
47
48         if (x11display == NULL || x11window == 0)
49                 return; // use fullscreen
50
51         pXGetGeometry(x11display, x11window, &root, &dx, &dy, &dw, &dh,
52                 &dummy, &dummy);
53         pXGetWindowAttributes(x11display, root, &xattrs_root);
54
55         if (dw == xattrs_root.width && dh == xattrs_root.height)
56                 return; // use fullscreen
57
58         pXTranslateCoordinates(x11display, x11window, root,
59                 dx, dy, &dx, &dy, &dummyw);
60
61         // how to deal with that weird centering thing?
62         // this is not quite right..
63         dx += (disp_w - xattrs_root.width) / 2;
64         dy += (disp_h - xattrs_root.height) / 2;
65
66         rect->x = dx;
67         rect->y = dy;
68         rect->width = dw;
69         rect->height = dh;
70 }
71
72 static void submit_rect(void)
73 {
74         DISPMANX_UPDATE_HANDLE_T m_dispmanUpdate;
75         DISPMANX_ELEMENT_HANDLE_T m_dispmanElement;
76         VC_RECT_T srcRect = { 0, }; // unused, but we segfault without passing it??
77         VC_RECT_T dstRect;
78
79         get_window_rect(&dstRect);
80
81         m_dispmanDisplay = vc_dispmanx_display_open(0);
82         m_dispmanUpdate = vc_dispmanx_update_start(0);
83
84         m_dispmanElement = vc_dispmanx_element_add(m_dispmanUpdate,
85                 m_dispmanDisplay, 0, &dstRect, 0, &srcRect,
86                 DISPMANX_PROTECTION_NONE, 0, 0, DISPMANX_NO_ROTATE);
87
88         m_nativeWindow.element = m_dispmanElement;
89         m_nativeWindow.width = dstRect.width;
90         m_nativeWindow.height = dstRect.height;
91
92         vc_dispmanx_update_submit_sync(m_dispmanUpdate);
93 }
94
95 int gl_platform_init(void **display, void **window, int *quirks)
96 {
97         x11display = NULL;
98         x11window = 0;
99
100         x11lib = dlopen("libX11.so.6", RTLD_LAZY);
101         if (x11lib != NULL) {
102                 pXGetGeometry = dlsym(x11lib, "XGetGeometry");
103                 pXGetWindowAttributes = dlsym(x11lib, "XGetWindowAttributes");
104                 pXTranslateCoordinates = dlsym(x11lib, "XTranslateCoordinates");
105                 if (pXGetGeometry != NULL && pXGetWindowAttributes != NULL
106                     && pXTranslateCoordinates != NULL)
107                 {
108                         x11display = *display;
109                         x11window = (Window)*window;
110                 }
111         }
112
113         bcm_host_init();
114         submit_rect();
115
116         *display = EGL_DEFAULT_DISPLAY;
117         *window = &m_nativeWindow;
118         *quirks |= GL_QUIRK_ACTIVATE_RECREATE;
119
120         return 0;
121 }
122
123 void gl_platform_finish(void)
124 {
125         vc_dispmanx_display_close(m_dispmanDisplay);
126         bcm_host_deinit();
127
128         if (x11lib) {
129                 dlclose(x11lib);
130                 x11lib = NULL;
131         }
132
133         x11display = NULL;
134         x11window = 0;
135 }
136
137 #else
138
139 int gl_platform_init(void **display, void **window, int *quirks)
140 {
141         return 0;
142 }
143
144 void gl_platform_finish(void)
145 {
146 }
147
148 #endif