egldispatchstubs.c revision 01e04c3f
1#include "egldispatchstubs.h"
2#include "g_egldispatchstubs.h"
3
4#include <string.h>
5#include <stdlib.h>
6
7#include "eglcurrent.h"
8
9static const __EGLapiExports *exports;
10
11const int __EGL_DISPATCH_FUNC_COUNT = __EGL_DISPATCH_COUNT;
12int __EGL_DISPATCH_FUNC_INDICES[__EGL_DISPATCH_COUNT + 1];
13
14static int Compare(const void *l, const void *r)
15{
16    const char *s = *(const char **)r;
17    return strcmp(l, s);
18}
19
20static int FindProcIndex(const char *name)
21{
22    const char **match = bsearch(name, __EGL_DISPATCH_FUNC_NAMES,
23            __EGL_DISPATCH_COUNT, sizeof(const char *), Compare);
24
25    if (match == NULL)
26        return __EGL_DISPATCH_COUNT;
27
28    return match - __EGL_DISPATCH_FUNC_NAMES;
29}
30
31void __eglInitDispatchStubs(const __EGLapiExports *exportsTable)
32{
33    int i;
34    exports = exportsTable;
35    for (i=0; i<__EGL_DISPATCH_FUNC_COUNT; i++) {
36        __EGL_DISPATCH_FUNC_INDICES[i] = -1;
37    }
38}
39
40void __eglSetDispatchIndex(const char *name, int dispatchIndex)
41{
42    int index = FindProcIndex(name);
43    __EGL_DISPATCH_FUNC_INDICES[index] = dispatchIndex;
44}
45
46void *__eglDispatchFindDispatchFunction(const char *name)
47{
48    int index = FindProcIndex(name);
49    return (void *) __EGL_DISPATCH_FUNCS[index];
50}
51
52static __eglMustCastToProperFunctionPointerType FetchVendorFunc(__EGLvendorInfo *vendor,
53        int index, EGLint errorCode)
54{
55    __eglMustCastToProperFunctionPointerType func = NULL;
56
57    if (vendor != NULL) {
58        func = exports->fetchDispatchEntry(vendor, __EGL_DISPATCH_FUNC_INDICES[index]);
59    }
60    if (func == NULL) {
61        if (errorCode != EGL_SUCCESS) {
62            // Since we have no vendor, the follow-up eglGetError() call will
63            // end up using the GLVND error code. Set it here.
64            if (vendor == NULL) {
65                exports->setEGLError(errorCode);
66            }
67            _eglError(errorCode, __EGL_DISPATCH_FUNC_NAMES[index]);
68        }
69        return NULL;
70    }
71
72    if (!exports->setLastVendor(vendor)) {
73        // Don't bother trying to set an error code in libglvnd. If
74        // setLastVendor failed, then setEGLError would also fail.
75        _eglError(errorCode, __EGL_DISPATCH_FUNC_NAMES[index]);
76        return NULL;
77    }
78
79    return func;
80}
81
82__eglMustCastToProperFunctionPointerType __eglDispatchFetchByCurrent(int index)
83{
84    __EGLvendorInfo *vendor;
85
86    // Note: This is only used for the eglWait* functions. For those, if
87    // there's no current context, then they're supposed to do nothing but
88    // return success.
89    exports->threadInit();
90    vendor = exports->getCurrentVendor();
91    return FetchVendorFunc(vendor, index, EGL_SUCCESS);
92}
93
94__eglMustCastToProperFunctionPointerType __eglDispatchFetchByDisplay(EGLDisplay dpy, int index)
95{
96    __EGLvendorInfo *vendor;
97
98    exports->threadInit();
99    vendor = exports->getVendorFromDisplay(dpy);
100    return FetchVendorFunc(vendor, index, EGL_BAD_DISPLAY);
101}
102
103__eglMustCastToProperFunctionPointerType __eglDispatchFetchByDevice(EGLDeviceEXT dev, int index)
104{
105    __EGLvendorInfo *vendor;
106
107    exports->threadInit();
108    vendor = exports->getVendorFromDevice(dev);
109    return FetchVendorFunc(vendor, index, EGL_BAD_DEVICE_EXT);
110}
111
112