From 4bdbb588a9d385509f9168e38bfdb76952ba469c Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Fri, 13 Mar 2015 11:43:44 -0600 Subject: [PATCH] mesa: reimplement dispatch table no-op function handling Use the new _glapi_new_nop_table() and _glapi_set_nop_handler() to improve how we handle calling no-op GL functions. If there's a current context for the calling thread, generate a GL_INVALID_OPERATION error. This will happen if the app calls an unimplemented extension function or it calls an illegal function between glBegin/glEnd. If there's no current context, print an error to stdout if it's a debug build. The dispatch_sanity.cpp file has some previous checks removed since the _mesa_generic_nop() function no longer exists. This fixes the piglit gl-1.0-dlist-begin-end and gl-1.0-beginend-coverage tests on Windows. Reviewed-by: Jose Fonseca --- src/mesa/main/context.c | 66 +++++++++++++------------ src/mesa/main/context.h | 3 -- src/mesa/main/tests/dispatch_sanity.cpp | 35 +------------ 3 files changed, 37 insertions(+), 67 deletions(-) diff --git a/src/mesa/main/context.c b/src/mesa/main/context.c index 22c2341d64f..e7d1f4d352a 100644 --- a/src/mesa/main/context.c +++ b/src/mesa/main/context.c @@ -882,18 +882,35 @@ update_default_objects(struct gl_context *ctx) /** - * This is the default function we plug into all dispatch table slots - * This helps prevents a segfault when someone calls a GL function without - * first checking if the extension's supported. + * This function is called by the glapi no-op functions. For each OpenGL + * function/entrypoint there's a simple no-op function. These "no-op" + * functions call this function. + * + * If there's a current OpenGL context for the calling thread, we record a + * GL_INVALID_OPERATION error. This can happen either because the app's + * calling an unsupported extension function, or calling an illegal function + * (such as glClear between glBegin/glEnd). + * + * If there's no current OpenGL context for the calling thread, we can + * print a message to stderr. + * + * \param name the name of the OpenGL function, without the "gl" prefix */ -int -_mesa_generic_nop(void) +static void +nop_handler(const char *name) { GET_CURRENT_CONTEXT(ctx); - _mesa_error(ctx, GL_INVALID_OPERATION, - "unsupported function called " - "(unsupported extension or deprecated function?)"); - return 0; + if (ctx) { + _mesa_error(ctx, GL_INVALID_OPERATION, "gl%s(invalid call)", name); + } +#if defined(DEBUG) + else if (getenv("MESA_DEBUG") || getenv("LIBGL_DEBUG")) { + fprintf(stderr, + "GL User Error: gl%s called without a rendering context\n", + name); + fflush(stderr); + } +#endif } @@ -909,13 +926,10 @@ nop_glFlush(void) #endif -extern void (*__glapi_noop_table[])(void); - - /** - * Allocate and initialize a new dispatch table. All the dispatch - * function pointers will point at the _mesa_generic_nop() function - * which raises GL_INVALID_OPERATION. + * Allocate and initialize a new dispatch table. The table will be + * populated with pointers to "no-op" functions. In turn, the no-op + * functions will call nop_handler() above. */ struct _glapi_table * _mesa_alloc_dispatch_table(void) @@ -926,23 +940,10 @@ _mesa_alloc_dispatch_table(void) * DRI drivers. */ GLint numEntries = MAX2(_glapi_get_dispatch_table_size(), _gloffset_COUNT); - struct _glapi_table *table; - - table = malloc(numEntries * sizeof(_glapi_proc)); - if (table) { - _glapi_proc *entry = (_glapi_proc *) table; - GLint i; - for (i = 0; i < numEntries; i++) { -#if defined(_WIN32) - /* FIXME: This will not generate an error, but at least it won't - * corrupt the stack like _mesa_generic_nop does. */ - entry[i] = __glapi_noop_table[i]; -#else - entry[i] = (_glapi_proc) _mesa_generic_nop; -#endif - } + struct _glapi_table *table = _glapi_new_nop_table(numEntries); #if defined(_WIN32) + if (table) { /* This is a special case for Windows in the event that * wglGetProcAddress is called between glBegin/End(). * @@ -960,8 +961,11 @@ _mesa_alloc_dispatch_table(void) * assertion passes and the test continues. */ SET_Flush(table, nop_glFlush); -#endif } +#endif + + _glapi_set_nop_handler(nop_handler); + return table; } diff --git a/src/mesa/main/context.h b/src/mesa/main/context.h index d5650877ed0..1cd89a84af6 100644 --- a/src/mesa/main/context.h +++ b/src/mesa/main/context.h @@ -175,9 +175,6 @@ _mesa_finish(struct gl_context *ctx); extern void _mesa_flush(struct gl_context *ctx); -extern int -_mesa_generic_nop(void); - extern void GLAPIENTRY _mesa_Finish( void ); diff --git a/src/mesa/main/tests/dispatch_sanity.cpp b/src/mesa/main/tests/dispatch_sanity.cpp index 5d849d4ddb0..59ebb21443f 100644 --- a/src/mesa/main/tests/dispatch_sanity.cpp +++ b/src/mesa/main/tests/dispatch_sanity.cpp @@ -119,20 +119,14 @@ offset_to_proc_name_safe(unsigned offset) } /* Scan through the dispatch table and check that all the functions in - * _glapi_proc *table exist. When found, set their pointers in the table - * to _mesa_generic_nop. */ + * _glapi_proc *table exist. + */ static void validate_functions(struct gl_context *ctx, const struct function *function_table) { _glapi_proc *table = (_glapi_proc *) ctx->Exec; for (unsigned i = 0; function_table[i].name != NULL; i++) { - /* The context version is >= the GL version where the - function was introduced. Therefore, the function cannot - be set to the nop function. - */ - bool cant_be_nop = ctx->Version >= function_table[i].Version; - const int offset = (function_table[i].offset != -1) ? function_table[i].offset : _glapi_get_proc_offset(function_table[i].name); @@ -142,27 +136,6 @@ validate_functions(struct gl_context *ctx, const struct function *function_table ASSERT_EQ(offset, _glapi_get_proc_offset(function_table[i].name)) << "Function: " << function_table[i].name; - if (cant_be_nop) { - EXPECT_NE((_glapi_proc) _mesa_generic_nop, table[offset]) - << "Function: " << function_table[i].name - << " at offset " << offset; - } - - table[offset] = (_glapi_proc) _mesa_generic_nop; - } -} - -/* Scan through the table and ensure that there is nothing except - * _mesa_generic_nop (as set by validate_functions(). */ -static void -validate_nops(struct gl_context *ctx) -{ - _glapi_proc *table = (_glapi_proc *) ctx->Exec; - - const unsigned size = _glapi_get_dispatch_table_size(); - for (unsigned i = 0; i < size; i++) { - EXPECT_EQ((_glapi_proc) _mesa_generic_nop, table[i]) - << "i = " << i << " (" << offset_to_proc_name_safe(i) << ")"; } } @@ -170,21 +143,18 @@ TEST_F(DispatchSanity_test, GL31_CORE) { SetUpCtx(API_OPENGL_CORE, 31); validate_functions(&ctx, gl_core_functions_possible); - validate_nops(&ctx); } TEST_F(DispatchSanity_test, GLES11) { SetUpCtx(API_OPENGLES, 11); validate_functions(&ctx, gles11_functions_possible); - validate_nops(&ctx); } TEST_F(DispatchSanity_test, GLES2) { SetUpCtx(API_OPENGLES2, 20); validate_functions(&ctx, gles2_functions_possible); - validate_nops(&ctx); } TEST_F(DispatchSanity_test, GLES3) @@ -192,7 +162,6 @@ TEST_F(DispatchSanity_test, GLES3) SetUpCtx(API_OPENGLES2, 30); validate_functions(&ctx, gles2_functions_possible); validate_functions(&ctx, gles3_functions_possible); - validate_nops(&ctx); } const struct function gl_core_functions_possible[] = { -- 2.30.2