17ec681f3Smrg/*
27ec681f3Smrg * (C) Copyright 2016, NVIDIA CORPORATION.
37ec681f3Smrg * All Rights Reserved.
47ec681f3Smrg *
57ec681f3Smrg * Permission is hereby granted, free of charge, to any person obtaining a
67ec681f3Smrg * copy of this software and associated documentation files (the "Software"),
77ec681f3Smrg * to deal in the Software without restriction, including without limitation
87ec681f3Smrg * on the rights to use, copy, modify, merge, publish, distribute, sub
97ec681f3Smrg * license, and/or sell copies of the Software, and to permit persons to whom
107ec681f3Smrg * the Software is furnished to do so, subject to the following conditions:
117ec681f3Smrg *
127ec681f3Smrg * The above copyright notice and this permission notice (including the next
137ec681f3Smrg * paragraph) shall be included in all copies or substantial portions of the
147ec681f3Smrg * Software.
157ec681f3Smrg *
167ec681f3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
177ec681f3Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
187ec681f3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
197ec681f3Smrg * IBM AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
207ec681f3Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
217ec681f3Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
227ec681f3Smrg * IN THE SOFTWARE.
237ec681f3Smrg *
247ec681f3Smrg * Authors:
257ec681f3Smrg *    Kyle Brenneman <kbrenneman@nvidia.com>
267ec681f3Smrg */
277ec681f3Smrg
2801e04c3fSmrg#include "egldispatchstubs.h"
2901e04c3fSmrg#include "g_egldispatchstubs.h"
3001e04c3fSmrg
3101e04c3fSmrg#include <string.h>
3201e04c3fSmrg#include <stdlib.h>
3301e04c3fSmrg
3401e04c3fSmrg#include "eglcurrent.h"
3501e04c3fSmrg
3601e04c3fSmrgstatic const __EGLapiExports *exports;
3701e04c3fSmrg
3801e04c3fSmrgconst int __EGL_DISPATCH_FUNC_COUNT = __EGL_DISPATCH_COUNT;
3901e04c3fSmrgint __EGL_DISPATCH_FUNC_INDICES[__EGL_DISPATCH_COUNT + 1];
4001e04c3fSmrg
4101e04c3fSmrgstatic int Compare(const void *l, const void *r)
4201e04c3fSmrg{
4301e04c3fSmrg    const char *s = *(const char **)r;
4401e04c3fSmrg    return strcmp(l, s);
4501e04c3fSmrg}
4601e04c3fSmrg
4701e04c3fSmrgstatic int FindProcIndex(const char *name)
4801e04c3fSmrg{
4901e04c3fSmrg    const char **match = bsearch(name, __EGL_DISPATCH_FUNC_NAMES,
5001e04c3fSmrg            __EGL_DISPATCH_COUNT, sizeof(const char *), Compare);
5101e04c3fSmrg
5201e04c3fSmrg    if (match == NULL)
5301e04c3fSmrg        return __EGL_DISPATCH_COUNT;
5401e04c3fSmrg
5501e04c3fSmrg    return match - __EGL_DISPATCH_FUNC_NAMES;
5601e04c3fSmrg}
5701e04c3fSmrg
5801e04c3fSmrgvoid __eglInitDispatchStubs(const __EGLapiExports *exportsTable)
5901e04c3fSmrg{
6001e04c3fSmrg    int i;
6101e04c3fSmrg    exports = exportsTable;
6201e04c3fSmrg    for (i=0; i<__EGL_DISPATCH_FUNC_COUNT; i++) {
6301e04c3fSmrg        __EGL_DISPATCH_FUNC_INDICES[i] = -1;
6401e04c3fSmrg    }
6501e04c3fSmrg}
6601e04c3fSmrg
6701e04c3fSmrgvoid __eglSetDispatchIndex(const char *name, int dispatchIndex)
6801e04c3fSmrg{
6901e04c3fSmrg    int index = FindProcIndex(name);
7001e04c3fSmrg    __EGL_DISPATCH_FUNC_INDICES[index] = dispatchIndex;
7101e04c3fSmrg}
7201e04c3fSmrg
7301e04c3fSmrgvoid *__eglDispatchFindDispatchFunction(const char *name)
7401e04c3fSmrg{
7501e04c3fSmrg    int index = FindProcIndex(name);
7601e04c3fSmrg    return (void *) __EGL_DISPATCH_FUNCS[index];
7701e04c3fSmrg}
7801e04c3fSmrg
7901e04c3fSmrgstatic __eglMustCastToProperFunctionPointerType FetchVendorFunc(__EGLvendorInfo *vendor,
8001e04c3fSmrg        int index, EGLint errorCode)
8101e04c3fSmrg{
8201e04c3fSmrg    __eglMustCastToProperFunctionPointerType func = NULL;
8301e04c3fSmrg
8401e04c3fSmrg    if (vendor != NULL) {
8501e04c3fSmrg        func = exports->fetchDispatchEntry(vendor, __EGL_DISPATCH_FUNC_INDICES[index]);
8601e04c3fSmrg    }
8701e04c3fSmrg    if (func == NULL) {
8801e04c3fSmrg        if (errorCode != EGL_SUCCESS) {
8901e04c3fSmrg            // Since we have no vendor, the follow-up eglGetError() call will
9001e04c3fSmrg            // end up using the GLVND error code. Set it here.
9101e04c3fSmrg            if (vendor == NULL) {
9201e04c3fSmrg                exports->setEGLError(errorCode);
9301e04c3fSmrg            }
9401e04c3fSmrg            _eglError(errorCode, __EGL_DISPATCH_FUNC_NAMES[index]);
9501e04c3fSmrg        }
9601e04c3fSmrg        return NULL;
9701e04c3fSmrg    }
9801e04c3fSmrg
9901e04c3fSmrg    if (!exports->setLastVendor(vendor)) {
10001e04c3fSmrg        // Don't bother trying to set an error code in libglvnd. If
10101e04c3fSmrg        // setLastVendor failed, then setEGLError would also fail.
10201e04c3fSmrg        _eglError(errorCode, __EGL_DISPATCH_FUNC_NAMES[index]);
10301e04c3fSmrg        return NULL;
10401e04c3fSmrg    }
10501e04c3fSmrg
10601e04c3fSmrg    return func;
10701e04c3fSmrg}
10801e04c3fSmrg
10901e04c3fSmrg__eglMustCastToProperFunctionPointerType __eglDispatchFetchByCurrent(int index)
11001e04c3fSmrg{
11101e04c3fSmrg    __EGLvendorInfo *vendor;
11201e04c3fSmrg
11301e04c3fSmrg    // Note: This is only used for the eglWait* functions. For those, if
11401e04c3fSmrg    // there's no current context, then they're supposed to do nothing but
11501e04c3fSmrg    // return success.
11601e04c3fSmrg    exports->threadInit();
11701e04c3fSmrg    vendor = exports->getCurrentVendor();
11801e04c3fSmrg    return FetchVendorFunc(vendor, index, EGL_SUCCESS);
11901e04c3fSmrg}
12001e04c3fSmrg
12101e04c3fSmrg__eglMustCastToProperFunctionPointerType __eglDispatchFetchByDisplay(EGLDisplay dpy, int index)
12201e04c3fSmrg{
12301e04c3fSmrg    __EGLvendorInfo *vendor;
12401e04c3fSmrg
12501e04c3fSmrg    exports->threadInit();
12601e04c3fSmrg    vendor = exports->getVendorFromDisplay(dpy);
12701e04c3fSmrg    return FetchVendorFunc(vendor, index, EGL_BAD_DISPLAY);
12801e04c3fSmrg}
12901e04c3fSmrg
13001e04c3fSmrg__eglMustCastToProperFunctionPointerType __eglDispatchFetchByDevice(EGLDeviceEXT dev, int index)
13101e04c3fSmrg{
13201e04c3fSmrg    __EGLvendorInfo *vendor;
13301e04c3fSmrg
13401e04c3fSmrg    exports->threadInit();
13501e04c3fSmrg    vendor = exports->getVendorFromDevice(dev);
13601e04c3fSmrg    return FetchVendorFunc(vendor, index, EGL_BAD_DEVICE_EXT);
13701e04c3fSmrg}
13801e04c3fSmrg
139