xref: /aosp_15_r20/external/angle/src/libANGLE/renderer/gl/glx/FunctionsGLX.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
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           createPixmapPtr(nullptr),
60           destroyPixmapPtr(nullptr),
61           createContextAttribsARBPtr(nullptr),
62           swapIntervalEXTPtr(nullptr),
63           swapIntervalMESAPtr(nullptr),
64           swapIntervalSGIPtr(nullptr),
65           getSyncValuesOMLPtr(nullptr),
66           getMscRateOMLPtr(nullptr),
67           bindTexImageEXTPtr(nullptr),
68           releaseTexImageEXTPtr(nullptr)
69     {}
70 
71     // GLX 1.0
72     PFNGLXCREATECONTEXTPROC createContextPtr;
73     PFNGLXDESTROYCONTEXTPROC destroyContextPtr;
74     PFNGLXMAKECURRENTPROC makeCurrentPtr;
75     PFNGLXSWAPBUFFERSPROC swapBuffersPtr;
76     PFNGLXQUERYEXTENSIONPROC queryExtensionPtr;
77     PFNGLXQUERYVERSIONPROC queryVersionPtr;
78     PFNGLXGETCURRENTCONTEXTPROC getCurrentContextPtr;
79     PFNGLXGETCURRENTDRAWABLEPROC getCurrentDrawablePtr;
80     PFNGLXWAITXPROC waitXPtr;
81     PFNGLXWAITGLPROC waitGLPtr;
82 
83     // GLX 1.1
84     PFNGLXGETCLIENTSTRINGPROC getClientStringPtr;
85     PFNGLXQUERYEXTENSIONSSTRINGPROC queryExtensionsStringPtr;
86 
87     // GLX 1.3
88     PFNGLXGETFBCONFIGSPROC getFBConfigsPtr;
89     PFNGLXCHOOSEFBCONFIGPROC chooseFBConfigPtr;
90     PFNGLXGETFBCONFIGATTRIBPROC getFBConfigAttribPtr;
91     PFNGLXGETVISUALFROMFBCONFIGPROC getVisualFromFBConfigPtr;
92     PFNGLXCREATEWINDOWPROC createWindowPtr;
93     PFNGLXDESTROYWINDOWPROC destroyWindowPtr;
94     PFNGLXCREATEPBUFFERPROC createPbufferPtr;
95     PFNGLXDESTROYPBUFFERPROC destroyPbufferPtr;
96     PFNGLXQUERYDRAWABLEPROC queryDrawablePtr;
97     PFNGLXCREATEPIXMAPPROC createPixmapPtr;
98     PFNGLXDESTROYPIXMAPPROC destroyPixmapPtr;
99 
100     // GLX_ARB_create_context
101     PFNGLXCREATECONTEXTATTRIBSARBPROC createContextAttribsARBPtr;
102 
103     // GLX_EXT_swap_control
104     PFNGLXSWAPINTERVALEXTPROC swapIntervalEXTPtr;
105 
106     // GLX_MESA_swap_control
107     PFNGLXSWAPINTERVALMESAPROC swapIntervalMESAPtr;
108 
109     // GLX_SGI_swap_control
110     PFNGLXSWAPINTERVALSGIPROC swapIntervalSGIPtr;
111 
112     // GLX_OML_sync_control
113     PFNGLXGETSYNCVALUESOMLPROC getSyncValuesOMLPtr;
114     PFNGLXGETMSCRATEOMLPROC getMscRateOMLPtr;
115 
116     // GLX_EXT_texture_from_pixmap
117     PFNGLXBINDTEXIMAGEEXTPROC bindTexImageEXTPtr;
118     PFNGLXRELEASETEXIMAGEEXTPROC releaseTexImageEXTPtr;
119 };
120 
FunctionsGLX()121 FunctionsGLX::FunctionsGLX()
122     : majorVersion(0),
123       minorVersion(0),
124       mXDisplay(nullptr),
125       mXScreen(-1),
126       mFnPtrs(new GLXFunctionTable())
127 {}
128 
~FunctionsGLX()129 FunctionsGLX::~FunctionsGLX()
130 {
131     delete mFnPtrs;
132     terminate();
133 }
134 
initialize(Display * xDisplay,int screen,std::string * errorString)135 bool FunctionsGLX::initialize(Display *xDisplay, int screen, std::string *errorString)
136 {
137     terminate();
138     mXDisplay = xDisplay;
139     mXScreen  = screen;
140 
141 #if !defined(ANGLE_LINK_GLX)
142     // Some OpenGL implementations can't handle having this library
143     // handle closed while there's any X window still open against
144     // which a GLXWindow was ever created.
145     if (!sLibHandle)
146     {
147         sLibHandle = dlopen("libGL.so.1", RTLD_NOW);
148         if (!sLibHandle)
149         {
150             *errorString = std::string("Could not dlopen libGL.so.1: ") + dlerror();
151             return false;
152         }
153     }
154 
155     getProc = reinterpret_cast<PFNGETPROCPROC>(dlsym(sLibHandle, "glXGetProcAddress"));
156     if (!getProc)
157     {
158         getProc = reinterpret_cast<PFNGETPROCPROC>(dlsym(sLibHandle, "glXGetProcAddressARB"));
159     }
160     if (!getProc)
161     {
162         *errorString = "Could not retrieve glXGetProcAddress";
163         return false;
164     }
165 #else
166     getProc = reinterpret_cast<PFNGETPROCPROC>(glXGetProcAddress);
167 #endif
168 
169 #define GET_PROC_OR_ERROR(MEMBER, NAME)                             \
170     do                                                              \
171     {                                                               \
172         if (!GetProc(getProc, MEMBER, #NAME))                       \
173         {                                                           \
174             *errorString = "Could not load GLX entry point " #NAME; \
175             return false;                                           \
176         }                                                           \
177     } while (0)
178 #if !defined(ANGLE_LINK_GLX)
179 #    define GET_FNPTR_OR_ERROR(MEMBER, NAME) GET_PROC_OR_ERROR(MEMBER, NAME)
180 #else
181 #    define GET_FNPTR_OR_ERROR(MEMBER, NAME) *MEMBER = NAME
182 #endif
183 
184     // GLX 1.0
185     GET_FNPTR_OR_ERROR(&mFnPtrs->createContextPtr, glXCreateContext);
186     GET_FNPTR_OR_ERROR(&mFnPtrs->destroyContextPtr, glXDestroyContext);
187     GET_FNPTR_OR_ERROR(&mFnPtrs->makeCurrentPtr, glXMakeCurrent);
188     GET_FNPTR_OR_ERROR(&mFnPtrs->swapBuffersPtr, glXSwapBuffers);
189     GET_FNPTR_OR_ERROR(&mFnPtrs->queryExtensionPtr, glXQueryExtension);
190     GET_FNPTR_OR_ERROR(&mFnPtrs->queryVersionPtr, glXQueryVersion);
191     GET_FNPTR_OR_ERROR(&mFnPtrs->getCurrentContextPtr, glXGetCurrentContext);
192     GET_FNPTR_OR_ERROR(&mFnPtrs->getCurrentDrawablePtr, glXGetCurrentDrawable);
193     GET_FNPTR_OR_ERROR(&mFnPtrs->waitXPtr, glXWaitX);
194     GET_FNPTR_OR_ERROR(&mFnPtrs->waitGLPtr, glXWaitGL);
195 
196     // GLX 1.1
197     GET_FNPTR_OR_ERROR(&mFnPtrs->getClientStringPtr, glXGetClientString);
198     GET_FNPTR_OR_ERROR(&mFnPtrs->queryExtensionsStringPtr, glXQueryExtensionsString);
199 
200     // Check we have a working GLX
201     {
202         int errorBase;
203         int eventBase;
204         if (!queryExtension(&errorBase, &eventBase))
205         {
206             *errorString = "GLX is not present.";
207             return false;
208         }
209     }
210 
211     // Check we have a supported version of GLX
212     if (!queryVersion(&majorVersion, &minorVersion))
213     {
214         *errorString = "Could not query the GLX version.";
215         return false;
216     }
217     if (majorVersion != 1 || minorVersion < 3)
218     {
219         *errorString = "Unsupported GLX version (requires at least 1.3).";
220         return false;
221     }
222 
223     const char *extensions = queryExtensionsString();
224     if (!extensions)
225     {
226         *errorString = "glXQueryExtensionsString returned NULL";
227         return false;
228     }
229     angle::SplitStringAlongWhitespace(extensions, &mExtensions);
230 
231     // GLX 1.3
232     GET_FNPTR_OR_ERROR(&mFnPtrs->getFBConfigsPtr, glXGetFBConfigs);
233     GET_FNPTR_OR_ERROR(&mFnPtrs->chooseFBConfigPtr, glXChooseFBConfig);
234     GET_FNPTR_OR_ERROR(&mFnPtrs->getFBConfigAttribPtr, glXGetFBConfigAttrib);
235     GET_FNPTR_OR_ERROR(&mFnPtrs->getVisualFromFBConfigPtr, glXGetVisualFromFBConfig);
236     GET_FNPTR_OR_ERROR(&mFnPtrs->createWindowPtr, glXCreateWindow);
237     GET_FNPTR_OR_ERROR(&mFnPtrs->destroyWindowPtr, glXDestroyWindow);
238     GET_FNPTR_OR_ERROR(&mFnPtrs->createPbufferPtr, glXCreatePbuffer);
239     GET_FNPTR_OR_ERROR(&mFnPtrs->destroyPbufferPtr, glXDestroyPbuffer);
240     GET_FNPTR_OR_ERROR(&mFnPtrs->queryDrawablePtr, glXQueryDrawable);
241     GET_FNPTR_OR_ERROR(&mFnPtrs->createPixmapPtr, glXCreatePixmap);
242     GET_FNPTR_OR_ERROR(&mFnPtrs->destroyPixmapPtr, glXDestroyPixmap);
243 
244     // Extensions
245     if (hasExtension("GLX_ARB_create_context"))
246     {
247         GET_PROC_OR_ERROR(&mFnPtrs->createContextAttribsARBPtr, glXCreateContextAttribsARB);
248     }
249     if (hasExtension("GLX_EXT_swap_control"))
250     {
251         GET_PROC_OR_ERROR(&mFnPtrs->swapIntervalEXTPtr, glXSwapIntervalEXT);
252     }
253     if (hasExtension("GLX_MESA_swap_control"))
254     {
255         GET_PROC_OR_ERROR(&mFnPtrs->swapIntervalMESAPtr, glXSwapIntervalMESA);
256     }
257     if (hasExtension("GLX_SGI_swap_control"))
258     {
259         GET_PROC_OR_ERROR(&mFnPtrs->swapIntervalSGIPtr, glXSwapIntervalSGI);
260     }
261     if (hasExtension("GLX_OML_sync_control"))
262     {
263         GET_PROC_OR_ERROR(&mFnPtrs->getSyncValuesOMLPtr, glXGetSyncValuesOML);
264         GET_PROC_OR_ERROR(&mFnPtrs->getMscRateOMLPtr, glXGetMscRateOML);
265     }
266     if (hasExtension("GLX_EXT_texture_from_pixmap"))
267     {
268         GET_PROC_OR_ERROR(&mFnPtrs->bindTexImageEXTPtr, glXBindTexImageEXT);
269         GET_PROC_OR_ERROR(&mFnPtrs->releaseTexImageEXTPtr, glXReleaseTexImageEXT);
270     }
271 
272 #undef GET_FNPTR_OR_ERROR
273 #undef GET_PROC_OR_ERROR
274 
275     *errorString = "";
276     return true;
277 }
278 
terminate()279 void FunctionsGLX::terminate() {}
280 
hasExtension(const char * extension) const281 bool FunctionsGLX::hasExtension(const char *extension) const
282 {
283     return std::find(mExtensions.begin(), mExtensions.end(), extension) != mExtensions.end();
284 }
285 
getDisplay() const286 Display *FunctionsGLX::getDisplay() const
287 {
288     return mXDisplay;
289 }
290 
getScreen() const291 int FunctionsGLX::getScreen() const
292 {
293     return mXScreen;
294 }
295 
296 // GLX functions
297 
298 // GLX 1.0
createContext(XVisualInfo * visual,glx::Context share,bool direct) const299 glx::Context FunctionsGLX::createContext(XVisualInfo *visual, glx::Context share, bool direct) const
300 {
301     GLXContext shareCtx = reinterpret_cast<GLXContext>(share);
302     GLXContext context  = mFnPtrs->createContextPtr(mXDisplay, visual, shareCtx, direct);
303     return reinterpret_cast<glx::Context>(context);
304 }
destroyContext(glx::Context context) const305 void FunctionsGLX::destroyContext(glx::Context context) const
306 {
307     GLXContext ctx = reinterpret_cast<GLXContext>(context);
308     mFnPtrs->destroyContextPtr(mXDisplay, ctx);
309 }
makeCurrent(glx::Drawable drawable,glx::Context context) const310 Bool FunctionsGLX::makeCurrent(glx::Drawable drawable, glx::Context context) const
311 {
312     GLXContext ctx = reinterpret_cast<GLXContext>(context);
313     return mFnPtrs->makeCurrentPtr(mXDisplay, drawable, ctx);
314 }
swapBuffers(glx::Drawable drawable) const315 void FunctionsGLX::swapBuffers(glx::Drawable drawable) const
316 {
317     mFnPtrs->swapBuffersPtr(mXDisplay, drawable);
318 }
queryExtension(int * errorBase,int * event) const319 Bool FunctionsGLX::queryExtension(int *errorBase, int *event) const
320 {
321     return mFnPtrs->queryExtensionPtr(mXDisplay, errorBase, event);
322 }
queryVersion(int * major,int * minor) const323 Bool FunctionsGLX::queryVersion(int *major, int *minor) const
324 {
325     return mFnPtrs->queryVersionPtr(mXDisplay, major, minor);
326 }
getCurrentContext() const327 glx::Context FunctionsGLX::getCurrentContext() const
328 {
329     GLXContext context = mFnPtrs->getCurrentContextPtr();
330     return reinterpret_cast<glx::Context>(context);
331 }
getCurrentDrawable() const332 glx::Drawable FunctionsGLX::getCurrentDrawable() const
333 {
334     GLXDrawable drawable = mFnPtrs->getCurrentDrawablePtr();
335     return reinterpret_cast<glx::Drawable>(drawable);
336 }
waitX() const337 void FunctionsGLX::waitX() const
338 {
339     mFnPtrs->waitXPtr();
340 }
waitGL() const341 void FunctionsGLX::waitGL() const
342 {
343     mFnPtrs->waitGLPtr();
344 }
345 
346 // GLX 1.1
getClientString(int name) const347 const char *FunctionsGLX::getClientString(int name) const
348 {
349     return mFnPtrs->getClientStringPtr(mXDisplay, name);
350 }
351 
queryExtensionsString() const352 const char *FunctionsGLX::queryExtensionsString() const
353 {
354     return mFnPtrs->queryExtensionsStringPtr(mXDisplay, mXScreen);
355 }
356 
357 // GLX 1.4
getFBConfigs(int * nElements) const358 glx::FBConfig *FunctionsGLX::getFBConfigs(int *nElements) const
359 {
360     GLXFBConfig *configs = mFnPtrs->getFBConfigsPtr(mXDisplay, mXScreen, nElements);
361     return reinterpret_cast<glx::FBConfig *>(configs);
362 }
chooseFBConfig(const int * attribList,int * nElements) const363 glx::FBConfig *FunctionsGLX::chooseFBConfig(const int *attribList, int *nElements) const
364 {
365     GLXFBConfig *configs = mFnPtrs->chooseFBConfigPtr(mXDisplay, mXScreen, attribList, nElements);
366     return reinterpret_cast<glx::FBConfig *>(configs);
367 }
getFBConfigAttrib(glx::FBConfig config,int attribute,int * value) const368 int FunctionsGLX::getFBConfigAttrib(glx::FBConfig config, int attribute, int *value) const
369 {
370     GLXFBConfig cfg = reinterpret_cast<GLXFBConfig>(config);
371     return mFnPtrs->getFBConfigAttribPtr(mXDisplay, cfg, attribute, value);
372 }
getVisualFromFBConfig(glx::FBConfig config) const373 XVisualInfo *FunctionsGLX::getVisualFromFBConfig(glx::FBConfig config) const
374 {
375     GLXFBConfig cfg = reinterpret_cast<GLXFBConfig>(config);
376     return mFnPtrs->getVisualFromFBConfigPtr(mXDisplay, cfg);
377 }
createWindow(glx::FBConfig config,Window window,const int * attribList) const378 GLXWindow FunctionsGLX::createWindow(glx::FBConfig config,
379                                      Window window,
380                                      const int *attribList) const
381 {
382     GLXFBConfig cfg = reinterpret_cast<GLXFBConfig>(config);
383     return mFnPtrs->createWindowPtr(mXDisplay, cfg, window, attribList);
384 }
destroyWindow(glx::Window window) const385 void FunctionsGLX::destroyWindow(glx::Window window) const
386 {
387     mFnPtrs->destroyWindowPtr(mXDisplay, window);
388 }
createPbuffer(glx::FBConfig config,const int * attribList) const389 glx::Pbuffer FunctionsGLX::createPbuffer(glx::FBConfig config, const int *attribList) const
390 {
391     GLXFBConfig cfg = reinterpret_cast<GLXFBConfig>(config);
392     return mFnPtrs->createPbufferPtr(mXDisplay, cfg, attribList);
393 }
destroyPbuffer(glx::Pbuffer pbuffer) const394 void FunctionsGLX::destroyPbuffer(glx::Pbuffer pbuffer) const
395 {
396     mFnPtrs->destroyPbufferPtr(mXDisplay, pbuffer);
397 }
queryDrawable(glx::Drawable drawable,int attribute,unsigned int * value) const398 void FunctionsGLX::queryDrawable(glx::Drawable drawable, int attribute, unsigned int *value) const
399 {
400     mFnPtrs->queryDrawablePtr(mXDisplay, drawable, attribute, value);
401 }
402 
createPixmap(glx::FBConfig config,Pixmap pixmap,const int * attribList) const403 glx::Pixmap FunctionsGLX::createPixmap(glx::FBConfig config,
404                                        Pixmap pixmap,
405                                        const int *attribList) const
406 {
407     GLXFBConfig cfg = reinterpret_cast<GLXFBConfig>(config);
408     return mFnPtrs->createPixmapPtr(mXDisplay, cfg, pixmap, attribList);
409 }
destroyPixmap(Pixmap pixmap) const410 void FunctionsGLX::destroyPixmap(Pixmap pixmap) const
411 {
412     mFnPtrs->destroyPixmapPtr(mXDisplay, pixmap);
413 }
414 
415 // GLX_ARB_create_context
createContextAttribsARB(glx::FBConfig config,glx::Context shareContext,Bool direct,const int * attribList) const416 glx::Context FunctionsGLX::createContextAttribsARB(glx::FBConfig config,
417                                                    glx::Context shareContext,
418                                                    Bool direct,
419                                                    const int *attribList) const
420 {
421     GLXContext shareCtx = reinterpret_cast<GLXContext>(shareContext);
422     GLXFBConfig cfg     = reinterpret_cast<GLXFBConfig>(config);
423     GLXContext ctx =
424         mFnPtrs->createContextAttribsARBPtr(mXDisplay, cfg, shareCtx, direct, attribList);
425     return reinterpret_cast<glx::Context>(ctx);
426 }
427 
swapIntervalEXT(glx::Drawable drawable,int intervals) const428 void FunctionsGLX::swapIntervalEXT(glx::Drawable drawable, int intervals) const
429 {
430     mFnPtrs->swapIntervalEXTPtr(mXDisplay, drawable, intervals);
431 }
432 
swapIntervalMESA(int intervals) const433 int FunctionsGLX::swapIntervalMESA(int intervals) const
434 {
435     return mFnPtrs->swapIntervalMESAPtr(intervals);
436 }
437 
swapIntervalSGI(int intervals) const438 int FunctionsGLX::swapIntervalSGI(int intervals) const
439 {
440     return mFnPtrs->swapIntervalSGIPtr(intervals);
441 }
442 
getSyncValuesOML(glx::Drawable drawable,int64_t * ust,int64_t * msc,int64_t * sbc) const443 bool FunctionsGLX::getSyncValuesOML(glx::Drawable drawable,
444                                     int64_t *ust,
445                                     int64_t *msc,
446                                     int64_t *sbc) const
447 {
448     return mFnPtrs->getSyncValuesOMLPtr(mXDisplay, drawable, ust, msc, sbc);
449 }
450 
getMscRateOML(glx::Drawable drawable,int32_t * numerator,int32_t * denominator) const451 bool FunctionsGLX::getMscRateOML(glx::Drawable drawable,
452                                  int32_t *numerator,
453                                  int32_t *denominator) const
454 {
455     return mFnPtrs->getMscRateOMLPtr(mXDisplay, drawable, numerator, denominator);
456 }
457 
bindTexImageEXT(glx::Drawable drawable,int buffer,const int * attribList) const458 void FunctionsGLX::bindTexImageEXT(glx::Drawable drawable, int buffer, const int *attribList) const
459 {
460     mFnPtrs->bindTexImageEXTPtr(mXDisplay, drawable, buffer, attribList);
461 }
releaseTexImageEXT(glx::Drawable drawable,int buffer) const462 void FunctionsGLX::releaseTexImageEXT(glx::Drawable drawable, int buffer) const
463 {
464     mFnPtrs->releaseTexImageEXTPtr(mXDisplay, drawable, buffer);
465 }
466 }  // namespace rx
467