fix a buffer overflow
[libpicofe.git] / gl_platform.c
CommitLineData
0d645bc5 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>
cceadf4c 18#include <dlfcn.h>
0d645bc5 19
20static Display *x11display;
21static Window x11window;
22static DISPMANX_DISPLAY_HANDLE_T m_dispmanDisplay;
23static EGL_DISPMANX_WINDOW_T m_nativeWindow;
24
cceadf4c 25static void *x11lib;
26#define FPTR(f) typeof(f) * p##f
27static FPTR(XGetGeometry);
28static FPTR(XGetWindowAttributes);
29static FPTR(XTranslateCoordinates);
30
0d645bc5 31static 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
cceadf4c 51 pXGetGeometry(x11display, x11window, &root, &dx, &dy, &dw, &dh,
0d645bc5 52 &dummy, &dummy);
cceadf4c 53 pXGetWindowAttributes(x11display, root, &xattrs_root);
0d645bc5 54
55 if (dw == xattrs_root.width && dh == xattrs_root.height)
56 return; // use fullscreen
57
cceadf4c 58 pXTranslateCoordinates(x11display, x11window, root,
0d645bc5 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
72static 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
95int gl_platform_init(void **display, void **window, int *quirks)
96{
cceadf4c 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 }
0d645bc5 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
123void gl_platform_finish(void)
124{
125 vc_dispmanx_display_close(m_dispmanDisplay);
126 bcm_host_deinit();
cceadf4c 127
128 if (x11lib) {
129 dlclose(x11lib);
130 x11lib = NULL;
131 }
132
133 x11display = NULL;
134 x11window = 0;
0d645bc5 135}
136
137#else
138
139int gl_platform_init(void **display, void **window, int *quirks)
140{
141 return 0;
142}
143
144void gl_platform_finish(void)
145{
146}
147
148#endif