/* * Copyright (c) 2019, NVIDIA CORPORATION. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and/or associated documentation files (the * "Materials"), to deal in the Materials without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Materials, and to * permit persons to whom the Materials are furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be included * unaltered in all copies or substantial portions of the Materials. * Any additions, deletions, or changes to the original source files * must be clearly indicated in accompanying documentation. * * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. */ #include #include #include #include #include #include #include #include #define VENDOR_COUNT 2 #define THREAD_COUNT 4 #define CALL_COUNT 1 typedef struct { int vendorID; __GLdispatchTable *dispatch; } VendorInfo; typedef struct { __GLdispatchThreadState dispatchThreadState; pthread_t thread; VendorInfo *vendor; int callCountStatic; int callCountEarly; int callCountLate; GLboolean destroyed; } ThreadState; typedef void (* pfn_glVertex3fv) (const GLfloat *v); static sem_t mainSemaphore; static sem_t threadSemaphore; static pfn_glVertex3fv ptr_glVertex3fv = NULL; static pfn_glVertex3fv ptr_glTestFuncEarly = NULL; static pfn_glVertex3fv ptr_glTestFuncLate = NULL; static ThreadState *GetCurrentThreadState(void) { __GLdispatchThreadState *ts = __glDispatchGetCurrentThreadState(); if (ts == NULL) { printf("__glDispatchGetCurrentThreadState failed\n"); } return (ThreadState *) ts; } static void dummy_glVertex3fv(const GLfloat *v) { ThreadState *ts = GetCurrentThreadState(); ts->callCountStatic++; } static void glTestFuncEarlyDUMMY(const GLfloat *v) { ThreadState *ts = GetCurrentThreadState(); ts->callCountEarly++; } static void glTestFuncLateDUMMY(const GLfloat *v) { ThreadState *ts = GetCurrentThreadState(); ts->callCountLate++; } static void *VendorGetProcAddressCallback(const char *procName, void *param) { if (strcmp(procName, "glVertex3fv") == 0) { return dummy_glVertex3fv; } else if (strcmp(procName, "glTestFuncEarlyDUMMY") == 0) { return glTestFuncEarlyDUMMY; } else if (strcmp(procName, "glTestFuncLateDUMMY") == 0) { return glTestFuncLateDUMMY; } else { return NULL; } } static void ThreadDestroyedCallback(__GLdispatchThreadState *dispatchThreadState) { ThreadState *ts = (ThreadState *) dispatchThreadState; ts->destroyed = GL_TRUE; } static void *ThreadProc(void *param) { ThreadState *ts = (ThreadState *) param; int i; ts->dispatchThreadState.threadDestroyedCallback = ThreadDestroyedCallback; if (!__glDispatchMakeCurrent(&ts->dispatchThreadState, ts->vendor->dispatch, ts->vendor->vendorID, NULL)) { printf("__glDispatchMakeCurrent failed\n"); exit(1); } // Notify the main thread that we're ready. if (sem_post(&mainSemaphore) != 0) { printf("sem_post failed\n"); exit(1); } // Wait for the main thread to finish calling __glDispatchGetProcAddress. if (sem_wait(&threadSemaphore) != 0) { printf("sem_wait failed\n"); exit(1); } for (i=0; i