Blame tests/testgldispatch.c

Packit 5af8b3
/*
Packit 5af8b3
 * Copyright (c) 2017, NVIDIA CORPORATION.
Packit 5af8b3
 *
Packit 5af8b3
 * Permission is hereby granted, free of charge, to any person obtaining a
Packit 5af8b3
 * copy of this software and/or associated documentation files (the
Packit 5af8b3
 * "Materials"), to deal in the Materials without restriction, including
Packit 5af8b3
 * without limitation the rights to use, copy, modify, merge, publish,
Packit 5af8b3
 * distribute, sublicense, and/or sell copies of the Materials, and to
Packit 5af8b3
 * permit persons to whom the Materials are furnished to do so, subject to
Packit 5af8b3
 * the following conditions:
Packit 5af8b3
 *
Packit 5af8b3
 * The above copyright notice and this permission notice shall be included
Packit 5af8b3
 * unaltered in all copies or substantial portions of the Materials.
Packit 5af8b3
 * Any additions, deletions, or changes to the original source files
Packit 5af8b3
 * must be clearly indicated in accompanying documentation.
Packit 5af8b3
 *
Packit 5af8b3
 * If only executable code is distributed, then the accompanying
Packit 5af8b3
 * documentation must state that "this software is based in part on the
Packit 5af8b3
 * work of the Khronos Group."
Packit 5af8b3
 *
Packit 5af8b3
 * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
Packit 5af8b3
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
Packit 5af8b3
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
Packit 5af8b3
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
Packit 5af8b3
 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
Packit 5af8b3
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
Packit 5af8b3
 * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
Packit 5af8b3
 */
Packit 5af8b3
Packit 5af8b3
#include <stdio.h>
Packit 5af8b3
#include <stdlib.h>
Packit 5af8b3
#include <string.h>
Packit 5af8b3
#include <getopt.h>
Packit 5af8b3
#include <pthread.h>
Packit 5af8b3
#include <GL/gl.h>
Packit 5af8b3
Packit 5af8b3
#include <GLdispatch.h>
Packit 5af8b3
Packit 5af8b3
#include "dummy/patchentrypoints.h"
Packit 5af8b3
Packit 5af8b3
#define DUMMY_VENDOR_COUNT 3
Packit 5af8b3
#define NUM_GLDISPATCH_CALLS 2
Packit 5af8b3
static const char *GENERATED_FUNCTION_NAME = "glDummyTestGLVND";
Packit 5af8b3
Packit 5af8b3
enum {
Packit 5af8b3
    CALL_INDEX_STATIC,
Packit 5af8b3
    CALL_INDEX_GENERATED,
Packit 5af8b3
    CALL_INDEX_STATIC_PATCH,
Packit 5af8b3
    CALL_INDEX_GENERATED_PATCH,
Packit 5af8b3
    CALL_INDEX_COUNT
Packit 5af8b3
};
Packit 5af8b3
Packit 5af8b3
typedef void (* pfn_glVertex3fv) (const GLfloat *v);
Packit 5af8b3
Packit 5af8b3
typedef struct DummyVendorLibRec {
Packit 5af8b3
    pfn_glVertex3fv vertexProc;
Packit 5af8b3
    pfn_glVertex3fv testProc;
Packit 5af8b3
    __GLgetProcAddressCallback getProcCallback;
Packit 5af8b3
Packit 5af8b3
    __GLdispatchThreadState threadState;
Packit 5af8b3
    __GLdispatchTable *dispatch;
Packit 5af8b3
    int vendorID;
Packit 5af8b3
    const __GLdispatchPatchCallbacks *patchCallbacksPtr;
Packit 5af8b3
    __GLdispatchPatchCallbacks patchCallbacks;
Packit 5af8b3
Packit 5af8b3
    int callCounts[CALL_INDEX_COUNT];
Packit 5af8b3
} DummyVendorLib;
Packit 5af8b3
Packit 5af8b3
static void InitDummyVendors(void);
Packit 5af8b3
static void CleanupDummyVendors(void);
Packit 5af8b3
Packit 5af8b3
static void *ForceMultiThreadedProc(void *param);
Packit 5af8b3
Packit 5af8b3
static GLboolean TestDispatch(int vendorIndex,
Packit 5af8b3
        GLboolean testStatic, GLboolean testGenerated);
