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 <kbrenneman@nvidia.com>
26 */
27
28 #include "egldispatchstubs.h"
29 #include "g_egldispatchstubs.h"
30
31 #include <string.h>
32 #include <stdlib.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
Compare(const void * l,const void * r)41 static int Compare(const void *l, const void *r)
42 {
43 const char *s = *(const char **)r;
44 return strcmp(l, s);
45 }
46
FindProcIndex(const char * name)47 static int FindProcIndex(const char *name)
48 {
49 const char **match = bsearch(name, __EGL_DISPATCH_FUNC_NAMES,
50 __EGL_DISPATCH_COUNT, sizeof(const char *), Compare);
51
52 if (match == NULL)
53 return __EGL_DISPATCH_COUNT;
54
55 return match - __EGL_DISPATCH_FUNC_NAMES;
56 }
57
__eglInitDispatchStubs(const __EGLapiExports * exportsTable)58 void __eglInitDispatchStubs(const __EGLapiExports *exportsTable)
59 {
60 int i;
61 exports = exportsTable;
62 for (i=0; i<__EGL_DISPATCH_FUNC_COUNT; i++) {
63 __EGL_DISPATCH_FUNC_INDICES[i] = -1;
64 }
65 }
66
__eglSetDispatchIndex(const char * name,int dispatchIndex)67 void __eglSetDispatchIndex(const char *name, int dispatchIndex)
68 {
69 int index = FindProcIndex(name);
70 __EGL_DISPATCH_FUNC_INDICES[index] = dispatchIndex;
71 }
72
__eglDispatchFindDispatchFunction(const char * name)73 void *__eglDispatchFindDispatchFunction(const char *name)
74 {
75 int index = FindProcIndex(name);
76 return (void *) __EGL_DISPATCH_FUNCS[index];
77 }
78
FetchVendorFunc(__EGLvendorInfo * vendor,int index,EGLint errorCode)79 static __eglMustCastToProperFunctionPointerType FetchVendorFunc(__EGLvendorInfo *vendor,
80 int index, EGLint errorCode)
81 {
82 __eglMustCastToProperFunctionPointerType func = NULL;
83
84 if (vendor != NULL) {
85 func = exports->fetchDispatchEntry(vendor, __EGL_DISPATCH_FUNC_INDICES[index]);
86 }
87 if (func == NULL) {
88 if (errorCode != EGL_SUCCESS) {
89 // Since we have no vendor, the follow-up eglGetError() call will
90 // end up using the GLVND error code. Set it here.
91 if (vendor == NULL) {
92 exports->setEGLError(errorCode);
93 }
94 _eglError(errorCode, __EGL_DISPATCH_FUNC_NAMES[index]);
95 }
96 return NULL;
97 }
98
99 if (!exports->setLastVendor(vendor)) {
100 // Don't bother trying to set an error code in libglvnd. If
101 // setLastVendor failed, then setEGLError would also fail.
102 _eglError(errorCode, __EGL_DISPATCH_FUNC_NAMES[index]);
103 return NULL;
104 }
105
106 return func;
107 }
108
__eglDispatchFetchByCurrent(int index)109 __eglMustCastToProperFunctionPointerType __eglDispatchFetchByCurrent(int index)
110 {
111 __EGLvendorInfo *vendor;
112
113 // Note: This is only used for the eglWait* functions. For those, if
114 // there's no current context, then they're supposed to do nothing but
115 // return success.
116 exports->threadInit();
117 vendor = exports->getCurrentVendor();
118 return FetchVendorFunc(vendor, index, EGL_SUCCESS);
119 }
120
__eglDispatchFetchByDisplay(EGLDisplay dpy,int index)121 __eglMustCastToProperFunctionPointerType __eglDispatchFetchByDisplay(EGLDisplay dpy, int index)
122 {
123 __EGLvendorInfo *vendor;
124
125 exports->threadInit();
126 vendor = exports->getVendorFromDisplay(dpy);
127 return FetchVendorFunc(vendor, index, EGL_BAD_DISPLAY);
128 }
129
__eglDispatchFetchByDevice(EGLDeviceEXT dev,int index)130 __eglMustCastToProperFunctionPointerType __eglDispatchFetchByDevice(EGLDeviceEXT dev, int index)
131 {
132 __EGLvendorInfo *vendor;
133
134 exports->threadInit();
135 vendor = exports->getVendorFromDevice(dev);
136 return FetchVendorFunc(vendor, index, EGL_BAD_DEVICE_EXT);
137 }
138
139