1 #include "HalideRuntime.h"
2
3 extern "C" {
4
5 typedef void *GLXContext;
6 typedef void *GLXFBConfig;
7 typedef int Bool;
8 typedef void Display;
9
10 typedef void (*__GLXextFuncPtr)(void);
11 extern __GLXextFuncPtr glXGetProcAddressARB(const char *);
12 extern void *XOpenDisplay(void *);
13 extern int XDefaultScreen(void *);
14 extern int glXQueryExtension(void *, void *, void *);
15 extern const char *glXQueryExtensionsString(Display *dpy, int screen);
16 extern GLXContext glXCreateNewContext(void *, void *, int, void *, int);
17 extern void **glXChooseFBConfig(void *, int, const int *, int *);
18 extern unsigned long glXCreatePbuffer(void *, void *, const int *);
19 extern int XFree(void *);
20 extern int XSync(void *, int);
21 extern GLXContext glXGetCurrentContext();
22 extern int glXMakeContextCurrent(void *, unsigned long, unsigned long, void *);
23
24 #define GLX_RENDER_TYPE 0x8011
25 #define GLX_RGBA_TYPE 0x8014
26 #define GLX_RGBA_BIT 1
27 #define GLX_RED_SIZE 8
28 #define GLX_GREEN_SIZE 8
29 #define GLX_BLUE_SIZE 8
30 #define GLX_ALPHA_SIZE 8
31
32 #define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091
33 #define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092
34 typedef GLXContext (*glXCreateContextAttribsARBProc)(Display *, GLXFBConfig, GLXContext, Bool, const int *);
35
36 } // extern "C"
37
38 namespace Halide {
39 namespace Runtime {
40 namespace Internal {
41
42 // Helper to check for extension string presence. Adapted from:
43 // http://www.opengl.org/resources/features/OGLextensions/
glx_extension_supported(const char * extlist,const char * extension)44 WEAK bool glx_extension_supported(const char *extlist, const char *extension) {
45 // Extension names should not have spaces.
46 if (strchr(extension, ' ') != NULL || *extension == '\0')
47 return false;
48
49 const char *start = extlist;
50 while (const char *pos = strstr(start, extension)) {
51 const char *end = pos + strlen(extension);
52 // Ensure the found match is a full word, not a substring.
53 if ((pos == start || pos[-1] == ' ') &&
54 (*end == ' ' || *end == '\0')) {
55 return true;
56 }
57 start = end;
58 }
59 return false;
60 }
61
62 } // namespace Internal
63 } // namespace Runtime
64 } // namespace Halide
65
66 extern "C" {
67
halide_opengl_get_proc_address(void * user_context,const char * name)68 WEAK void *halide_opengl_get_proc_address(void *user_context, const char *name) {
69 return (void *)glXGetProcAddressARB(name);
70 }
71
72 // Initialize OpenGL
halide_opengl_create_context(void * user_context)73 WEAK int halide_opengl_create_context(void *user_context) {
74 const int desired_major_version = 3;
75 const int desired_minor_version = 2;
76
77 if (glXGetCurrentContext()) {
78 // Already have a context
79 return 0;
80 }
81
82 void *dpy = XOpenDisplay(NULL);
83 if (!dpy) {
84 halide_error(user_context, "Could not open X11 display.\n");
85 return -1;
86 }
87
88 // GLX supported?
89 if (!glXQueryExtension(dpy, NULL, NULL)) {
90 halide_error(user_context, "GLX not supported by X server.\n");
91 return -1;
92 }
93
94 int screen = XDefaultScreen(dpy);
95
96 int attribs[] = {
97 GLX_RENDER_TYPE, GLX_RGBA_BIT,
98 GLX_RED_SIZE, 8,
99 GLX_GREEN_SIZE, 8,
100 GLX_BLUE_SIZE, 8,
101 GLX_ALPHA_SIZE, 8,
102 0};
103 int num_configs = 0;
104 void **fbconfigs = glXChooseFBConfig(dpy, screen, attribs, &num_configs);
105 if (!num_configs) {
106 halide_error(user_context, "Could not get framebuffer config.\n");
107 return -1;
108 }
109 void *fbconfig = fbconfigs[0];
110
111 const char *glxexts = glXQueryExtensionsString(dpy, screen);
112 void *share_list = NULL;
113 int direct = 1;
114 void *context = NULL;
115
116 glXCreateContextAttribsARBProc glXCreateContextAttribsARB = 0;
117 glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc)
118 glXGetProcAddressARB("glXCreateContextAttribsARB");
119
120 if (glx_extension_supported(glxexts, "GLX_ARB_create_context") &&
121 glXCreateContextAttribsARB) {
122 int context_attribs[] = {
123 GLX_CONTEXT_MAJOR_VERSION_ARB, desired_major_version,
124 GLX_CONTEXT_MINOR_VERSION_ARB, desired_minor_version,
125 0};
126 context = glXCreateContextAttribsARB(dpy, fbconfig, share_list, direct,
127 context_attribs);
128 }
129 if (!context) {
130 // Open a legacy context
131 context = glXCreateNewContext(dpy, fbconfig, GLX_RGBA_TYPE, share_list, direct);
132 }
133 if (!context) {
134 halide_error(user_context, "Could not create OpenGL context.\n");
135 return -1;
136 }
137
138 int pbuffer_attribs[] = {
139 0x8041 /* GLX_PBUFFER_WIDTH */, 32,
140 0x8040 /* GLX_PBUFFER_HEIGHT */, 32,
141 0};
142 unsigned long pbuffer = glXCreatePbuffer(dpy, fbconfig, pbuffer_attribs);
143
144 XFree(fbconfigs);
145 XSync(dpy, 0);
146
147 if (!glXMakeContextCurrent(dpy, pbuffer, pbuffer, context)) {
148 halide_error(user_context, "Could not make context current.\n");
149 return -1;
150 }
151
152 return 0;
153 }
154 }
155