Packit 5af8b3
Packit 5af8b3
static void *common_getProcAddressCallback(const char *procName, void *param, int vendorIndex);
Packit 5af8b3
static GLboolean common_InitiatePatch(int type, int stubSize,
Packit 5af8b3
        DispatchPatchLookupStubOffset lookupStubOffset, int vendorIndex);
Packit 5af8b3
Packit 5af8b3
static void *dummy0_getProcAddressCallback(const char *procName, void *param);
Packit 5af8b3
static void dummy0_glVertex3fv(const GLfloat *v);
Packit 5af8b3
static void dummy0_glDummyTestProc(const GLfloat *v);
Packit 5af8b3
static GLboolean dummy0_InitiatePatch(int type, int stubSize,
Packit 5af8b3
        DispatchPatchLookupStubOffset lookupStubOffset);
Packit 5af8b3
Packit 5af8b3
static void *dummy1_getProcAddressCallback(const char *procName, void *param);
Packit 5af8b3
static void dummy1_glVertex3fv(const GLfloat *v);
Packit 5af8b3
static void dummy1_glDummyTestProc(const GLfloat *v);
Packit 5af8b3
static GLboolean dummy1_InitiatePatch(int type, int stubSize,
Packit 5af8b3
        DispatchPatchLookupStubOffset lookupStubOffset);
