1 /*
2 * Compton - a compositor for X11
3 *
4 * Based on `xcompmgr` - Copyright (c) 2003, Keith Packard
5 *
6 * Copyright (c) 2011-2013, Christopher Jeffrey
7 * See LICENSE for more information.
8 *
9 */
10
11 #include "common.h"
12
13 #include <ctype.h>
14 #include <locale.h>
15
16 #ifdef DEBUG_GLX_ERR
17
18 /**
19 * Get a textual representation of an OpenGL error.
20 */
21 static inline const char *
glx_dump_err_str(GLenum err)22 glx_dump_err_str(GLenum err) {
23 switch (err) {
24 CASESTRRET(GL_NO_ERROR);
25 CASESTRRET(GL_INVALID_ENUM);
26 CASESTRRET(GL_INVALID_VALUE);
27 CASESTRRET(GL_INVALID_OPERATION);
28 CASESTRRET(GL_INVALID_FRAMEBUFFER_OPERATION);
29 CASESTRRET(GL_OUT_OF_MEMORY);
30 CASESTRRET(GL_STACK_UNDERFLOW);
31 CASESTRRET(GL_STACK_OVERFLOW);
32 }
33
34 return NULL;
35 }
36
37 /**
38 * Check for GLX error.
39 *
40 * http://blog.nobel-joergensen.com/2013/01/29/debugging-opengl-using-glgeterror/
41 */
42 static inline void
glx_check_err_(session_t * ps,const char * func,int line)43 glx_check_err_(session_t *ps, const char *func, int line) {
44 if (!ps->psglx->context) return;
45
46 GLenum err = GL_NO_ERROR;
47
48 while (GL_NO_ERROR != (err = glGetError())) {
49 print_timestamp(ps);
50 printf("%s():%d: GLX error ", func, line);
51 const char *errtext = glx_dump_err_str(err);
52 if (errtext) {
53 printf_dbg("%s\n", errtext);
54 }
55 else {
56 printf_dbg("%d\n", err);
57 }
58 }
59 }
60
61 #define glx_check_err(ps) glx_check_err_(ps, __func__, __LINE__)
62 #else
63 #define glx_check_err(ps) ((void) 0)
64 #endif
65
66 /**
67 * Check if a word is in string.
68 */
69 static inline bool
wd_is_in_str(const char * haystick,const char * needle)70 wd_is_in_str(const char *haystick, const char *needle) {
71 if (!haystick)
72 return false;
73
74 assert(*needle);
75
76 const char *pos = haystick - 1;
77 while ((pos = strstr(pos + 1, needle))) {
78 // Continue if it isn't a word boundary
79 if (((pos - haystick) && !isspace(*(pos - 1)))
80 || (strlen(pos) > strlen(needle) && !isspace(pos[strlen(needle)])))
81 continue;
82 return true;
83 }
84
85 return false;
86 }
87
88 /**
89 * Check if a GLX extension exists.
90 */
91 static inline bool
glx_hasglxext(session_t * ps,const char * ext)92 glx_hasglxext(session_t *ps, const char *ext) {
93 const char *glx_exts = glXQueryExtensionsString(ps->dpy, ps->scr);
94 if (!glx_exts) {
95 printf_errf("(): Failed get GLX extension list.");
96 return false;
97 }
98
99 bool found = wd_is_in_str(glx_exts, ext);
100 if (!found)
101 printf_errf("(): Missing GLX extension %s.", ext);
102
103 return found;
104 }
105
106 /**
107 * Check if a GLX extension exists.
108 */
109 static inline bool
glx_hasglext(session_t * ps,const char * ext)110 glx_hasglext(session_t *ps, const char *ext) {
111 const char *gl_exts = (const char *) glGetString(GL_EXTENSIONS);
112 if (!gl_exts) {
113 printf_errf("(): Failed get GL extension list.");
114 return false;
115 }
116
117 bool found = wd_is_in_str(gl_exts, ext);
118 if (!found)
119 printf_errf("(): Missing GL extension %s.", ext);
120
121 return found;
122 }
123
124 static inline XVisualInfo *
get_visualinfo_from_visual(session_t * ps,Visual * visual)125 get_visualinfo_from_visual(session_t *ps, Visual *visual) {
126 XVisualInfo vreq = { .visualid = XVisualIDFromVisual(visual) };
127 int nitems = 0;
128
129 return XGetVisualInfo(ps->dpy, VisualIDMask, &vreq, &nitems);
130 }
131
132 static bool
133 glx_update_fbconfig(session_t *ps);
134
135 static int
136 glx_cmp_fbconfig(session_t *ps,
137 const glx_fbconfig_t *pfbc_a, const glx_fbconfig_t *pfbc_b);
138
139 static void
140 glx_render_color(session_t *ps, int dx, int dy, int width, int height, int z,
141 XserverRegion reg_tgt, const reg_data_t *pcache_reg);
142
143 static void
144 glx_render_dots(session_t *ps, int dx, int dy, int width, int height, int z,
145 XserverRegion reg_tgt, const reg_data_t *pcache_reg);
146