forked from notaz/libpicofe
-
Notifications
You must be signed in to change notification settings - Fork 5
/
gl_platform.c
148 lines (116 loc) · 3.33 KB
/
gl_platform.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
#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>
#include <dlfcn.h>
static Display *x11display;
static Window x11window;
static DISPMANX_DISPLAY_HANDLE_T m_dispmanDisplay;
static EGL_DISPMANX_WINDOW_T m_nativeWindow;
static void *x11lib;
#define FPTR(f) typeof(f) * p##f
static FPTR(XGetGeometry);
static FPTR(XGetWindowAttributes);
static FPTR(XTranslateCoordinates);
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
pXGetGeometry(x11display, x11window, &root, &dx, &dy, &dw, &dh,
&dummy, &dummy);
pXGetWindowAttributes(x11display, root, &xattrs_root);
if (dw == xattrs_root.width && dh == xattrs_root.height)
return; // use fullscreen
pXTranslateCoordinates(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 = NULL;
x11window = 0;
x11lib = dlopen("libX11.so.6", RTLD_LAZY);
if (x11lib != NULL) {
pXGetGeometry = dlsym(x11lib, "XGetGeometry");
pXGetWindowAttributes = dlsym(x11lib, "XGetWindowAttributes");
pXTranslateCoordinates = dlsym(x11lib, "XTranslateCoordinates");
if (pXGetGeometry != NULL && pXGetWindowAttributes != NULL
&& pXTranslateCoordinates != NULL)
{
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();
if (x11lib) {
dlclose(x11lib);
x11lib = NULL;
}
x11display = NULL;
x11window = 0;
}
#else
int gl_platform_init(void **display, void **window, int *quirks)
{
return 0;
}
void gl_platform_finish(void)
{
}
#endif