• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2015 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 
7 // FunctionsGLX.cpp: Implements the FunctionsGLX class.
8 
9 #define ANGLE_SKIP_GLX_DEFINES 1
10 #include "libANGLE/renderer/gl/glx/FunctionsGLX.h"
11 #undef ANGLE_SKIP_GLX_DEFINES
12 
13 // We can only include glx.h in files which do not include ANGLE's GLES
14 // headers, to avoid doubly-defined GLenum macros, typedefs, etc.
15 #include <GL/glx.h>
16 
17 #include <dlfcn.h>
18 #include <algorithm>
19 
20 #include "common/string_utils.h"
21 #include "libANGLE/renderer/gl/glx/functionsglx_typedefs.h"
22 
23 namespace rx
24 {
25 
26 void *FunctionsGLX::sLibHandle = nullptr;
27 
28 template <typename T>
GetProc(PFNGETPROCPROC getProc,T * member,const char * name)29 static bool GetProc(PFNGETPROCPROC getProc, T *member, const char *name)
30 {
31     *member = reinterpret_cast<T>(getProc(name));
32     return *member != nullptr;
33 }
34 
35 struct FunctionsGLX::GLXFunctionTable
36 {
GLXFunctionTablerx::FunctionsGLX::GLXFunctionTable37     GLXFunctionTable()
38         : createContextPtr(nullptr),
39           destroyContextPtr(nullptr),
40           makeCurrentPtr(nullptr),
41           swapBuffersPtr(nullptr),
42           queryExtensionPtr(nullptr),
43           queryVersionPtr(nullptr),
44           getCurrentContextPtr(nullptr),
45           getCurrentDrawablePtr(nullptr),
46           waitXPtr(nullptr),
47           waitGLPtr(nullptr),
48           getClientStringPtr(nullptr),
49           queryExtensionsStringPtr(nullptr),
50           getFBConfigsPtr(nullptr),
51           chooseFBConfigPtr(nullptr),
52           getFBConfigAttribPtr(nullptr),
53           getVisualFromFBConfigPtr(nullptr),
54           createWindowPtr(nullptr),
55           destroyWindowPtr(nullptr),
56           createPbufferPtr(nullptr),
57           destroyPbufferPtr(nullptr),
58           queryDrawablePtr(nullptr),
59           createContextAttribsARBPtr(nullptr),
60           swapIntervalEXTPtr(nullptr),
61           swapIntervalMESAPtr(nullptr),
62           swapIntervalSGIPtr(nullptr),
63           getSyncValuesOMLPtr(nullptr),
64           getMscRateOMLPtr(nullptr)
65     {}
66 
67     // GLX 1.0
68     PFNGLXCREATECONTEXTPROC createContextPtr;
69     PFNGLXDESTROYCONTEXTPROC destroyContextPtr;
70     PFNGLXMAKECURRENTPROC makeCurrentPtr;
71     PFNGLXSWAPBUFFERSPROC swapBuffersPtr;
72     PFNGLXQUERYEXTENSIONPROC queryExtensionPtr;
73     PFNGLXQUERYVERSIONPROC queryVersionPtr;
74     PFNGLXGETCURRENTCONTEXTPROC getCurrentContextPtr;
75     PFNGLXGETCURRENTDRAWABLEPROC getCurrentDrawablePtr;
76     PFNGLXWAITXPROC waitXPtr;
77     PFNGLXWAITGLPROC waitGLPtr;
78 
79     // GLX 1.1
80     PFNGLXGETCLIENTSTRINGPROC getClientStringPtr;
81     PFNGLXQUERYEXTENSIONSSTRINGPROC queryExtensionsStringPtr;
82 
83     // GLX 1.3
84     PFNGLXGETFBCONFIGSPROC getFBConfigsPtr;
85     PFNGLXCHOOSEFBCONFIGPROC chooseFBConfigPtr;
86     PFNGLXGETFBCONFIGATTRIBPROC getFBConfigAttribPtr;
87     PFNGLXGETVISUALFROMFBCONFIGPROC getVisualFromFBConfigPtr;
88     PFNGLXCREATEWINDOWPROC createWindowPtr;
89     PFNGLXDESTROYWINDOWPROC destroyWindowPtr;
90     PFNGLXCREATEPBUFFERPROC createPbufferPtr;
91     PFNGLXDESTROYPBUFFERPROC destroyPbufferPtr;
92     PFNGLXQUERYDRAWABLEPROC queryDrawablePtr;
93 
94     // GLX_ARB_create_context
95     PFNGLXCREATECONTEXTATTRIBSARBPROC createContextAttribsARBPtr;
96 
97     // GLX_EXT_swap_control
98     PFNGLXSWAPINTERVALEXTPROC swapIntervalEXTPtr;
99 
100     // GLX_MESA_swap_control
101     PFNGLXSWAPINTERVALMESAPROC swapIntervalMESAPtr;
102 
103     // GLX_SGI_swap_control
104     PFNGLXSWAPINTERVALSGIPROC swapIntervalSGIPtr;
105 
106     // GLX_OML_sync_control
107     PFNGLXGETSYNCVALUESOMLPROC getSyncValuesOMLPtr;
108     PFNGLXGETMSCRATEOMLPROC getMscRateOMLPtr;
109 };
110 
FunctionsGLX()111 FunctionsGLX::FunctionsGLX()
112     : majorVersion(0),
113       minorVersion(0),
114       mXDisplay(nullptr),
115       mXScreen(-1),
116       mFnPtrs(new GLXFunctionTable())
117 {}
118 
~FunctionsGLX()119 FunctionsGLX::~FunctionsGLX()
120 {
121     delete mFnPtrs;
122     terminate();
123 }
124 
initialize(Display * xDisplay,int screen,std::string * errorString)125 bool FunctionsGLX::initialize(Display *xDisplay, int screen, std::string *errorString)
126 {
127     terminate();
128     mXDisplay = xDisplay;
129     mXScreen  = screen;
130 
131 #if !defined(ANGLE_LINK_GLX)
132     // Some OpenGL implementations can't handle having this library
133     // handle closed while there's any X window still open against
134     // which a GLXWindow was ever created.
135     if (!sLibHandle)
136     {
137         sLibHandle = dlopen("libGL.so.1", RTLD_NOW);
138         if (!sLibHandle)
139         {
140             *errorString = std::string("Could not dlopen libGL.so.1: ") + dlerror();
141             return false;
142         }
143     }
144 
145     getProc = reinterpret_cast<PFNGETPROCPROC>(dlsym(sLibHandle, "glXGetProcAddress"));
146     if (!getProc)
147     {
148         getProc = reinterpret_cast<PFNGETPROCPROC>(dlsym(sLibHandle, "glXGetProcAddressARB"));
149     }
150     if (!getProc)
151     {
152         *errorString = "Could not retrieve glXGetProcAddress";
153         return false;
154     }
155 #else
156     getProc = reinterpret_cast<PFNGETPROCPROC>(glXGetProcAddress);
157 #endif
158 
159 #define GET_PROC_OR_ERROR(MEMBER, NAME)                             \
160     do                                                              \
161     {                                                               \
162         if (!GetProc(getProc, MEMBER, #NAME))                       \
163         {                                                           \
164             *errorString = "Could not load GLX entry point " #NAME; \
165             return false;                                           \
166         }                                                           \
167     } while (0)
168 #if !defined(ANGLE_LINK_GLX)
169 #    define GET_FNPTR_OR_ERROR(MEMBER, NAME) GET_PROC_OR_ERROR(MEMBER, NAME)
170 #else
171 #    define GET_FNPTR_OR_ERROR(MEMBER, NAME) *MEMBER = NAME
172 #endif
173 
174     // GLX 1.0
175     GET_FNPTR_OR_ERROR(&mFnPtrs->createContextPtr, glXCreateContext);
176     GET_FNPTR_OR_ERROR(&mFnPtrs->destroyContextPtr, glXDestroyContext);
177     GET_FNPTR_OR_ERROR(&mFnPtrs->makeCurrentPtr, glXMakeCurrent);
178     GET_FNPTR_OR_ERROR(&mFnPtrs->swapBuffersPtr, glXSwapBuffers);
179     GET_FNPTR_OR_ERROR(&mFnPtrs->queryExtensionPtr, glXQueryExtension);
180     GET_FNPTR_OR_ERROR(&mFnPtrs->queryVersionPtr, glXQueryVersion);
181     GET_FNPTR_OR_ERROR(&mFnPtrs->getCurrentContextPtr, glXGetCurrentContext);
182     GET_FNPTR_OR_ERROR(&mFnPtrs->getCurrentDrawablePtr, glXGetCurrentDrawable);
183     GET_FNPTR_OR_ERROR(&mFnPtrs->waitXPtr, glXWaitX);
184     GET_FNPTR_OR_ERROR(&mFnPtrs->waitGLPtr, glXWaitGL);
185 
186     // GLX 1.1
187     GET_FNPTR_OR_ERROR(&mFnPtrs->getClientStringPtr, glXGetClientString);
188     GET_FNPTR_OR_ERROR(&mFnPtrs->queryExtensionsStringPtr, glXQueryExtensionsString);
189 
190     // Check we have a working GLX
191     {
192         int errorBase;
193         int eventBase;
194         if (!queryExtension(&errorBase, &eventBase))
195         {
196             *errorString = "GLX is not present.";
197             return false;
198         }
199     }
200 
201     // Check we have a supported version of GLX
202     if (!queryVersion(&majorVersion, &minorVersion))
203     {
204         *errorString = "Could not query the GLX version.";
205         return false;
206     }
207     if (majorVersion != 1 || minorVersion < 3)
208     {
209         *errorString = "Unsupported GLX version (requires at least 1.3).";
210         return false;
211     }
212 
213     const char *extensions = queryExtensionsString();
214     if (!extensions)
215     {
216         *errorString = "glXQueryExtensionsString returned NULL";
217         return false;
218     }
219     angle::SplitStringAlongWhitespace(extensions, &mExtensions);
220 
221     // GLX 1.3
222     GET_FNPTR_OR_ERROR(&mFnPtrs->getFBConfigsPtr, glXGetFBConfigs);
223     GET_FNPTR_OR_ERROR(&mFnPtrs->chooseFBConfigPtr, glXChooseFBConfig);
224     GET_FNPTR_OR_ERROR(&mFnPtrs->getFBConfigAttribPtr, glXGetFBConfigAttrib);
225     GET_FNPTR_OR_ERROR(&mFnPtrs->getVisualFromFBConfigPtr, glXGetVisualFromFBConfig);
226     GET_FNPTR_OR_ERROR(&mFnPtrs->createWindowPtr, glXCreateWindow);
227     GET_FNPTR_OR_ERROR(&mFnPtrs->destroyWindowPtr, glXDestroyWindow);
228     GET_FNPTR_OR_ERROR(&mFnPtrs->createPbufferPtr, glXCreatePbuffer);
229     GET_FNPTR_OR_ERROR(&mFnPtrs->destroyPbufferPtr, glXDestroyPbuffer);
230     GET_FNPTR_OR_ERROR(&mFnPtrs->queryDrawablePtr, glXQueryDrawable);
231 
232     // Extensions
233     if (hasExtension("GLX_ARB_create_context"))
234     {
235         GET_PROC_OR_ERROR(&mFnPtrs->createContextAttribsARBPtr, glXCreateContextAttribsARB);
236     }
237     if (hasExtension("GLX_EXT_swap_control"))
238     {
239         GET_PROC_OR_ERROR(&mFnPtrs->swapIntervalEXTPtr, glXSwapIntervalEXT);
240     }
241     if (hasExtension("GLX_MESA_swap_control"))
242     {
243         GET_PROC_OR_ERROR(&mFnPtrs->swapIntervalMESAPtr, glXSwapIntervalMESA);
244     }
245     if (hasExtension("GLX_SGI_swap_control"))
246     {
247         GET_PROC_OR_ERROR(&mFnPtrs->swapIntervalSGIPtr, glXSwapIntervalSGI);
248     }
249     if (hasExtension("GLX_OML_sync_control"))
250     {
251         GET_PROC_OR_ERROR(&mFnPtrs->getSyncValuesOMLPtr, glXGetSyncValuesOML);
252         GET_PROC_OR_ERROR(&mFnPtrs->getMscRateOMLPtr, glXGetMscRateOML);
253     }
254 
255 #undef GET_FNPTR_OR_ERROR
256 #undef GET_PROC_OR_ERROR
257 
258     *errorString = "";
259     return true;
260 }
261 
terminate()262 void FunctionsGLX::terminate() {}
263 
hasExtension(const char * extension) const264 bool FunctionsGLX::hasExtension(const char *extension) const
265 {
266     return std::find(mExtensions.begin(), mExtensions.end(), extension) != mExtensions.end();
267 }
268 
getDisplay() const269 Display *FunctionsGLX::getDisplay() const
270 {
271     return mXDisplay;
272 }
273 
getScreen() const274 int FunctionsGLX::getScreen() const
275 {
276     return mXScreen;
277 }
278 
279 // GLX functions
280 
281 // GLX 1.0
createContext(XVisualInfo * visual,glx::Context share,bool direct) const282 glx::Context FunctionsGLX::createContext(XVisualInfo *visual, glx::Context share, bool direct) const
283 {
284     GLXContext shareCtx = reinterpret_cast<GLXContext>(share);
285     GLXContext context  = mFnPtrs->createContextPtr(mXDisplay, visual, shareCtx, direct);
286     return reinterpret_cast<glx::Context>(context);
287 }
destroyContext(glx::Context context) const288 void FunctionsGLX::destroyContext(glx::Context context) const
289 {
290     GLXContext ctx = reinterpret_cast<GLXContext>(context);
291     mFnPtrs->destroyContextPtr(mXDisplay, ctx);
292 }
makeCurrent(glx::Drawable drawable,glx::Context context) const293 Bool FunctionsGLX::makeCurrent(glx::Drawable drawable, glx::Context context) const
294 {
295     GLXContext ctx = reinterpret_cast<GLXContext>(context);
296     return mFnPtrs->makeCurrentPtr(mXDisplay, drawable, ctx);
297 }
swapBuffers(glx::Drawable drawable) const298 void FunctionsGLX::swapBuffers(glx::Drawable drawable) const
299 {
300     mFnPtrs->swapBuffersPtr(mXDisplay, drawable);
301 }
queryExtension(int * errorBase,int * event) const302 Bool FunctionsGLX::queryExtension(int *errorBase, int *event) const
303 {
304     return mFnPtrs->queryExtensionPtr(mXDisplay, errorBase, event);
305 }
queryVersion(int * major,int * minor) const306 Bool FunctionsGLX::queryVersion(int *major, int *minor) const
307 {
308     return mFnPtrs->queryVersionPtr(mXDisplay, major, minor);
309 }
getCurrentContext() const310 glx::Context FunctionsGLX::getCurrentContext() const
311 {
312     GLXContext context = mFnPtrs->getCurrentContextPtr();
313     return reinterpret_cast<glx::Context>(context);
314 }
getCurrentDrawable() const315 glx::Drawable FunctionsGLX::getCurrentDrawable() const
316 {
317     GLXDrawable drawable = mFnPtrs->getCurrentDrawablePtr();
318     return reinterpret_cast<glx::Drawable>(drawable);
319 }
waitX() const320 void FunctionsGLX::waitX() const
321 {
322     mFnPtrs->waitXPtr();
323 }
waitGL() const324 void FunctionsGLX::waitGL() const
325 {
326     mFnPtrs->waitGLPtr();
327 }
328 
329 // GLX 1.1
getClientString(int name) const330 const char *FunctionsGLX::getClientString(int name) const
331 {
332     return mFnPtrs->getClientStringPtr(mXDisplay, name);
333 }
334 
queryExtensionsString() const335 const char *FunctionsGLX::queryExtensionsString() const
336 {
337     return mFnPtrs->queryExtensionsStringPtr(mXDisplay, mXScreen);
338 }
339 
340 // GLX 1.4
getFBConfigs(int * nElements) const341 glx::FBConfig *FunctionsGLX::getFBConfigs(int *nElements) const
342 {
343     GLXFBConfig *configs = mFnPtrs->getFBConfigsPtr(mXDisplay, mXScreen, nElements);
344     return reinterpret_cast<glx::FBConfig *>(configs);
345 }
chooseFBConfig(const int * attribList,int * nElements) const346 glx::FBConfig *FunctionsGLX::chooseFBConfig(const int *attribList, int *nElements) const
347 {
348     GLXFBConfig *configs = mFnPtrs->chooseFBConfigPtr(mXDisplay, mXScreen, attribList, nElements);
349     return reinterpret_cast<glx::FBConfig *>(configs);
350 }
getFBConfigAttrib(glx::FBConfig config,int attribute,int * value) const351 int FunctionsGLX::getFBConfigAttrib(glx::FBConfig config, int attribute, int *value) const
352 {
353     GLXFBConfig cfg = reinterpret_cast<GLXFBConfig>(config);
354     return mFnPtrs->getFBConfigAttribPtr(mXDisplay, cfg, attribute, value);
355 }
getVisualFromFBConfig(glx::FBConfig config) const356 XVisualInfo *FunctionsGLX::getVisualFromFBConfig(glx::FBConfig config) const
357 {
358     GLXFBConfig cfg = reinterpret_cast<GLXFBConfig>(config);
359     return mFnPtrs->getVisualFromFBConfigPtr(mXDisplay, cfg);
360 }
createWindow(glx::FBConfig config,Window window,const int * attribList) const361 GLXWindow FunctionsGLX::createWindow(glx::FBConfig config,
362                                      Window window,
363                                      const int *attribList) const
364 {
365     GLXFBConfig cfg = reinterpret_cast<GLXFBConfig>(config);
366     return mFnPtrs->createWindowPtr(mXDisplay, cfg, window, attribList);
367 }
destroyWindow(glx::Window window) const368 void FunctionsGLX::destroyWindow(glx::Window window) const
369 {
370     mFnPtrs->destroyWindowPtr(mXDisplay, window);
371 }
createPbuffer(glx::FBConfig config,const int * attribList) const372 glx::Pbuffer FunctionsGLX::createPbuffer(glx::FBConfig config, const int *attribList) const
373 {
374     GLXFBConfig cfg = reinterpret_cast<GLXFBConfig>(config);
375     return mFnPtrs->createPbufferPtr(mXDisplay, cfg, attribList);
376 }
destroyPbuffer(glx::Pbuffer pbuffer) const377 void FunctionsGLX::destroyPbuffer(glx::Pbuffer pbuffer) const
378 {
379     mFnPtrs->destroyPbufferPtr(mXDisplay, pbuffer);
380 }
queryDrawable(glx::Drawable drawable,int attribute,unsigned int * value) const381 void FunctionsGLX::queryDrawable(glx::Drawable drawable, int attribute, unsigned int *value) const
382 {
383     mFnPtrs->queryDrawablePtr(mXDisplay, drawable, attribute, value);
384 }
385 
386 // GLX_ARB_create_context
createContextAttribsARB(glx::FBConfig config,glx::Context shareContext,Bool direct,const int * attribList) const387 glx::Context FunctionsGLX::createContextAttribsARB(glx::FBConfig config,
388                                                    glx::Context shareContext,
389                                                    Bool direct,
390                                                    const int *attribList) const
391 {
392     GLXContext shareCtx = reinterpret_cast<GLXContext>(shareContext);
393     GLXFBConfig cfg     = reinterpret_cast<GLXFBConfig>(config);
394     GLXContext ctx =
395         mFnPtrs->createContextAttribsARBPtr(mXDisplay, cfg, shareCtx, direct, attribList);
396     return reinterpret_cast<glx::Context>(ctx);
397 }
398 
swapIntervalEXT(glx::Drawable drawable,int intervals) const399 void FunctionsGLX::swapIntervalEXT(glx::Drawable drawable, int intervals) const
400 {
401     mFnPtrs->swapIntervalEXTPtr(mXDisplay, drawable, intervals);
402 }
403 
swapIntervalMESA(int intervals) const404 int FunctionsGLX::swapIntervalMESA(int intervals) const
405 {
406     return mFnPtrs->swapIntervalMESAPtr(intervals);
407 }
408 
swapIntervalSGI(int intervals) const409 int FunctionsGLX::swapIntervalSGI(int intervals) const
410 {
411     return mFnPtrs->swapIntervalSGIPtr(intervals);
412 }
413 
getSyncValuesOML(glx::Drawable drawable,int64_t * ust,int64_t * msc,int64_t * sbc) const414 bool FunctionsGLX::getSyncValuesOML(glx::Drawable drawable,
415                                     int64_t *ust,
416                                     int64_t *msc,
417                                     int64_t *sbc) const
418 {
419     return mFnPtrs->getSyncValuesOMLPtr(mXDisplay, drawable, ust, msc, sbc);
420 }
421 
getMscRateOML(glx::Drawable drawable,int32_t * numerator,int32_t * denominator) const422 bool FunctionsGLX::getMscRateOML(glx::Drawable drawable,
423                                  int32_t *numerator,
424                                  int32_t *denominator) const
425 {
426     return mFnPtrs->getMscRateOMLPtr(mXDisplay, drawable, numerator, denominator);
427 }
428 
429 }  // namespace rx
430