1 // Copyright (C)2004 Landmark Graphics Corporation
2 // Copyright (C)2005, 2006 Sun Microsystems, Inc.
3 // Copyright (C)2009, 2011, 2013-2016, 2018-2021 D. R. Commander
4 //
5 // This library is free software and may be redistributed and/or modified under
6 // the terms of the wxWindows Library License, Version 3.1 or (at your option)
7 // any later version. The full license is in the LICENSE.txt file included
8 // with this distribution.
9 //
10 // This library is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // wxWindows Library License for more details.
14
15 #ifndef __FAKER_H__
16 #define __FAKER_H__
17
18 #include <X11/Xmd.h>
19 #include <X11/Xlib.h>
20 #include "Error.h"
21 #include "Log.h"
22 #include "Mutex.h"
23 #include "fakerconfig.h"
24 #include "vglutil.h"
25 #include "vglwrap.h"
26
27
28 namespace vglfaker
29 {
30 extern Display *dpy3D;
31 extern bool deadYet;
32 extern char *glExtensions;
33 #ifdef EGLBACKEND
34 extern EGLint eglMajor, eglMinor;
35 #endif
36
37 extern void init(void);
38 extern Display *init3D(void);
39 extern void safeExit(int);
40
41 extern long getTraceLevel(void);
42 extern void setTraceLevel(long level);
43 extern long getFakerLevel(void);
44 extern void setFakerLevel(long level);
45 extern bool getExcludeCurrent(void);
46 extern void setExcludeCurrent(bool excludeCurrent);
47 extern long getAutotestColor();
48 extern void setAutotestColor(long color);
49 extern long getAutotestRColor();
50 extern void setAutotestRColor(long color);
51 extern long getAutotestFrame();
52 extern void setAutotestFrame(long color);
53 extern Display *getAutotestDisplay();
54 extern void setAutotestDisplay(Display *dpy);
55 extern long getAutotestDrawable();
56 extern void setAutotestDrawable(long d);
57
58 void *loadSymbol(const char *name, bool optional = false);
59 void unloadSymbols(void);
60
61 extern bool isDisplayStringExcluded(char *name);
62
isDisplayExcluded(Display * dpy)63 INLINE bool isDisplayExcluded(Display *dpy)
64 {
65 XEDataObject obj = { dpy };
66 XExtData *extData;
67
68 if(!dpy) return false;
69 // The 3D X server may have its own extensions that conflict with ours.
70 if(!fconfig.egl && dpy == dpy3D) return true;
71 int minExtensionNumber =
72 XFindOnExtensionList(XEHeadOfExtensionList(obj), 0) ? 0 : 1;
73 extData = XFindOnExtensionList(XEHeadOfExtensionList(obj),
74 minExtensionNumber);
75 ERRIFNOT(extData);
76 ERRIFNOT(extData->private_data);
77
78 return *(bool *)extData->private_data;
79 }
80
81 extern "C" int deleteCS(XExtData *extData);
82 extern "C" int deleteRBOContext(XExtData *extData);
83
getDisplayCS(Display * dpy)84 INLINE vglutil::CriticalSection &getDisplayCS(Display *dpy)
85 {
86 XEDataObject obj = { dpy };
87 XExtData *extData;
88
89 // The 3D X server may have its own extensions that conflict with ours.
90 if(!fconfig.egl && dpy == dpy3D)
91 THROW("vglfaker::getDisplayCS() called with 3D X server handle (this should never happen)");
92 int minExtensionNumber =
93 XFindOnExtensionList(XEHeadOfExtensionList(obj), 0) ? 0 : 1;
94 extData = XFindOnExtensionList(XEHeadOfExtensionList(obj),
95 minExtensionNumber + 1);
96 ERRIFNOT(extData);
97 ERRIFNOT(extData->private_data);
98
99 return *(vglutil::CriticalSection *)extData->private_data;
100 }
101
102 extern void sendGLXError(Display *dpy, CARD16 minorCode, CARD8 errorCode,
103 bool x11Error);
104 }
105
106 #define DPY3D vglfaker::init3D()
107 #define EDPY ((EGLDisplay)vglfaker::init3D())
108
109 #define IS_EXCLUDED(dpy) \
110 (vglfaker::deadYet || vglfaker::getFakerLevel() > 0 \
111 || vglfaker::isDisplayExcluded(dpy))
112
113 #define IS_FRONT(drawbuf) \
114 (drawbuf == GL_FRONT || drawbuf == GL_FRONT_AND_BACK \
115 || drawbuf == GL_FRONT_LEFT || drawbuf == GL_FRONT_RIGHT \
116 || drawbuf == GL_LEFT || drawbuf == GL_RIGHT)
117
118 #define IS_RIGHT(drawbuf) \
119 (drawbuf == GL_RIGHT || drawbuf == GL_FRONT_RIGHT \
120 || drawbuf == GL_BACK_RIGHT)
121
122
DrawingToFront(void)123 static INLINE int DrawingToFront(void)
124 {
125 GLint drawbuf = GL_BACK;
126 VGLGetIntegerv(GL_DRAW_BUFFER, &drawbuf);
127 return IS_FRONT(drawbuf);
128 }
129
130
DrawingToRight(void)131 static INLINE int DrawingToRight(void)
132 {
133 GLint drawbuf = GL_LEFT;
134 VGLGetIntegerv(GL_DRAW_BUFFER, &drawbuf);
135 return IS_RIGHT(drawbuf);
136 }
137
138
139 #define DIE(f, m) \
140 { \
141 if(!vglfaker::deadYet) \
142 vglout.print("[VGL] ERROR: in %s--\n[VGL] %s\n", f, m); \
143 vglfaker::safeExit(1); \
144 }
145
146
147 #define TRY() try {
148 #define CATCH() } \
149 catch(std::exception &e) { DIE(GET_METHOD(e), e.what()); }
150
151
152 // Clear any pending OpenGL errors.
153 #define TRY_GL() \
154 { \
155 int e; \
156 do { e = _glGetError(); } while(e != GL_NO_ERROR); \
157 }
158
159 // Catch any OpenGL errors that occurred since TRY_GL() was invoked.
160 #define CATCH_GL(m) \
161 { \
162 int e; bool doThrow = false; \
163 do \
164 { \
165 e = _glGetError(); \
166 if(e != GL_NO_ERROR) \
167 { \
168 vglout.print("[VGL] ERROR: OpenGL error 0x%.4x\n", e); \
169 doThrow = true; \
170 } \
171 } while(e != GL_NO_ERROR); \
172 if(doThrow) THROW(m); \
173 }
174
175
176 // Tracing stuff
177
178 #define PRARGD(a) vglout.print("%s=0x%.8lx(%s) ", #a, (unsigned long)a, \
179 a ? DisplayString(a) : "NULL")
180
181 #define PRARGS(a) vglout.print("%s=%s ", #a, a ? a : "NULL")
182
183 #define PRARGX(a) vglout.print("%s=0x%.8lx ", #a, a)
184
185 #define PRARGIX(a) vglout.print("%s=%d(0x%.lx) ", #a, (unsigned long)a, \
186 (unsigned long)a)
187
188 #define PRARGI(a) vglout.print("%s=%d ", #a, a)
189
190 #define PRARGF(a) vglout.print("%s=%f ", #a, (double)a)
191
192 #define PRARGV(a) \
193 vglout.print("%s=0x%.8lx(0x%.2lx) ", #a, (unsigned long)a, \
194 a ? (a)->visualid : 0)
195
196 #define PRARGC(a) \
197 vglout.print("%s=0x%.8lx(0x%.2x) ", #a, (unsigned long)a, a ? FBCID(a) : 0)
198
199 #define PRARGAL11(a) if(a) \
200 { \
201 vglout.print(#a "=["); \
202 for(int __an = 0; a[__an] != None; __an++) \
203 { \
204 vglout.print("0x%.4x", a[__an]); \
205 if(a[__an] != GLX_USE_GL && a[__an] != GLX_DOUBLEBUFFER \
206 && a[__an] != GLX_STEREO && a[__an] != GLX_RGBA) \
207 vglout.print("=0x%.4x", a[++__an]); \
208 vglout.print(" "); \
209 } \
210 vglout.print("] "); \
211 }
212
213 #define PRARGAL13(a) if(a != NULL) \
214 { \
215 vglout.print(#a "=["); \
216 for(int __an = 0; a[__an] != None; __an += 2) \
217 { \
218 vglout.print("0x%.4x=0x%.4x ", a[__an], a[__an + 1]); \
219 } \
220 vglout.print("] "); \
221 }
222
223 #ifdef FAKEXCB
224 #define PRARGERR(a) \
225 { \
226 vglout.print("(%s)->response_type=%d ", #a, (a)->response_type); \
227 vglout.print("(%s)->error_code=%d ", #a, (a)->error_code); \
228 }
229 #endif
230
231 #define OPENTRACE(f) \
232 double vglTraceTime = 0.; \
233 if(fconfig.trace) \
234 { \
235 if(vglfaker::getTraceLevel() > 0) \
236 { \
237 vglout.print("\n[VGL 0x%.8x] ", pthread_self()); \
238 for(int __i = 0; __i < vglfaker::getTraceLevel(); __i++) \
239 vglout.print(" "); \
240 } \
241 else vglout.print("[VGL 0x%.8x] ", pthread_self()); \
242 vglfaker::setTraceLevel(vglfaker::getTraceLevel() + 1); \
243 vglout.print("%s (", #f); \
244
245 #define STARTTRACE() \
246 vglTraceTime = GetTime(); \
247 }
248
249 #define STOPTRACE() \
250 if(fconfig.trace) \
251 { \
252 vglTraceTime = GetTime() - vglTraceTime;
253
254 #define CLOSETRACE() \
255 vglout.PRINT(") %f ms\n", vglTraceTime * 1000.); \
256 vglfaker::setTraceLevel(vglfaker::getTraceLevel() - 1); \
257 if(vglfaker::getTraceLevel() > 0) \
258 { \
259 vglout.print("[VGL 0x%.8x] ", pthread_self()); \
260 if(vglfaker::getTraceLevel() > 1) \
261 for(int __i = 0; __i < vglfaker::getTraceLevel() - 1; __i++) \
262 vglout.print(" "); \
263 } \
264 }
265
266 #endif // __FAKER_H__
267