xref: /aosp_15_r20/external/mesa3d/src/egl/main/egldispatchstubs.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * (C) Copyright 2016, NVIDIA CORPORATION.
3  * All Rights Reserved.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * on the rights to use, copy, modify, merge, publish, distribute, sub
9  * license, and/or sell copies of the Software, and to permit persons to whom
10  * the Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice (including the next
13  * paragraph) shall be included in all copies or substantial portions of the
14  * Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
19  * IBM AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22  * IN THE SOFTWARE.
23  *
24  * Authors:
25  *    Kyle Brenneman <[email protected]>
26  */
27 
28 #include "egldispatchstubs.h"
29 #include "g_egldispatchstubs.h"
30 
31 #include <stdlib.h>
32 #include <string.h>
33 
34 #include "eglcurrent.h"
35 
36 static const __EGLapiExports *exports;
37 
38 const int __EGL_DISPATCH_FUNC_COUNT = __EGL_DISPATCH_COUNT;
39 int __EGL_DISPATCH_FUNC_INDICES[__EGL_DISPATCH_COUNT + 1];
40 
41 static int
Compare(const void * l,const void * r)42 Compare(const void *l, const void *r)
43 {
44    const char *s = *(const char **)r;
45    return strcmp(l, s);
46 }
47 
48 static int
FindProcIndex(const char * name)49 FindProcIndex(const char *name)
50 {
51    const char **match =
52       bsearch(name, __EGL_DISPATCH_FUNC_NAMES, __EGL_DISPATCH_COUNT,
53               sizeof(const char *), Compare);
54 
55    if (match == NULL)
56       return __EGL_DISPATCH_COUNT;
57 
58    return match - __EGL_DISPATCH_FUNC_NAMES;
59 }
60 
61 void
__eglInitDispatchStubs(const __EGLapiExports * exportsTable)62 __eglInitDispatchStubs(const __EGLapiExports *exportsTable)
63 {
64    int i;
65    exports = exportsTable;
66    for (i = 0; i < __EGL_DISPATCH_FUNC_COUNT; i++) {
67       __EGL_DISPATCH_FUNC_INDICES[i] = -1;
68    }
69 }
70 
71 void
__eglSetDispatchIndex(const char * name,int dispatchIndex)72 __eglSetDispatchIndex(const char *name, int dispatchIndex)
73 {
74    int index = FindProcIndex(name);
75    __EGL_DISPATCH_FUNC_INDICES[index] = dispatchIndex;
76 }
77 
78 void *
__eglDispatchFindDispatchFunction(const char * name)79 __eglDispatchFindDispatchFunction(const char *name)
80 {
81    int index = FindProcIndex(name);
82    return (void *)__EGL_DISPATCH_FUNCS[index];
83 }
84 
85 static __eglMustCastToProperFunctionPointerType
FetchVendorFunc(__EGLvendorInfo * vendor,int index,EGLint errorCode)86 FetchVendorFunc(__EGLvendorInfo *vendor, int index, EGLint errorCode)
87 {
88    __eglMustCastToProperFunctionPointerType func = NULL;
89 
90    if (vendor != NULL) {
91       func = exports->fetchDispatchEntry(vendor,
92                                          __EGL_DISPATCH_FUNC_INDICES[index]);
93    }
94    if (func == NULL) {
95       if (errorCode != EGL_SUCCESS) {
96          // Since we have no vendor, the follow-up eglGetError() call will
97          // end up using the GLVND error code. Set it here.
98          if (vendor == NULL) {
99             exports->setEGLError(errorCode);
100          }
101          _eglError(errorCode, __EGL_DISPATCH_FUNC_NAMES[index]);
102       }
103       return NULL;
104    }
105 
106    if (!exports->setLastVendor(vendor)) {
107       // Don't bother trying to set an error code in libglvnd. If
108       // setLastVendor failed, then setEGLError would also fail.
109       _eglError(errorCode, __EGL_DISPATCH_FUNC_NAMES[index]);
110       return NULL;
111    }
112 
113    return func;
114 }
115 
116 __eglMustCastToProperFunctionPointerType
__eglDispatchFetchByCurrent(int index)117 __eglDispatchFetchByCurrent(int index)
118 {
119    __EGLvendorInfo *vendor;
120 
121    // Note: This is only used for the eglWait* functions. For those, if
122    // there's no current context, then they're supposed to do nothing but
123    // return success.
124    exports->threadInit();
125    vendor = exports->getCurrentVendor();
126    return FetchVendorFunc(vendor, index, EGL_SUCCESS);
127 }
128 
129 __eglMustCastToProperFunctionPointerType
__eglDispatchFetchByDisplay(EGLDisplay dpy,int index)130 __eglDispatchFetchByDisplay(EGLDisplay dpy, int index)
131 {
132    __EGLvendorInfo *vendor;
133 
134    exports->threadInit();
135    vendor = exports->getVendorFromDisplay(dpy);
136    return FetchVendorFunc(vendor, index, EGL_BAD_DISPLAY);
137 }
138 
139 __eglMustCastToProperFunctionPointerType
__eglDispatchFetchByDevice(EGLDeviceEXT dev,int index)140 __eglDispatchFetchByDevice(EGLDeviceEXT dev, int index)
141 {
142    __EGLvendorInfo *vendor;
143 
144    exports->threadInit();
145    vendor = exports->getVendorFromDevice(dev);
146    return FetchVendorFunc(vendor, index, EGL_BAD_DEVICE_EXT);
147 }
148