mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-23 15:30:14 +01:00
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 <jfonseca@vmware.com>
This commit is contained in:
parent
201e36e77d
commit
4bdbb588a9
3 changed files with 37 additions and 67 deletions
|
|
@ -882,18 +882,35 @@ update_default_objects(struct gl_context *ctx)
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the default function we plug into all dispatch table slots
|
* This function is called by the glapi no-op functions. For each OpenGL
|
||||||
* This helps prevents a segfault when someone calls a GL function without
|
* function/entrypoint there's a simple no-op function. These "no-op"
|
||||||
* first checking if the extension's supported.
|
* 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
|
static void
|
||||||
_mesa_generic_nop(void)
|
nop_handler(const char *name)
|
||||||
{
|
{
|
||||||
GET_CURRENT_CONTEXT(ctx);
|
GET_CURRENT_CONTEXT(ctx);
|
||||||
_mesa_error(ctx, GL_INVALID_OPERATION,
|
if (ctx) {
|
||||||
"unsupported function called "
|
_mesa_error(ctx, GL_INVALID_OPERATION, "gl%s(invalid call)", name);
|
||||||
"(unsupported extension or deprecated function?)");
|
}
|
||||||
return 0;
|
#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
|
#endif
|
||||||
|
|
||||||
|
|
||||||
extern void (*__glapi_noop_table[])(void);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allocate and initialize a new dispatch table. All the dispatch
|
* Allocate and initialize a new dispatch table. The table will be
|
||||||
* function pointers will point at the _mesa_generic_nop() function
|
* populated with pointers to "no-op" functions. In turn, the no-op
|
||||||
* which raises GL_INVALID_OPERATION.
|
* functions will call nop_handler() above.
|
||||||
*/
|
*/
|
||||||
struct _glapi_table *
|
struct _glapi_table *
|
||||||
_mesa_alloc_dispatch_table(void)
|
_mesa_alloc_dispatch_table(void)
|
||||||
|
|
@ -926,23 +940,10 @@ _mesa_alloc_dispatch_table(void)
|
||||||
* DRI drivers.
|
* DRI drivers.
|
||||||
*/
|
*/
|
||||||
GLint numEntries = MAX2(_glapi_get_dispatch_table_size(), _gloffset_COUNT);
|
GLint numEntries = MAX2(_glapi_get_dispatch_table_size(), _gloffset_COUNT);
|
||||||
struct _glapi_table *table;
|
struct _glapi_table *table = _glapi_new_nop_table(numEntries);
|
||||||
|
|
||||||
table = malloc(numEntries * sizeof(_glapi_proc));
|
#if defined(_WIN32)
|
||||||
if (table) {
|
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
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(_WIN32)
|
|
||||||
/* This is a special case for Windows in the event that
|
/* This is a special case for Windows in the event that
|
||||||
* wglGetProcAddress is called between glBegin/End().
|
* wglGetProcAddress is called between glBegin/End().
|
||||||
*
|
*
|
||||||
|
|
@ -960,8 +961,11 @@ _mesa_alloc_dispatch_table(void)
|
||||||
* assertion passes and the test continues.
|
* assertion passes and the test continues.
|
||||||
*/
|
*/
|
||||||
SET_Flush(table, nop_glFlush);
|
SET_Flush(table, nop_glFlush);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
_glapi_set_nop_handler(nop_handler);
|
||||||
|
|
||||||
return table;
|
return table;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -175,9 +175,6 @@ _mesa_finish(struct gl_context *ctx);
|
||||||
extern void
|
extern void
|
||||||
_mesa_flush(struct gl_context *ctx);
|
_mesa_flush(struct gl_context *ctx);
|
||||||
|
|
||||||
extern int
|
|
||||||
_mesa_generic_nop(void);
|
|
||||||
|
|
||||||
extern void GLAPIENTRY
|
extern void GLAPIENTRY
|
||||||
_mesa_Finish( void );
|
_mesa_Finish( void );
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -119,20 +119,14 @@ offset_to_proc_name_safe(unsigned offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Scan through the dispatch table and check that all the functions in
|
/* Scan through the dispatch table and check that all the functions in
|
||||||
* _glapi_proc *table exist. When found, set their pointers in the table
|
* _glapi_proc *table exist.
|
||||||
* to _mesa_generic_nop. */
|
*/
|
||||||
static void
|
static void
|
||||||
validate_functions(struct gl_context *ctx, const struct function *function_table)
|
validate_functions(struct gl_context *ctx, const struct function *function_table)
|
||||||
{
|
{
|
||||||
_glapi_proc *table = (_glapi_proc *) ctx->Exec;
|
_glapi_proc *table = (_glapi_proc *) ctx->Exec;
|
||||||
|
|
||||||
for (unsigned i = 0; function_table[i].name != NULL; i++) {
|
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)
|
const int offset = (function_table[i].offset != -1)
|
||||||
? function_table[i].offset
|
? function_table[i].offset
|
||||||
: _glapi_get_proc_offset(function_table[i].name);
|
: _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,
|
ASSERT_EQ(offset,
|
||||||
_glapi_get_proc_offset(function_table[i].name))
|
_glapi_get_proc_offset(function_table[i].name))
|
||||||
<< "Function: " << 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);
|
SetUpCtx(API_OPENGL_CORE, 31);
|
||||||
validate_functions(&ctx, gl_core_functions_possible);
|
validate_functions(&ctx, gl_core_functions_possible);
|
||||||
validate_nops(&ctx);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(DispatchSanity_test, GLES11)
|
TEST_F(DispatchSanity_test, GLES11)
|
||||||
{
|
{
|
||||||
SetUpCtx(API_OPENGLES, 11);
|
SetUpCtx(API_OPENGLES, 11);
|
||||||
validate_functions(&ctx, gles11_functions_possible);
|
validate_functions(&ctx, gles11_functions_possible);
|
||||||
validate_nops(&ctx);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(DispatchSanity_test, GLES2)
|
TEST_F(DispatchSanity_test, GLES2)
|
||||||
{
|
{
|
||||||
SetUpCtx(API_OPENGLES2, 20);
|
SetUpCtx(API_OPENGLES2, 20);
|
||||||
validate_functions(&ctx, gles2_functions_possible);
|
validate_functions(&ctx, gles2_functions_possible);
|
||||||
validate_nops(&ctx);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(DispatchSanity_test, GLES3)
|
TEST_F(DispatchSanity_test, GLES3)
|
||||||
|
|
@ -192,7 +162,6 @@ TEST_F(DispatchSanity_test, GLES3)
|
||||||
SetUpCtx(API_OPENGLES2, 30);
|
SetUpCtx(API_OPENGLES2, 30);
|
||||||
validate_functions(&ctx, gles2_functions_possible);
|
validate_functions(&ctx, gles2_functions_possible);
|
||||||
validate_functions(&ctx, gles3_functions_possible);
|
validate_functions(&ctx, gles3_functions_possible);
|
||||||
validate_nops(&ctx);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct function gl_core_functions_possible[] = {
|
const struct function gl_core_functions_possible[] = {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue