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