Packit 5af8b3
Packit 5af8b3
static void *dummy2_getProcAddressCallback(const char *procName, void *param);
Packit 5af8b3
static void dummy2_glVertex3fv(const GLfloat *v);
Packit 5af8b3
static void dummy2_glDummyTestProc(const GLfloat *v);
Packit 5af8b3
Packit 5af8b3
static DummyVendorLib dummyVendors[DUMMY_VENDOR_COUNT] = {
Packit 5af8b3
    { dummy0_glVertex3fv, dummy0_glDummyTestProc, dummy0_getProcAddressCallback },
Packit 5af8b3
    { dummy1_glVertex3fv, dummy1_glDummyTestProc, dummy1_getProcAddressCallback },
Packit 5af8b3
    { dummy2_glVertex3fv, dummy2_glDummyTestProc, dummy2_getProcAddressCallback },
Packit 5af8b3
};
Packit 5af8b3
Packit 5af8b3
static pfn_glVertex3fv ptr_glVertex3fv;
Packit 5af8b3
static pfn_glVertex3fv ptr_glDummyTestProc;
Packit 5af8b3
Packit 5af8b3
static GLboolean enableStaticTest = GL_FALSE;
Packit 5af8b3
static GLboolean enableGeneratedTest = GL_FALSE;
Packit 5af8b3
static GLboolean enablePatching = GL_FALSE;
Packit 5af8b3
static GLboolean forceMultiThreaded = GL_FALSE;
Packit 5af8b3
Packit 5af8b3
int main(int argc, char **argv)
Packit 5af8b3
{
Packit 5af8b3
    int i;
Packit 5af8b3
Packit 5af8b3
    while (1) {
Packit 5af8b3
        int opt = getopt(argc, argv, "sgpt");
Packit 5af8b3
        if (opt == -1) {
Packit 5af8b3
            break;
Packit 5af8b3
        }
Packit 5af8b3
        switch (opt) {
Packit 5af8b3
        case 's':
Packit 5af8b3
            enableStaticTest = GL_TRUE;
Packit 5af8b3
            break;
Packit 5af8b3
        case 'g':
Packit 5af8b3
            enableGeneratedTest = GL_TRUE;
Packit 5af8b3
            break;
Packit 5af8b3
        case 'p':
Packit 5af8b3
            enablePatching = GL_TRUE;
Packit 5af8b3
            break;
Packit 5af8b3
        case 't':
Packit 5af8b3
            forceMultiThreaded = GL_TRUE;
Packit 5af8b3
            break;
Packit 5af8b3
        default:
Packit 5af8b3
            return 1;
Packit 5af8b3
        }
Packit 5af8b3
    };
Packit 5af8b3
Packit 5af8b3
    __glDispatchInit();
Packit 5af8b3
    InitDummyVendors();
Packit 5af8b3
Packit 5af8b3
    if (forceMultiThreaded) {
Packit 5af8b3
        pthread_t thr;
Packit 5af8b3
Packit 5af8b3
        printf("Forcing libGLdispatch into multi-threaded mode.\n");
Packit 5af8b3
        __glDispatchCheckMultithreaded();
Packit 5af8b3
        pthread_create(&thr, NULL, ForceMultiThreadedProc, NULL);
Packit 5af8b3
        pthread_join(thr, NULL);
Packit 5af8b3
    }
Packit 5af8b3
Packit 5af8b3
    ptr_glVertex3fv = (pfn_glVertex3fv) __glDispatchGetProcAddress("glVertex3fv");
Packit 5af8b3
    if (ptr_glVertex3fv == NULL) {
Packit 5af8b3
        printf("Can't find dispatch function for glVertex3fv\n");
Packit 5af8b3
    }
Packit 5af8b3
Packit 5af8b3
    if (enableGeneratedTest) {
Packit 5af8b3
        ptr_glDummyTestProc = (pfn_glVertex3fv) __glDispatchGetProcAddress(GENERATED_FUNCTION_NAME);
Packit 5af8b3
        if (ptr_glDummyTestProc == NULL) {
Packit 5af8b3
            printf("Can't find dispatch function for %s\n", GENERATED_FUNCTION_NAME);
Packit 5af8b3
        }
Packit 5af8b3
    }
Packit 5af8b3
Packit 5af8b3
    for (i=0; i
Packit 5af8b3
        if (!TestDispatch(i, enableStaticTest, enableGeneratedTest)) {
Packit 5af8b3
            return 1;
Packit 5af8b3
        }
Packit 5af8b3
    }
Packit 5af8b3
Packit 5af8b3
    CleanupDummyVendors();
Packit 5af8b3
    __glDispatchFini();
Packit 5af8b3
    return 0;
Packit 5af8b3
}
Packit 5af8b3
Packit 5af8b3
static void *ForceMultiThreadedProc(void *param)
Packit 5af8b3
{
Packit 5af8b3
    __glDispatchCheckMultithreaded();
Packit 5af8b3
    return NULL;
Packit 5af8b3
}
Packit 5af8b3
Packit 5af8b3
static void InitDummyVendors(void)
Packit 5af8b3
{
Packit 5af8b3
    int i;
Packit 5af8b3
    for (i=0; i
Packit 5af8b3
        dummyVendors[i].vendorID = __glDispatchNewVendorID();
Packit 5af8b3
        if (dummyVendors[i].vendorID == 0) {
Packit 5af8b3
            printf("__glDispatchNewVendorID failed\n");
Packit 5af8b3
            abort();
Packit 5af8b3
        }
Packit 5af8b3
Packit 5af8b3
        dummyVendors[i].dispatch = __glDispatchCreateTable(
Packit 5af8b3
                dummyVendors[i].getProcCallback, &dummyVendors[i]);
Packit 5af8b3
        if (dummyVendors[i].dispatch == NULL) {
Packit 5af8b3
            printf("__glDispatchCreateTable failed\n");
Packit 5af8b3
            abort();
Packit 5af8b3
        }
Packit 5af8b3
    }
Packit 5af8b3
Packit 5af8b3
    if (enablePatching) {
Packit 5af8b3
        dummyVendors[0].patchCallbacks.isPatchSupported = dummyCheckPatchSupported;
Packit 5af8b3
        dummyVendors[0].patchCallbacks.initiatePatch = dummy0_InitiatePatch;
Packit 5af8b3
        dummyVendors[0].patchCallbacksPtr = &dummyVendors[0].patchCallbacks;
Packit 5af8b3
Packit 5af8b3
        dummyVendors[1].patchCallbacks.isPatchSupported = dummyCheckPatchSupported;
Packit 5af8b3
        dummyVendors[1].patchCallbacks.initiatePatch = dummy1_InitiatePatch;
Packit 5af8b3
        dummyVendors[1].patchCallbacksPtr = &dummyVendors[1].patchCallbacks;
Packit 5af8b3
    }
Packit 5af8b3
}
Packit 5af8b3
Packit 5af8b3
static void CleanupDummyVendors(void)
Packit 5af8b3
{
Packit 5af8b3
    int i;
Packit 5af8b3
    for (i=0; i
Packit 5af8b3
        if (dummyVendors[i].dispatch != NULL) {
Packit 5af8b3
            __glDispatchDestroyTable(dummyVendors[i].dispatch);
Packit 5af8b3
            dummyVendors[i].dispatch = NULL;
Packit 5af8b3
        }
Packit 5af8b3
    }
Packit 5af8b3
}
Packit 5af8b3
Packit 5af8b3
static void ResetCallCounts(void)
Packit 5af8b3
{
Packit 5af8b3
    int i, j;
Packit 5af8b3
    for (i=0; i
Packit 5af8b3
        for (j=0; j
Packit 5af8b3
            dummyVendors[i].callCounts[j] = 0;
Packit 5af8b3
        }
Packit 5af8b3
    }
Packit 5af8b3
}
Packit 5af8b3
Packit 5af8b3
static GLboolean CheckCallCounts(int expectedVendorIndex, int expectedCallIndex, int count)
Packit 5af8b3
{
Packit 5af8b3
    int vendorIndex, callIndex;
Packit 5af8b3
    GLboolean result = GL_TRUE;
Packit 5af8b3
Packit 5af8b3
    for (vendorIndex=0; vendorIndex
Packit 5af8b3
        for (callIndex=0; callIndex
Packit 5af8b3
            int expected;
Packit 5af8b3
            if (vendorIndex == expectedVendorIndex && callIndex == expectedCallIndex) {
Packit 5af8b3
                expected = count;
Packit 5af8b3
            } else {
Packit 5af8b3
                expected = 0;
Packit 5af8b3
            }
Packit 5af8b3
Packit 5af8b3
            if (dummyVendors[vendorIndex].callCounts[callIndex] != expected) {
Packit 5af8b3
                printf("Wrong value for vendor %d, call %d: Expected %d, got %d\n",
Packit 5af8b3
                        vendorIndex, callIndex, expected,
Packit 5af8b3
                        dummyVendors[vendorIndex].callCounts[callIndex]);
Packit 5af8b3
                result = GL_FALSE;
Packit 5af8b3
            }
Packit 5af8b3
        }
Packit 5af8b3
    }
Packit 5af8b3
    return result;
Packit 5af8b3
}
Packit 5af8b3
Packit 5af8b3
static GLboolean TestDispatch(int vendorIndex,
Packit 5af8b3
        GLboolean testStatic, GLboolean testGenerated)
