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