Merge branch 'github/fork/kbrenneman/fix-tests-no-assembly' into 'master'
Fix for unit tests with no assembly support Closes #154 See merge request glvnd/libglvnd!180
This commit is contained in:
commit
1613facce8
|
@ -66,3 +66,15 @@ build-i386-tsd:
|
|||
variables:
|
||||
CONFIGURE_OPTIONS: --build=i686-pc-linux-gnu CFLAGS=-m32 --disable-tls
|
||||
|
||||
build-pure-c-tls:
|
||||
extends:
|
||||
- .build-check
|
||||
variables:
|
||||
CONFIGURE_OPTIONS: --disable-asm
|
||||
|
||||
build-pure-c-tsd:
|
||||
extends:
|
||||
- .build-check
|
||||
variables:
|
||||
CONFIGURE_OPTIONS: --disable-asm --disable-tls
|
||||
|
||||
|
|
|
@ -271,6 +271,9 @@ AM_CONDITIONAL([GLDISPATCH_TYPE_ARMV7_TSD], [test "x$gldispatch_entry_type" = "x
|
|||
AM_CONDITIONAL([GLDISPATCH_TYPE_AARCH64_TSD], [test "x$gldispatch_entry_type" = "xaarch64_tsd"])
|
||||
AM_CONDITIONAL([GLDISPATCH_TYPE_PURE_C], [test "x$gldispatch_entry_type" = "xpure_c"])
|
||||
|
||||
AS_IF([test "x$gldispatch_entry_type" != "xpure_c"],
|
||||
[AC_DEFINE([USE_DISPATCH_ASM], 1,
|
||||
[Define to 1 if libGLdispatch and libGLX should use assembly dispatch functions.])])
|
||||
|
||||
AC_MSG_CHECKING([for constructor attributes])
|
||||
AC_COMPILE_IFELSE([AC_LANG_SOURCE([
|
||||
|
|
|
@ -37,17 +37,7 @@
|
|||
#include <sys/mman.h>
|
||||
#include <assert.h>
|
||||
|
||||
#if defined(USE_X86_ASM) || \
|
||||
defined(USE_X86_64_ASM) || \
|
||||
defined(USE_ARMV7_ASM) || \
|
||||
defined(USE_AARCH64_ASM) || \
|
||||
defined(USE_PPC64LE_ASM)
|
||||
# define USE_ASM 1
|
||||
#else
|
||||
# define USE_ASM 0
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) && USE_ASM
|
||||
#if defined(USE_DISPATCH_ASM)
|
||||
|
||||
/// The maximum number of entrypoints that we can generate.
|
||||
#define GENERATED_ENTRYPOINT_MAX 4096
|
||||
|
@ -344,7 +334,7 @@ void *DefaultDispatchFunc(void)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
#else // defined(__GNUC__) && USE_ASM
|
||||
#else // defined(USE_DISPATCH_ASM)
|
||||
|
||||
GLVNDentrypointStub glvndGenerateEntrypoint(const char *procName)
|
||||
{
|
||||
|
@ -359,4 +349,4 @@ void glvndUpdateEntrypoints(GLVNDentrypointUpdateCallback callback, void *param)
|
|||
{
|
||||
}
|
||||
|
||||
#endif // defined(__GNUC__) && USE_ASM
|
||||
#endif // defined(USE_DISPATCH_ASM)
|
||||
|
|
|
@ -71,6 +71,16 @@ testgldispatch_LDADD += dummy/libpatchentrypoints.la
|
|||
testgldispatch_LDADD += $(top_builddir)/src/util/libutils_misc.la
|
||||
testgldispatch_LDADD += $(PTHREAD_LIBS)
|
||||
|
||||
TESTS += testgldispatchthread.sh
|
||||
check_PROGRAMS += testgldispatchthread
|
||||
testgldispatchthread_SOURCES = \
|
||||
testgldispatchthread.c
|
||||
testgldispatchthread_CFLAGS = \
|
||||
-I$(top_srcdir)/include \
|
||||
-I$(top_srcdir)/src/GLdispatch \
|
||||
$(PTHREAD_CFLAGS)
|
||||
testgldispatchthread_LDADD = $(top_builddir)/src/GLdispatch/libGLdispatch.la
|
||||
|
||||
# Start of GLX-specific tests.
|
||||
# Notes that the TESTS_GLX variable must be defined outside the conditional, so
|
||||
# that we can include the test scripts in the EXTRA_DIST package. Otherwise,
|
||||
|
@ -81,13 +91,11 @@ TESTS_GLX += testglxcreatecontext.sh
|
|||
TESTS_GLX += testglxmcbasic.sh
|
||||
TESTS_GLX += testglxmcloop.sh
|
||||
TESTS_GLX += testglxmcthreads.sh
|
||||
TESTS_GLX += testglxmclate.sh
|
||||
TESTS_GLX += testglxmcoldlink.sh
|
||||
TESTS_GLX += testglxgetprocaddress.sh
|
||||
TESTS_GLX += testglxgetprocaddress_genentry.sh
|
||||
TESTS_GLX += testglxgetclientstr.sh
|
||||
TESTS_GLX += testglxqueryversion.sh
|
||||
TESTS_GLX += testpatchentrypoints.sh
|
||||
|
||||
if ENABLE_GLX
|
||||
|
||||
|
@ -129,9 +137,19 @@ testglxmakecurrent_oldlink_LDADD += $(top_builddir)/src/util/libutils_misc.la
|
|||
|
||||
|
||||
check_PROGRAMS += testglxgetprocaddress
|
||||
testglxgetprocaddress_CFLAGS = $(CFLAGS_COMMON) $(X11_CFLAGS)
|
||||
testglxgetprocaddress_CFLAGS = \
|
||||
$(CFLAGS_COMMON) \
|
||||
$(X11_CFLAGS) \
|
||||
-I$(top_srcdir)/include \
|
||||
-I$(top_srcdir)/src/GLdispatch
|
||||
testglxgetprocaddress_LDADD = $(X11_LIBS)
|
||||
testglxgetprocaddress_LDADD += $(top_builddir)/src/GLX/libGLX.la
|
||||
testglxgetprocaddress_LDADD += $(top_builddir)/src/GLdispatch/libGLdispatch.la
|
||||
|
||||
|
||||
check_PROGRAMS += testglxgetprocaddress_genentry
|
||||
testglxgetprocaddress_genentry_LDADD = -lX11
|
||||
testglxgetprocaddress_genentry_LDADD += $(top_builddir)/src/GLX/libGLX.la
|
||||
|
||||
|
||||
check_PROGRAMS += testglxgetclientstr
|
||||
|
@ -149,19 +167,6 @@ testglxqueryversion_LDADD = $(X11_LIBS)
|
|||
testglxqueryversion_LDADD += $(top_builddir)/src/GLX/libGLX.la
|
||||
testglxqueryversion_LDADD += $(top_builddir)/src/OpenGL/libOpenGL.la
|
||||
|
||||
|
||||
check_PROGRAMS += testpatchentrypoints
|
||||
testpatchentrypoints_SOURCES = \
|
||||
testpatchentrypoints.c \
|
||||
test_utils.c
|
||||
|
||||
testpatchentrypoints_CFLAGS = $(CFLAGS_COMMON) $(X11_CFLAGS)
|
||||
testpatchentrypoints_LDADD = $(X11_LIBS) @LIB_DL@
|
||||
testpatchentrypoints_LDADD += $(top_builddir)/src/GLX/libGLX.la
|
||||
testpatchentrypoints_LDADD += $(top_builddir)/src/OpenGL/libOpenGL.la
|
||||
testpatchentrypoints_LDADD += $(top_builddir)/src/util/libtrace.la
|
||||
testpatchentrypoints_LDADD += $(top_builddir)/src/util/libutils_misc.la
|
||||
|
||||
endif # ENABLE_GLX
|
||||
|
||||
|
||||
|
|
|
@ -67,11 +67,17 @@ static GLXContext dispatch_glXCreateContextVendorDUMMY(Display *dpy,
|
|||
|
||||
static void dummy_glXExampleExtensionFunction(Display *dpy, int screen, int *retval);
|
||||
static void dispatch_glXExampleExtensionFunction(Display *dpy, int screen, int *retval);
|
||||
static void dummy_glXExampleExtensionFunction2(Display *dpy, int screen, int *retval);
|
||||
static void dispatch_glXExampleExtensionFunction2(Display *dpy, int screen, int *retval);
|
||||
static void dummy_glXMakeCurrentTestResults(GLint req, GLboolean *saw, void **ret);
|
||||
static void dispatch_glXMakeCurrentTestResults(GLint req, GLboolean *saw, void **ret);
|
||||
|
||||
enum
|
||||
{
|
||||
DI_glXExampleExtensionFunction,
|
||||
DI_glXExampleExtensionFunction2,
|
||||
DI_glXCreateContextVendorDUMMY,
|
||||
DI_glXMakeCurrentTestResults,
|
||||
DI_COUNT,
|
||||
};
|
||||
static struct {
|
||||
|
@ -82,7 +88,9 @@ static struct {
|
|||
} glxExtensionProcs[] = {
|
||||
#define PROC_ENTRY(name) { #name, dummy_##name, dispatch_##name, -1 }
|
||||
PROC_ENTRY(glXExampleExtensionFunction),
|
||||
PROC_ENTRY(glXExampleExtensionFunction2),
|
||||
PROC_ENTRY(glXCreateContextVendorDUMMY),
|
||||
PROC_ENTRY(glXMakeCurrentTestResults),
|
||||
#undef PROC_ENTRY
|
||||
};
|
||||
|
||||
|
@ -520,9 +528,7 @@ static void dummy_glEnd (void)
|
|||
ctx->endHit++;
|
||||
}
|
||||
|
||||
static void dummy_glMakeCurrentTestResults(GLint req,
|
||||
GLboolean *saw,
|
||||
void **ret)
|
||||
static void dummy_glXMakeCurrentTestResults(GLint req, GLboolean *saw, void **ret)
|
||||
{
|
||||
GLXContext ctx = apiExports->getCurrentContext();
|
||||
assert(ctx);
|
||||
|
@ -538,15 +544,6 @@ static void dummy_glMakeCurrentTestResults(GLint req,
|
|||
*ret = (void *)data;
|
||||
}
|
||||
break;
|
||||
case GL_MC_VENDOR_STRING:
|
||||
{
|
||||
// FIXME: This is used from testglxnscreens to check that the
|
||||
// correct vendor library is loaded from each display. Originally,
|
||||
// it used the vendor name passed to __glx_Main, but libGLX doesn't
|
||||
// provide the vendor name anymore.
|
||||
*ret = NULL;
|
||||
}
|
||||
break;
|
||||
case GL_MC_LAST_REQ:
|
||||
default:
|
||||
*ret = NULL;
|
||||
|
@ -554,35 +551,76 @@ static void dummy_glMakeCurrentTestResults(GLint req,
|
|||
}
|
||||
}
|
||||
|
||||
static void dispatch_glXMakeCurrentTestResults(GLint req, GLboolean *saw, void **ret)
|
||||
{
|
||||
__GLXvendorInfo *dynDispatch;
|
||||
PFNGLXMAKECURRENTTESTRESULTSPROC func;
|
||||
const int index = glxExtensionProcs[DI_glXMakeCurrentTestResults].index;
|
||||
|
||||
dynDispatch = apiExports->getCurrentDynDispatch();
|
||||
if (!dynDispatch) {
|
||||
return;
|
||||
}
|
||||
|
||||
func = (PFNGLXMAKECURRENTTESTRESULTSPROC)
|
||||
apiExports->fetchDispatchEntry(dynDispatch, index);
|
||||
if (func) {
|
||||
func(req, saw, ret);
|
||||
}
|
||||
}
|
||||
|
||||
static void dummy_glXExampleExtensionFunction(Display *dpy, int screen, int *retval)
|
||||
{
|
||||
// Indicate that we've called the real function, and not a dispatch stub
|
||||
*retval = 1;
|
||||
}
|
||||
|
||||
static void dispatch_glXExampleExtensionFunction(Display *dpy,
|
||||
static void commonDispatch_glXExampleExtensionFunction(Display *dpy,
|
||||
int screen,
|
||||
int *retval)
|
||||
int *retval,
|
||||
int funcIndex)
|
||||
{
|
||||
typedef void (*ExampleExtensionFunctionPtr)(Display *dpy,
|
||||
int screen,
|
||||
int *retval);
|
||||
__GLXvendorInfo *dynDispatch;
|
||||
ExampleExtensionFunctionPtr func;
|
||||
const int index = glxExtensionProcs[DI_glXExampleExtensionFunction].index;
|
||||
PFNGLXEXAMPLEEXTENSIONFUNCTION func;
|
||||
const int index = glxExtensionProcs[funcIndex].index;
|
||||
|
||||
dynDispatch = apiExports->getDynDispatch(dpy, screen);
|
||||
if (!dynDispatch) {
|
||||
return;
|
||||
}
|
||||
|
||||
func = (ExampleExtensionFunctionPtr)
|
||||
func = (PFNGLXEXAMPLEEXTENSIONFUNCTION)
|
||||
apiExports->fetchDispatchEntry(dynDispatch, index);
|
||||
if (func) {
|
||||
func(dpy, screen, retval);
|
||||
}
|
||||
}
|
||||
|
||||
static void dispatch_glXExampleExtensionFunction(Display *dpy,
|
||||
int screen,
|
||||
int *retval)
|
||||
{
|
||||
// Set a different value here. That way, if a test fails, you can easily
|
||||
// tell if it got as far as the dispatch function.
|
||||
*retval = -1;
|
||||
commonDispatch_glXExampleExtensionFunction(dpy, screen, retval,
|
||||
DI_glXExampleExtensionFunction);
|
||||
}
|
||||
|
||||
static void dummy_glXExampleExtensionFunction2(Display *dpy, int screen, int *retval)
|
||||
{
|
||||
*retval = 2;
|
||||
}
|
||||
|
||||
static void dispatch_glXExampleExtensionFunction2(Display *dpy,
|
||||
int screen,
|
||||
int *retval)
|
||||
{
|
||||
*retval = -2;
|
||||
commonDispatch_glXExampleExtensionFunction(dpy, screen, retval,
|
||||
DI_glXExampleExtensionFunction2);
|
||||
}
|
||||
|
||||
/*
|
||||
* Note we only fill in real implementations for a few core GL functions.
|
||||
* The rest will dispatch to the NOP stub.
|
||||
|
@ -595,7 +633,6 @@ static const struct {
|
|||
PROC_ENTRY(glBegin),
|
||||
PROC_ENTRY(glEnd),
|
||||
PROC_ENTRY(glVertex3fv),
|
||||
PROC_ENTRY(glMakeCurrentTestResults),
|
||||
|
||||
PROC_ENTRY(glXChooseVisual),
|
||||
PROC_ENTRY(glXCopyContext),
|
||||
|
|
|
@ -48,11 +48,6 @@ enum {
|
|||
*/
|
||||
GL_MC_FUNCTION_COUNTS,
|
||||
|
||||
/*
|
||||
* Returns a NULL-terminated string describing the name of this vendor.
|
||||
*/
|
||||
GL_MC_VENDOR_STRING,
|
||||
|
||||
/*
|
||||
* Last request. Always returns NULL.
|
||||
*/
|
||||
|
@ -67,8 +62,16 @@ enum {
|
|||
*/
|
||||
#define GLX_CONTEX_ATTRIB_DUMMY 0x10000
|
||||
|
||||
/**
|
||||
* glXExampleExtensionFunction(): Dummy GLX extension function.
|
||||
*
|
||||
* This function just assigns 1 to *retval. It's used to test dispatching
|
||||
* through a venodr-supplied dispatch function.
|
||||
*/
|
||||
typedef void (* PFNGLXEXAMPLEEXTENSIONFUNCTION) (Display *dpy, int screen, int *retval);
|
||||
|
||||
/*
|
||||
* glMakeCurrentTestResults(): perform queries on vendor library state.
|
||||
* glXMakeCurrentTestResults(): perform queries on vendor library state.
|
||||
*
|
||||
* This explicitly is designed to not return anything, in case a bug causes the
|
||||
* API library to dispatch this to a no-op stub. If this function returned a
|
||||
|
@ -85,7 +88,7 @@ enum {
|
|||
* set to NULL if there was an error, or a pointer to request-specific data
|
||||
* otherwise. The pointer may be passed into free(3).
|
||||
*/
|
||||
typedef void (*PFNGLMAKECURRENTTESTRESULTSPROC)(
|
||||
typedef void (*PFNGLXMAKECURRENTTESTRESULTSPROC)(
|
||||
GLint req,
|
||||
GLboolean *saw,
|
||||
void **ret
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#!/bin/sh
|
||||
|
||||
__GLX_VENDOR_LIBRARY_NAME=dummy
|
||||
export __GLX_VENDOR_LIBRARY_NAME
|
||||
__GLX_FORCE_VENDOR_LIBRARY_0=dummy
|
||||
export __GLX_FORCE_VENDOR_LIBRARY_0
|
||||
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$TOP_BUILDDIR/tests/dummy/.libs
|
||||
export LD_LIBRARY_PATH
|
||||
|
|
|
@ -135,6 +135,16 @@ int main(int argc, char **argv)
|
|||
}
|
||||
};
|
||||
|
||||
#if !defined(USE_DISPATCH_ASM)
|
||||
// If the assembly dispatch stubs aren't enabled, then generating and
|
||||
// patching entrypoints won't work. In that case, exit with 77 to tell
|
||||
// automake to skip the test instead of failing.
|
||||
if (enablePatching || enableGeneratedTest)
|
||||
{
|
||||
return 77;
|
||||
}
|
||||
#endif
|
||||
|
||||
__glDispatchInit();
|
||||
InitDummyVendors();
|
||||
|
||||
|
|
275
tests/testgldispatchthread.c
Normal file
275
tests/testgldispatchthread.c
Normal file
|
@ -0,0 +1,275 @@
|
|||
/*
|
||||
* 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.
|
||||
*
|
||||
* If only executable code is distributed, then the accompanying
|
||||
* documentation must state that "this software is based in part on the
|
||||
* work of the Khronos Group."
|
||||
*
|
||||
* 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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <getopt.h>
|
||||
#include <pthread.h>
|
||||
#include <semaphore.h>
|
||||
#include <GL/gl.h>
|
||||
|
||||
#include <GLdispatch.h>
|
||||
|
||||
#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<CALL_COUNT; i++) {
|
||||
ptr_glVertex3fv(NULL);
|
||||
if (ptr_glTestFuncEarly != NULL) {
|
||||
ptr_glTestFuncEarly(NULL);
|
||||
}
|
||||
if (ptr_glTestFuncLate != NULL) {
|
||||
ptr_glTestFuncLate(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
VendorInfo vendors[VENDOR_COUNT] = {};
|
||||
ThreadState threads[THREAD_COUNT] = {};
|
||||
int result, i;
|
||||
|
||||
if (sem_init(&mainSemaphore, 0, 0) != 0) {
|
||||
printf("sem_init failed\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (sem_init(&threadSemaphore, 0, 0) != 0) {
|
||||
printf("sem_init failed\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
__glDispatchInit();
|
||||
|
||||
ptr_glVertex3fv = (pfn_glVertex3fv) __glDispatchGetProcAddress("glVertex3fv");
|
||||
if (ptr_glVertex3fv == NULL) {
|
||||
printf("__glDispatchGetProcAddress(glVertex3fv) failed\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if defined(USE_DISPATCH_ASM)
|
||||
ptr_glTestFuncEarly = (pfn_glVertex3fv) __glDispatchGetProcAddress("glTestFuncEarlyDUMMY");
|
||||
if (ptr_glTestFuncEarly == NULL) {
|
||||
printf("__glDispatchGetProcAddress(glTestFuncEarlyDUMMY) failed\n");
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Create some dummy vendors and dispatch tables.
|
||||
for (i=0; i<VENDOR_COUNT; i++) {
|
||||
vendors[i].vendorID = __glDispatchNewVendorID();
|
||||
vendors[i].dispatch = __glDispatchCreateTable(VendorGetProcAddressCallback, &vendors[i]);
|
||||
if (vendors[i].dispatch == NULL) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Start the worker threads.
|
||||
for (i=0; i<THREAD_COUNT; i++) {
|
||||
threads[i].vendor = &vendors[i % VENDOR_COUNT];
|
||||
|
||||
if (pthread_create(&threads[i].thread, NULL, ThreadProc, &threads[i]) != 0) {
|
||||
printf("Failed to create thread\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Wait for each thread to be ready. After this, each thread will have
|
||||
// called __glDispatchMakeCurrent, and is waiting for the main thread to
|
||||
// tell it to proceed.
|
||||
for (i=0; i<THREAD_COUNT; i++) {
|
||||
if (sem_wait(&mainSemaphore) != 0) {
|
||||
printf("sem_wait failed\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(USE_DISPATCH_ASM)
|
||||
// Generate another GL function. This tests whether libGLdispatch will
|
||||
// correctly update existing dispatch tables that are current to some
|
||||
// thread.
|
||||
ptr_glTestFuncLate = (pfn_glVertex3fv) __glDispatchGetProcAddress("glTestFuncLateDUMMY");
|
||||
if (ptr_glTestFuncLate == NULL) {
|
||||
printf("__glDispatchGetProcAddress(glTestFuncLateDUMMY) failed\n");
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Wake up the threads and let them continue. The threads will try calling
|
||||
// each of the GL functions.
|
||||
for (i=0; i<THREAD_COUNT; i++) {
|
||||
if (sem_post(&threadSemaphore) != 0) {
|
||||
printf("sem_post failed\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Wait for the threads to finish.
|
||||
for (i=0; i<THREAD_COUNT; i++) {
|
||||
pthread_join(threads[i].thread, NULL);
|
||||
}
|
||||
|
||||
// Check the results.
|
||||
result = 0;
|
||||
for (i=0; i<THREAD_COUNT; i++) {
|
||||
if (threads[i].callCountStatic != CALL_COUNT) {
|
||||
printf("Thread %d: Static call count is wrong: %d\n", i, threads[i].callCountStatic);
|
||||
result = 1;
|
||||
}
|
||||
if (ptr_glTestFuncEarly != NULL) {
|
||||
if (threads[i].callCountEarly != CALL_COUNT) {
|
||||
printf("Thread %d: Early call count is wrong: %d\n", i, threads[i].callCountEarly);
|
||||
result = 1;
|
||||
}
|
||||
}
|
||||
if (ptr_glTestFuncLate != NULL) {
|
||||
if (threads[i].callCountLate != CALL_COUNT) {
|
||||
printf("Thread %d: Late call count is wrong: %d\n", i, threads[i].callCountLate);
|
||||
result = 1;
|
||||
}
|
||||
}
|
||||
if (!threads[i].destroyed) {
|
||||
printf("Thread %d: Destroy callback was not called\n", i);
|
||||
result = 1;
|
||||
}
|
||||
}
|
||||
|
||||
for (i=0; i<VENDOR_COUNT; i++) {
|
||||
if (vendors[i].dispatch != NULL) {
|
||||
__glDispatchDestroyTable(vendors[i].dispatch);
|
||||
}
|
||||
}
|
||||
|
||||
sem_destroy(&mainSemaphore);
|
||||
sem_destroy(&threadSemaphore);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
4
tests/testgldispatchthread.sh
Executable file
4
tests/testgldispatchthread.sh
Executable file
|
@ -0,0 +1,4 @@
|
|||
#!/bin/sh
|
||||
|
||||
./testgldispatchthread
|
||||
|
|
@ -27,42 +27,28 @@
|
|||
* MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
*/
|
||||
|
||||
#include <GL/glx.h>
|
||||
#include <GL/gl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
typedef __GLXextFuncPtr (* pfn_glXGetProcAddress) (const GLubyte *procName);
|
||||
static pfn_glXGetProcAddress ptr_glXGetProcAddress;
|
||||
#include <GL/glx.h>
|
||||
#include <GL/gl.h>
|
||||
|
||||
typedef void (* pfn_glXWaitGL) (void);
|
||||
static pfn_glXWaitGL ptr_glXWaitGL;
|
||||
#include <GLdispatch.h>
|
||||
#include "dummy/GLX_dummy.h"
|
||||
|
||||
typedef void (* pfn_glVertex3fv) (const GLfloat *v);
|
||||
static pfn_glVertex3fv ptr_glVertex3fv;
|
||||
|
||||
typedef void (* pfn_glXExampleExtensionFunction) (Display *dpy, int screen, int *retval);
|
||||
static pfn_glXExampleExtensionFunction ptr_glXExampleExtensionFunction;
|
||||
|
||||
typedef void (* pfn_glBogusFunc1) (int a, int b, int c);
|
||||
static pfn_glBogusFunc1 ptr_glBogusFunc1;
|
||||
|
||||
typedef void (* pfn_glBogusFunc2) (int a, int b, int c);
|
||||
static pfn_glBogusFunc2 ptr_glBogusFunc2;
|
||||
typedef const char * (* pfn_glXQueryServerString) (Display *dpy, int screen, int name);
|
||||
|
||||
static void *LoadFunction(const char *name);
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
Display *dpy = NULL;
|
||||
int retval = 0;
|
||||
pfn_glXQueryServerString ptr_glXQueryServerString;
|
||||
PFNGLXEXAMPLEEXTENSIONFUNCTION ptr_glXExampleExtensionFunction;
|
||||
|
||||
/*
|
||||
* Try GetProcAddress on different classes of API functions, and bogus
|
||||
* functions. The API library should return entry point addresses for
|
||||
* any function beginning with gl*(), though bogus functions will resolve
|
||||
* to no-ops.
|
||||
*/
|
||||
Display *dpy = NULL;
|
||||
const char *str;
|
||||
__GLdispatchProc dispatchPtr, glxPtr;
|
||||
int retval = 0;
|
||||
|
||||
dpy = XOpenDisplay(NULL);
|
||||
if (dpy == NULL) {
|
||||
|
@ -70,61 +56,44 @@ int main(int argc, char **argv)
|
|||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Load the function addresses up front. Note that in order to test GLX
|
||||
* entrypoint generation, we have to load the functions early, before
|
||||
* libGLX.so loads the vendor library.
|
||||
*/
|
||||
ptr_glXGetProcAddress = (pfn_glXGetProcAddress)
|
||||
LoadFunction("glXGetProcAddress");
|
||||
ptr_glXWaitGL = (pfn_glXWaitGL) LoadFunction("glXWaitGL");
|
||||
ptr_glXExampleExtensionFunction = (pfn_glXExampleExtensionFunction)
|
||||
LoadFunction("glXExampleExtensionFunction");
|
||||
ptr_glVertex3fv = (pfn_glVertex3fv) LoadFunction("glVertex3fv");
|
||||
ptr_glBogusFunc1 = (pfn_glBogusFunc1) LoadFunction("glBogusFunc1");
|
||||
ptr_glBogusFunc2 = (pfn_glBogusFunc2) LoadFunction("glBogusFunc2");
|
||||
|
||||
/*
|
||||
* Test core GLX dispatch functions implemented by API library. This
|
||||
* simply returns the symbol exported by libGLX.
|
||||
*/
|
||||
ptr_glXGetProcAddress((const GLubyte *) "glBogusFunc1");
|
||||
ptr_glXWaitGL();
|
||||
|
||||
// Call glXGetClientString to force libGLX to load the vendor library.
|
||||
glXGetClientString(dpy, GLX_EXTENSIONS);
|
||||
|
||||
/*
|
||||
* Test a "GLX extension" function with a vendor-neutral dispatcher
|
||||
* implemented by the vendor library (in this case, libGLX_dummy). If we
|
||||
* successfully used libGLX_dummy's dispatcher, retval should be non-zero
|
||||
* (a zero value indicates we might be calling into a no-op stub generated
|
||||
* by libGLdispatch).
|
||||
*/
|
||||
ptr_glXExampleExtensionFunction(dpy, 0, &retval);
|
||||
if (!retval) {
|
||||
printf("Unexpected glXExampleExtensionFunction() return value!\n");
|
||||
// Test a core GLX function first.
|
||||
ptr_glXQueryServerString = (pfn_glXQueryServerString) LoadFunction("glXQueryServerString");
|
||||
str = ptr_glXQueryServerString(dpy, 0, GLX_VENDOR);
|
||||
if (str == NULL) {
|
||||
printf("glXQueryServerString returned NULL\n");
|
||||
return 1;
|
||||
}
|
||||
if (strcmp(str, "testlib") != 0) {
|
||||
printf("glXQueryServerString returned unexpected value: %s\n", str);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Try getting the address of the core GL function glVertex3fv().
|
||||
* This retrieves a static stub from glapi.
|
||||
* Note calling this function with a NULL pointer is fine since this is a
|
||||
* no-op function while there is no context current.
|
||||
* Test a "GLX extension" function with a vendor-neutral dispatcher
|
||||
* implemented by the vendor library (in this case, libGLX_dummy). If we
|
||||
* successfully used libGLX_dummy's dispatcher, retval should be 1.
|
||||
*/
|
||||
ptr_glVertex3fv(NULL);
|
||||
ptr_glXExampleExtensionFunction = (PFNGLXEXAMPLEEXTENSIONFUNCTION)
|
||||
LoadFunction("glXExampleExtensionFunction");
|
||||
ptr_glXExampleExtensionFunction(dpy, 0, &retval);
|
||||
if (retval != 1) {
|
||||
printf("Unexpected glXExampleExtensionFunction() return value: %d\n", retval);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* These are bogus functions, but will get a valid entry point since they
|
||||
* are prefixed with "gl". The first GetProcAddress() will early out since
|
||||
* there should be a cached copy from the explicit call made above, but
|
||||
* the second one will go through glapi's dynamic stub generation path.
|
||||
*
|
||||
* Again, calling these functions should be a no-op.
|
||||
*/
|
||||
ptr_glBogusFunc1(0, 0, 0);
|
||||
ptr_glBogusFunc2(1, 1, 1);
|
||||
// Test loading a normal GL function. Load the function through
|
||||
// glXGetProcAddress, and then again directly through libGLdispatch. We
|
||||
// should get the same poiner for both.
|
||||
glxPtr = LoadFunction("glVertex3fv");
|
||||
dispatchPtr = __glDispatchGetProcAddress("glVertex3fv");
|
||||
if (dispatchPtr != glxPtr) {
|
||||
printf("Mismatch for function glVertex3fv: GLX returned %p, GLdispatch returned %p\n",
|
||||
glxPtr, dispatchPtr);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Success!
|
||||
return 0;
|
||||
|
@ -132,12 +101,21 @@ int main(int argc, char **argv)
|
|||
|
||||
static void *LoadFunction(const char *name)
|
||||
{
|
||||
__GLXextFuncPtr func = glXGetProcAddress((const GLubyte *) name);
|
||||
__GLXextFuncPtr func, func2;
|
||||
func = glXGetProcAddress((const GLubyte *) name);
|
||||
if (func == NULL) {
|
||||
printf("failed to get %s!\n", name);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Call glXGetProcAddress again to make sure that we get the same address.
|
||||
func2 = glXGetProcAddress((const GLubyte *) name);
|
||||
if (func != func2) {
|
||||
printf("glXGetProcAddress returned different address for %s: %p, %p\n",
|
||||
name, func, func2);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return (void *) func;
|
||||
}
|
||||
|
||||
|
|
126
tests/testglxgetprocaddress_genentry.c
Normal file
126
tests/testglxgetprocaddress_genentry.c
Normal file
|
@ -0,0 +1,126 @@
|
|||
/*
|
||||
* 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.
|
||||
*
|
||||
* If only executable code is distributed, then the accompanying
|
||||
* documentation must state that "this software is based in part on the
|
||||
* work of the Khronos Group."
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#if defined(USE_DISPATCH_ASM)
|
||||
|
||||
#include <GL/glx.h>
|
||||
#include <GL/gl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "dummy/GLX_dummy.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
PFNGLXEXAMPLEEXTENSIONFUNCTION ptr_glXExampleExtensionFunction;
|
||||
PFNGLXEXAMPLEEXTENSIONFUNCTION ptr_glXExampleExtensionFunction2;
|
||||
__GLXextFuncPtr proc;
|
||||
Display *dpy = NULL;
|
||||
int result = 0;
|
||||
int i;
|
||||
|
||||
// Load the function pointer first, before libGLX can load the dummy vendor
|
||||
// library. That'll force libGLX to generate an entrypoint stub.
|
||||
ptr_glXExampleExtensionFunction = (PFNGLXEXAMPLEEXTENSIONFUNCTION)
|
||||
glXGetProcAddress((const GLubyte *) "glXExampleExtensionFunction");
|
||||
if (ptr_glXExampleExtensionFunction == NULL) {
|
||||
printf("Can't look up glXExampleExtensionFunction\n");
|
||||
return 1;
|
||||
}
|
||||
printf("Got glXExampleExtensionFunction at address %p\n", ptr_glXExampleExtensionFunction);
|
||||
|
||||
// Call glXGetProcAddress to generate more dummy dispatch stubs, and then a
|
||||
// second extension function. This tests that the generated dispatch stubs
|
||||
// can correctly handle a large index.
|
||||
for (i=0; i<4094; i++) {
|
||||
char buf[50];
|
||||
|
||||
snprintf(buf, sizeof(buf), "glXUndefined%dDUMMY", i);
|
||||
proc = glXGetProcAddress((const GLubyte *) buf);
|
||||
if (proc == NULL) {
|
||||
printf("Failed to generate stub for dummy function %d %s\n", i, buf);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
ptr_glXExampleExtensionFunction2 = (PFNGLXEXAMPLEEXTENSIONFUNCTION)
|
||||
glXGetProcAddress((const GLubyte *) "glXExampleExtensionFunction2");
|
||||
if (ptr_glXExampleExtensionFunction2 == NULL) {
|
||||
printf("Can't look up glXExampleExtensionFunction\n");
|
||||
return 1;
|
||||
}
|
||||
printf("Got glXExampleExtensionFunction2 at address %p\n", ptr_glXExampleExtensionFunction2);
|
||||
|
||||
// Make one more call to glXGetProcAddress. This should return NULL.
|
||||
proc = glXGetProcAddress((const GLubyte *) "glXLastUndefinedDummy");
|
||||
if (proc != NULL) {
|
||||
printf("Last glXGetProcAddress returned non-NULL: %p\n", proc);
|
||||
return 1;
|
||||
}
|
||||
|
||||
dpy = XOpenDisplay(NULL);
|
||||
if (dpy == NULL) {
|
||||
printf("Can't open display\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Call glXGetClientString to force libGLX to load the vendor library.
|
||||
glXGetClientString(dpy, GLX_EXTENSIONS);
|
||||
|
||||
ptr_glXExampleExtensionFunction(dpy, 0, &result);
|
||||
if (result != 1) {
|
||||
printf("Unexpected glXExampleExtensionFunction() return value: %d\n", result);
|
||||
XCloseDisplay(dpy);
|
||||
return 1;
|
||||
}
|
||||
|
||||
ptr_glXExampleExtensionFunction2(dpy, 0, &result);
|
||||
if (result != 2) {
|
||||
printf("Unexpected glXExampleExtensionFunction2() return value: %d\n", result);
|
||||
XCloseDisplay(dpy);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("%p - %p = %d\n", ptr_glXExampleExtensionFunction2,
|
||||
ptr_glXExampleExtensionFunction,
|
||||
(int) (((intptr_t) ptr_glXExampleExtensionFunction2) - ((intptr_t) ptr_glXExampleExtensionFunction)));
|
||||
|
||||
XCloseDisplay(dpy);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else // defined(USE_DISPATCH_ASM)
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
// If libGLX can't generate new dispatch stubs, then just skip this test.
|
||||
return 77;
|
||||
}
|
||||
|
||||
#endif // defined(USE_DISPATCH_ASM)
|
|
@ -2,11 +2,4 @@
|
|||
|
||||
. $TOP_SRCDIR/tests/glxenv.sh
|
||||
|
||||
# Set __GLX_FORCE_VENDOR_LIBRARY_0 instead of __GLX_VENDOR_LIBRARY_NAME. That
|
||||
# way, it won't pre-load the vendor library, which would force it to generate
|
||||
# a dispatch stub for glXExampleExtensionFunction.
|
||||
__GLX_FORCE_VENDOR_LIBRARY_0=$__GLX_VENDOR_LIBRARY_NAME
|
||||
export __GLX_FORCE_VENDOR_LIBRARY_0
|
||||
unset __GLX_VENDOR_LIBRARY_NAME
|
||||
|
||||
./testglxgetprocaddress
|
||||
./testglxgetprocaddress_genentry
|
||||
|
|
|
@ -49,7 +49,6 @@
|
|||
typedef struct TestOptionsRec {
|
||||
int iterations;
|
||||
int threads;
|
||||
GLboolean late;
|
||||
} TestOptions;
|
||||
|
||||
static void print_help(void)
|
||||
|
@ -58,8 +57,7 @@ static void print_help(void)
|
|||
"Options: \n"
|
||||
" -h, --help Print this help message.\n"
|
||||
" -i<N>, --iterations=<N> Run N make current iterations in each thread \n"
|
||||
" -t<N>, --threads=<N> Run with N threads.\n"
|
||||
" -l, --late Call GetProcAddress() after MakeCurrent()\n";
|
||||
" -t<N>, --threads=<N> Run with N threads.\n";
|
||||
printf("%s", help_string);
|
||||
}
|
||||
|
||||
|
@ -71,17 +69,15 @@ void init_options(int argc, char **argv, TestOptions *t)
|
|||
{ "help", no_argument, NULL, 'h'},
|
||||
{ "iterations", required_argument, NULL, 'i'},
|
||||
{ "threads", required_argument, NULL, 't'},
|
||||
{ "late", no_argument, NULL, 'l' },
|
||||
{ NULL, no_argument, NULL, 0 }
|
||||
};
|
||||
|
||||
// Initialize defaults
|
||||
t->iterations = 1;
|
||||
t->threads = 1;
|
||||
t->late = GL_FALSE;
|
||||
|
||||
do {
|
||||
c = getopt_long(argc, argv, "hi:t:l", long_options, NULL);
|
||||
c = getopt_long(argc, argv, "hi:t:", long_options, NULL);
|
||||
switch (c) {
|
||||
case -1:
|
||||
default:
|
||||
|
@ -106,36 +102,15 @@ void init_options(int argc, char **argv, TestOptions *t)
|
|||
exit(1);
|
||||
}
|
||||
break;
|
||||
case 'l':
|
||||
t->late = GL_TRUE;
|
||||
break;
|
||||
}
|
||||
} while (c != -1);
|
||||
|
||||
}
|
||||
|
||||
static PFNGLMAKECURRENTTESTRESULTSPROC GetMakeCurrentTestResults(void)
|
||||
{
|
||||
int i;
|
||||
PFNGLMAKECURRENTTESTRESULTSPROC proc = NULL, old_proc = NULL;
|
||||
// Call this multiple times to verify address caching works correctly.
|
||||
for (i = 0; i < 3; i++) {
|
||||
proc = (PFNGLMAKECURRENTTESTRESULTSPROC)
|
||||
glXGetProcAddress((GLubyte *)"glMakeCurrentTestResults");
|
||||
if ((i != 0) && (proc != old_proc))
|
||||
{
|
||||
printError("Got different addresses for glMakeCurrentTestResults: %p, %p\n", proc, old_proc);
|
||||
return NULL;
|
||||
}
|
||||
old_proc = proc;
|
||||
}
|
||||
return proc;
|
||||
}
|
||||
|
||||
void *MakeCurrentThread(void *arg)
|
||||
{
|
||||
struct window_info wi;
|
||||
PFNGLMAKECURRENTTESTRESULTSPROC pMakeCurrentTestResults = NULL;
|
||||
PFNGLXMAKECURRENTTESTRESULTSPROC pMakeCurrentTestResults = NULL;
|
||||
GLXContext ctx = NULL;
|
||||
const GLfloat v[] = { 0, 0, 0 };
|
||||
struct {
|
||||
|
@ -162,15 +137,16 @@ void *MakeCurrentThread(void *arg)
|
|||
goto fail;
|
||||
}
|
||||
|
||||
// Make sure that libGLX has loaded the vendor library.
|
||||
glXGetClientString(dpy, GLX_EXTENSIONS);
|
||||
|
||||
// Test the robustness of GetProcAddress() by calling this separately for
|
||||
// each thread.
|
||||
if (!t->late) {
|
||||
pMakeCurrentTestResults = GetMakeCurrentTestResults();
|
||||
|
||||
if (!pMakeCurrentTestResults) {
|
||||
printError("Failed to get glMakeCurrentTestResults() function!\n");
|
||||
goto fail;
|
||||
}
|
||||
pMakeCurrentTestResults = (PFNGLXMAKECURRENTTESTRESULTSPROC)
|
||||
glXGetProcAddress((const GLubyte *) "glXMakeCurrentTestResults");
|
||||
if (pMakeCurrentTestResults == NULL) {
|
||||
printError("Failed to get glXMakeCurrentTestResults() function!\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
success = testUtilsCreateWindow(dpy, &wi, 0);
|
||||
|
@ -192,22 +168,13 @@ void *MakeCurrentThread(void *arg)
|
|||
goto fail;
|
||||
}
|
||||
|
||||
if (t->late) {
|
||||
pMakeCurrentTestResults = GetMakeCurrentTestResults();
|
||||
|
||||
if (!pMakeCurrentTestResults) {
|
||||
printError("Failed to get glMakeCurrentTestResults() function!\n");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
glBegin(GL_TRIANGLES); BeginCount++;
|
||||
glVertex3fv(v); Vertex3fvCount++;
|
||||
glVertex3fv(v); Vertex3fvCount++;
|
||||
glVertex3fv(v); Vertex3fvCount++;
|
||||
glEnd(); EndCount++;
|
||||
|
||||
// Make a call to glMakeCurrentTestResults() to get the function counts.
|
||||
// Make a call to glXMakeCurrentTestResults() to get the function counts.
|
||||
makeCurrentTestResultsParams.req = GL_MC_FUNCTION_COUNTS;
|
||||
makeCurrentTestResultsParams.saw = GL_FALSE;
|
||||
makeCurrentTestResultsParams.ret = NULL;
|
||||
|
@ -217,12 +184,12 @@ void *MakeCurrentThread(void *arg)
|
|||
&makeCurrentTestResultsParams.ret);
|
||||
|
||||
if (!makeCurrentTestResultsParams.saw) {
|
||||
printError("Failed to dispatch glMakeCurrentTestResults()!\n");
|
||||
printError("Failed to dispatch glXMakeCurrentTestResults()!\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!makeCurrentTestResultsParams.ret) {
|
||||
printError("Internal glMakeCurrentTestResults() error!\n");
|
||||
printError("Internal glXMakeCurrentTestResults() error!\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
@ -248,7 +215,7 @@ void *MakeCurrentThread(void *arg)
|
|||
glVertex3fv(NULL);
|
||||
glEnd();
|
||||
|
||||
// Similarly the call to the dynamic function glMakeCurrentTestResults()
|
||||
// Similarly the call to the dynamic function glXMakeCurrentTestResults()
|
||||
// should be a no-op.
|
||||
makeCurrentTestResultsParams.req = GL_MC_FUNCTION_COUNTS;
|
||||
makeCurrentTestResultsParams.saw = GL_FALSE;
|
||||
|
@ -259,7 +226,7 @@ void *MakeCurrentThread(void *arg)
|
|||
&makeCurrentTestResultsParams.ret);
|
||||
|
||||
if (makeCurrentTestResultsParams.saw) {
|
||||
printError("Dynamic function glMakeCurrentTestResults() dispatched "
|
||||
printError("Dynamic function glXMakeCurrentTestResults() dispatched "
|
||||
"to vendor library even though no context was current!\n");
|
||||
goto fail;
|
||||
}
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
. $TOP_SRCDIR/tests/glxenv.sh
|
||||
|
||||
# Run the make current test exactly once, but with GetProcAddress() called
|
||||
# after MakeCurrent().
|
||||
./testglxmakecurrent -t 1 -i 1 -l
|
|
@ -1,87 +0,0 @@
|
|||
#define _GNU_SOURCE 1
|
||||
|
||||
#include <string.h>
|
||||
#include <X11/X.h>
|
||||
#include <GL/gl.h>
|
||||
#include <dlfcn.h>
|
||||
#include "test_utils.h"
|
||||
|
||||
#define NUM_VERTEX3FV_CALLS 100
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
struct window_info wi;
|
||||
Display *dpy = XOpenDisplay(NULL);
|
||||
int sawVertex3fv1, *pSawVertex3fv;
|
||||
int i;
|
||||
int ret = 1;
|
||||
GLXContext ctx = None;
|
||||
void *vendorHandle;
|
||||
|
||||
if (!dpy) {
|
||||
printError("No display!\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
memset(&wi, 0, sizeof(wi));
|
||||
|
||||
if (!testUtilsCreateWindow(dpy, &wi, 0)) {
|
||||
printError("Failed to create window!\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ctx = glXCreateContext(dpy, wi.visinfo, NULL, GL_TRUE);
|
||||
if (!ctx) {
|
||||
printError("Failed to create a context!\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!glXMakeContextCurrent(dpy, wi.win, wi.win, ctx)) {
|
||||
printError("Failed to make current\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
vendorHandle = dlopen("libGLX_dummy.so", RTLD_LAZY);
|
||||
if (!vendorHandle) {
|
||||
printError("No valid vendor library handle\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
pSawVertex3fv = (int *)dlsym(vendorHandle, "__glXSawVertex3fv");
|
||||
if (!pSawVertex3fv) {
|
||||
printError("Could not find __glXSawVertex3fv\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
for (i = 0; i < NUM_VERTEX3FV_CALLS; i++) {
|
||||
glVertex3fv(NULL);
|
||||
}
|
||||
|
||||
// Read the resulting value
|
||||
sawVertex3fv1 = *pSawVertex3fv;
|
||||
|
||||
if (!glXMakeContextCurrent(dpy, None, None, NULL)) {
|
||||
printError("Could not lose current\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
dlclose(vendorHandle);
|
||||
pSawVertex3fv = NULL;
|
||||
|
||||
if (sawVertex3fv1 != NUM_VERTEX3FV_CALLS) {
|
||||
printError("sawVertex3fv1 mismatch: expected %d, got %d\n",
|
||||
NUM_VERTEX3FV_CALLS, sawVertex3fv1);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
fail:
|
||||
if (ctx) {
|
||||
glXDestroyContext(dpy, ctx);
|
||||
}
|
||||
|
||||
testUtilsDestroyWindow(dpy, &wi);
|
||||
|
||||
return ret;
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
. $TOP_SRCDIR/tests/glxenv.sh
|
||||
export GLVND_TEST_PATCH_ENTRYPOINTS=1
|
||||
|
||||
# Run the patch entrypoint test.
|
||||
./testpatchentrypoints
|
Loading…
Reference in a new issue