Packit 5af8b3
{
Packit 5af8b3
    int i;
Packit 5af8b3
    GLboolean result = GL_FALSE;
Packit 5af8b3
    GLboolean patched = (dummyVendors[vendorIndex].patchCallbacksPtr != NULL);
Packit 5af8b3
Packit 5af8b3
    if (!__glDispatchMakeCurrent(&dummyVendors[vendorIndex].threadState,
Packit 5af8b3
                dummyVendors[vendorIndex].dispatch, dummyVendors[vendorIndex].vendorID,
Packit 5af8b3
                dummyVendors[vendorIndex].patchCallbacksPtr)) {
Packit 5af8b3
        printf("__glDispatchMakeCurrent failed\n");
Packit 5af8b3
        return GL_FALSE;
Packit 5af8b3
    }
Packit 5af8b3
Packit 5af8b3
    printf("Testing vendor %d, patched = %d\n", vendorIndex, (int) patched);
Packit 5af8b3
    if (testStatic) {
Packit 5af8b3
        int callIndex = (patched ? CALL_INDEX_STATIC_PATCH : CALL_INDEX_STATIC);
Packit 5af8b3
Packit 5af8b3
        printf("Testing static dispatch through libOpenGL\n");
Packit 5af8b3
        ResetCallCounts();
Packit 5af8b3
        for (i = 0; i < NUM_GLDISPATCH_CALLS; i++) {
Packit 5af8b3
            glVertex3fv(NULL);
Packit 5af8b3
        }
Packit 5af8b3
        if (!CheckCallCounts(vendorIndex, callIndex, NUM_GLDISPATCH_CALLS)) {
Packit 5af8b3
            goto done;
Packit 5af8b3
        }
Packit 5af8b3
Packit 5af8b3
        printf("Testing static dispatch through GetProcAddress\n");
Packit 5af8b3
        ResetCallCounts();
Packit 5af8b3
        for (i = 0; i < NUM_GLDISPATCH_CALLS; i++) {
Packit 5af8b3
            ptr_glVertex3fv(NULL);
Packit 5af8b3
        }
Packit 5af8b3
        if (!CheckCallCounts(vendorIndex, callIndex, NUM_GLDISPATCH_CALLS)) {
Packit 5af8b3
            goto done;
Packit 5af8b3
        }
Packit 5af8b3
    }
Packit 5af8b3
Packit 5af8b3
    if (testGenerated) {
Packit 5af8b3
        int callIndex = (patched ? CALL_INDEX_GENERATED_PATCH : CALL_INDEX_GENERATED);
Packit 5af8b3
Packit 5af8b3
        printf("Testing generated dispatch\n");
Packit 5af8b3
        ResetCallCounts();
Packit 5af8b3
        for (i = 0; i < NUM_GLDISPATCH_CALLS; i++) {
Packit 5af8b3
            ptr_glDummyTestProc(NULL);
Packit 5af8b3
        }
Packit 5af8b3
        if (!CheckCallCounts(vendorIndex, callIndex, NUM_GLDISPATCH_CALLS)) {
Packit 5af8b3
            goto done;
Packit 5af8b3
        }
Packit 5af8b3
    }
Packit 5af8b3
Packit 5af8b3
    result = GL_TRUE;
Packit 5af8b3
Packit 5af8b3
done:
Packit 5af8b3
    __glDispatchLoseCurrent();
Packit 5af8b3
    return result;
Packit 5af8b3
}
Packit 5af8b3
Packit 5af8b3
static void *common_getProcAddressCallback(const char *procName, void *param, int vendorIndex)
Packit 5af8b3
{
Packit 5af8b3
    DummyVendorLib *dummyVendor = (DummyVendorLib *) param;
Packit 5af8b3
    if (dummyVendor != &dummyVendors[vendorIndex]) {
Packit 5af8b3
        printf("getProcAddress for vendor %d called with the wrong parameter\n", vendorIndex);
Packit 5af8b3
        abort();
Packit 5af8b3
    }
Packit 5af8b3
Packit 5af8b3
    if (strcmp(procName, "glVertex3fv") == 0) {
Packit 5af8b3
        return dummyVendor->vertexProc;
Packit 5af8b3
    } else if (strcmp(procName, GENERATED_FUNCTION_NAME) == 0) {
Packit 5af8b3
        return dummyVendor->testProc;
Packit 5af8b3
    } else {
Packit 5af8b3
        return NULL;
Packit 5af8b3
    }
Packit 5af8b3
}
Packit 5af8b3
Packit 5af8b3
static void *dummy0_getProcAddressCallback(const char *procName, void *param)
Packit 5af8b3
{
Packit 5af8b3
    return common_getProcAddressCallback(procName, param, 0);
Packit 5af8b3
}
Packit 5af8b3
Packit 5af8b3
static void *dummy1_getProcAddressCallback(const char *procName, void *param)
Packit 5af8b3
{
Packit 5af8b3
    return common_getProcAddressCallback(procName, param, 1);
Packit 5af8b3
}
Packit 5af8b3
Packit 5af8b3
static void *dummy2_getProcAddressCallback(const char *procName, void *param)
Packit 5af8b3
{
Packit 5af8b3
    return common_getProcAddressCallback(procName, param, 2);
Packit 5af8b3
}
Packit 5af8b3
Packit 5af8b3
static void dummy0_glVertex3fv(const GLfloat *v)
Packit 5af8b3
{
Packit 5af8b3
    dummyVendors[0].callCounts[CALL_INDEX_STATIC]++;
Packit 5af8b3
}
Packit 5af8b3
Packit 5af8b3
static void dummy1_glVertex3fv(const GLfloat *v)
Packit 5af8b3
{
Packit 5af8b3
    dummyVendors[1].callCounts[CALL_INDEX_STATIC]++;
Packit 5af8b3
}
Packit 5af8b3
Packit 5af8b3
static void dummy2_glVertex3fv(const GLfloat *v)
Packit 5af8b3
{
Packit 5af8b3
    dummyVendors[2].callCounts[CALL_INDEX_STATIC]++;
Packit 5af8b3
}
Packit 5af8b3
Packit 5af8b3
static void dummy0_glDummyTestProc(const GLfloat *v)
Packit 5af8b3
{
Packit 5af8b3
    dummyVendors[0].callCounts[CALL_INDEX_GENERATED]++;
Packit 5af8b3
}
Packit 5af8b3
Packit 5af8b3
static void dummy1_glDummyTestProc(const GLfloat *v)
Packit 5af8b3
{
Packit 5af8b3
    dummyVendors[1].callCounts[CALL_INDEX_GENERATED]++;
Packit 5af8b3
}
Packit 5af8b3
Packit 5af8b3
static void dummy2_glDummyTestProc(const GLfloat *v)
Packit 5af8b3
{
Packit 5af8b3
    dummyVendors[2].callCounts[CALL_INDEX_GENERATED]++;
Packit 5af8b3
}
Packit 5af8b3
Packit 5af8b3
static GLboolean common_InitiatePatch(int type, int stubSize,
Packit 5af8b3
        DispatchPatchLookupStubOffset lookupStubOffset, int vendorIndex)
