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