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