Packit 5af8b3
{
Packit 5af8b3
    if (!dummyPatchFunction(type, stubSize, lookupStubOffset, "Vertex3fv",
Packit 5af8b3
                &dummyVendors[vendorIndex].callCounts[CALL_INDEX_STATIC_PATCH])) {
Packit 5af8b3
        return GL_FALSE;
Packit 5af8b3
    }
Packit 5af8b3
Packit 5af8b3
    if (enableGeneratedTest) {
Packit 5af8b3
        if (!dummyPatchFunction(type, stubSize, lookupStubOffset, GENERATED_FUNCTION_NAME,
Packit 5af8b3
                    &dummyVendors[vendorIndex].callCounts[CALL_INDEX_GENERATED_PATCH])) {
Packit 5af8b3
            return GL_FALSE;
Packit 5af8b3
        }
Packit 5af8b3
    }
Packit 5af8b3
    return GL_TRUE;
Packit 5af8b3
}
Packit 5af8b3
Packit 5af8b3
static GLboolean dummy0_InitiatePatch(int type, int stubSize,
Packit 5af8b3
        DispatchPatchLookupStubOffset lookupStubOffset)
Packit 5af8b3
{
Packit 5af8b3
    return common_InitiatePatch(type, stubSize, lookupStubOffset, 0);
Packit 5af8b3
}
Packit 5af8b3
Packit 5af8b3
static GLboolean dummy1_InitiatePatch(int type, int stubSize,
Packit 5af8b3
        DispatchPatchLookupStubOffset lookupStubOffset)
Packit 5af8b3
{
Packit 5af8b3
    return common_InitiatePatch(type, stubSize, lookupStubOffset, 1);
Packit 5af8b3
}
Packit 5af8b3