mesa/tests: Sanity check the ES2 dispatch table
authorIan Romanick <ian.d.romanick@intel.com>
Thu, 2 Aug 2012 05:19:01 +0000 (22:19 -0700)
committerIan Romanick <ian.d.romanick@intel.com>
Fri, 28 Sep 2012 15:19:54 +0000 (08:19 -0700)
This test is only built when shared-glapi is used.  Because of changes
elsewhere in the tree that were necessary to make shared-glapi work
correct with GLX, it's not feasible to make the test function both ways.

The list of expected functions originally came from the functions set by
api_exec_es2.c.  This file no longer exists in Mesa (but api_exec_es1.c
is still generated).  It was the generated file that configured the
dispatch table for ES2 contexts.  This test verifies that all of the
functions set by the old api_exec_es2.c (with the recent addition of VAO
functions) are set in the dispatch table and everything else is a NOP.

When adding ES2 (or ES3) extensions that add new functions, this test
will need to be modified to expect dispatch functions for the new
extension functions.

v2: Expect VAO functions be non-NOP.

Signed-off-by: Ian Romanick <ian.d.romanick@intel.com>
src/mesa/main/api_exec.c
src/mesa/main/tests/Makefile.am
src/mesa/main/tests/dispatch_sanity.cpp [new file with mode: 0644]

index 69179abb1e7325f563ec769d658ef79a79995351..ddf7c7fc119192a8b9c10a69ba8b7d03468d9445 100644 (file)
@@ -874,7 +874,7 @@ _mesa_create_exec_table(struct gl_context *ctx)
       SET_TexStorage1D(exec, _mesa_TexStorage1D);
       SET_TextureStorage1DEXT(exec, _mesa_TextureStorage1DEXT);
    }
-   if (_mesa_desktop_gl(ctx) || _mesa_is_gles3(ctx)) {
+   if (_mesa_is_desktop_gl(ctx) || _mesa_is_gles3(ctx)) {
       SET_TexStorage2D(exec, _mesa_TexStorage2D);
       SET_TexStorage3D(exec, _mesa_TexStorage3D);
       SET_TextureStorage2DEXT(exec, _mesa_TextureStorage2DEXT);
index 3d1a5d8923f16c28ce3b07ddfdd2d2663b6614a9..cac04bcd6ec7a9665940c22175c8f5419038049d 100644 (file)
@@ -19,6 +19,9 @@ main_test_LDADD = \
 if HAVE_SHARED_GLAPI
 AM_CPPFLAGS += -DHAVE_SHARED_GLAPI
 
+main_test_SOURCES +=                   \
+       dispatch_sanity.cpp
+
 main_test_LDADD += \
        $(top_builddir)/src/mapi/shared-glapi/libglapi.la
 else
diff --git a/src/mesa/main/tests/dispatch_sanity.cpp b/src/mesa/main/tests/dispatch_sanity.cpp
new file mode 100644 (file)
index 0000000..b5d7128
--- /dev/null
@@ -0,0 +1,309 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS 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 SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \name dispatch_sanity.cpp
+ *
+ * Verify that only set of functions that should be available in a particular
+ * API are available in that API.
+ *
+ * The list of expected functions originally came from the functions set by
+ * api_exec_es2.c.  This file no longer exists in Mesa (but api_exec_es1.c was
+ * still generated at the time this test was written).  It was the generated
+ * file that configured the dispatch table for ES2 contexts.  This test
+ * verifies that all of the functions set by the old api_exec_es2.c (with the
+ * recent addition of VAO functions) are set in the dispatch table and
+ * everything else is a NOP.
+ *
+ * When adding extensions that add new functions, this test will need to be
+ * modified to expect dispatch functions for the new extension functions.
+ */
+
+extern "C" {
+#include "main/mfeatures.h"
+}
+
+#if FEATURE_ES2
+
+#include <gtest/gtest.h>
+
+extern "C" {
+#include "GL/gl.h"
+#include "GL/glext.h"
+#include "main/compiler.h"
+#include "main/api_exec.h"
+#include "main/context.h"
+#include "main/remap.h"
+#include "glapi/glapi.h"
+#include "drivers/common/driverfuncs.h"
+
+#include "swrast/swrast.h"
+#include "vbo/vbo.h"
+#include "tnl/tnl.h"
+#include "swrast_setup/swrast_setup.h"
+
+#ifndef GLAPIENTRYP
+#define GLAPIENTRYP GL_APIENTRYP
+#endif
+
+#include "main/dispatch.h"
+}
+
+struct function {
+   const char *name;
+   int offset;
+};
+
+extern const struct function gles2_functions_possible[];
+
+class DispatchSanity_test : public ::testing::Test {
+public:
+   virtual void SetUp();
+
+   struct gl_config visual;
+   struct dd_function_table driver_functions;
+   struct gl_context share_list;
+   struct gl_context ctx;
+};
+
+void
+DispatchSanity_test::SetUp()
+{
+   memset(&visual, 0, sizeof(visual));
+   memset(&driver_functions, 0, sizeof(driver_functions));
+   memset(&share_list, 0, sizeof(share_list));
+   memset(&ctx, 0, sizeof(ctx));
+
+   _mesa_init_driver_functions(&driver_functions);
+}
+
+static void
+validate_functions(_glapi_proc *table, const struct function *function_table)
+{
+   for (unsigned i = 0; function_table[i].name != NULL; i++) {
+      const int offset = (function_table[i].offset != -1)
+         ? function_table[i].offset
+         : _glapi_get_proc_offset(function_table[i].name);
+
+      ASSERT_NE(-1, offset)
+         << "Function: " << function_table[i].name;
+      ASSERT_EQ(offset,
+                _glapi_get_proc_offset(function_table[i].name))
+         << "Function: " << function_table[i].name;
+      EXPECT_NE((_glapi_proc) _mesa_generic_nop, table[offset])
+         << "Function: " << function_table[i].name
+         << " at offset " << offset;
+
+      table[offset] = (_glapi_proc) _mesa_generic_nop;
+   }
+
+   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;
+   }
+}
+
+TEST_F(DispatchSanity_test, GLES2)
+{
+   ctx.Version = 20;
+   _mesa_initialize_context(&ctx,
+                            API_OPENGLES2, //api,
+                            &visual,
+                            NULL, //&share_list,
+                            &driver_functions,
+                            (void *) NULL);
+
+   _swrast_CreateContext(&ctx);
+   _vbo_CreateContext(&ctx);
+   _tnl_CreateContext(&ctx);
+   _swsetup_CreateContext(&ctx);
+
+   validate_functions((_glapi_proc *) ctx.Exec, gles2_functions_possible);
+}
+
+const struct function gles2_functions_possible[] = {
+   { "glActiveTexture", _gloffset_ActiveTextureARB },
+   { "glAttachShader", -1 },
+   { "glBindAttribLocation", -1 },
+   { "glBindBuffer", -1 },
+   { "glBindFramebuffer", -1 },
+   { "glBindRenderbuffer", -1 },
+   { "glBindTexture", _gloffset_BindTexture },
+   { "glBindVertexArrayOES", -1 },
+   { "glBlendColor", _gloffset_BlendColor },
+   { "glBlendEquation", _gloffset_BlendEquation },
+   { "glBlendEquationSeparate", -1 },
+   { "glBlendFunc", _gloffset_BlendFunc },
+   { "glBlendFuncSeparate", -1 },
+   { "glBufferData", -1 },
+   { "glBufferSubData", -1 },
+   { "glCheckFramebufferStatus", -1 },
+   { "glClear", _gloffset_Clear },
+   { "glClearColor", _gloffset_ClearColor },
+   { "glClearDepthf", -1 },
+   { "glClearStencil", _gloffset_ClearStencil },
+   { "glColorMask", _gloffset_ColorMask },
+   { "glCompileShader", -1 },
+   { "glCompressedTexImage2D", -1 },
+   { "glCompressedTexImage3DOES", -1 },
+   { "glCompressedTexSubImage2D", -1 },
+   { "glCompressedTexSubImage3DOES", -1 },
+   { "glCopyTexImage2D", _gloffset_CopyTexImage2D },
+   { "glCopyTexSubImage2D", _gloffset_CopyTexSubImage2D },
+   { "glCopyTexSubImage3DOES", _gloffset_CopyTexSubImage3D },
+   { "glCreateProgram", -1 },
+   { "glCreateShader", -1 },
+   { "glCullFace", _gloffset_CullFace },
+   { "glDeleteBuffers", -1 },
+   { "glDeleteFramebuffers", -1 },
+   { "glDeleteProgram", -1 },
+   { "glDeleteRenderbuffers", -1 },
+   { "glDeleteShader", -1 },
+   { "glDeleteTextures", _gloffset_DeleteTextures },
+   { "glDeleteVertexArraysOES", -1 },
+   { "glDepthFunc", _gloffset_DepthFunc },
+   { "glDepthMask", _gloffset_DepthMask },
+   { "glDepthRangef", -1 },
+   { "glDetachShader", -1 },
+   { "glDisable", _gloffset_Disable },
+   { "glDisableVertexAttribArray", -1 },
+   { "glDrawArrays", _gloffset_DrawArrays },
+   { "glDrawBuffersNV", -1 },
+   { "glDrawElements", _gloffset_DrawElements },
+   { "glEGLImageTargetRenderbufferStorageOES", -1 },
+   { "glEGLImageTargetTexture2DOES", -1 },
+   { "glEnable", _gloffset_Enable },
+   { "glEnableVertexAttribArray", -1 },
+   { "glFinish", _gloffset_Finish },
+   { "glFlush", _gloffset_Flush },
+   { "glFramebufferRenderbuffer", -1 },
+   { "glFramebufferTexture2D", -1 },
+   { "glFramebufferTexture3DOES", -1 },
+   { "glFrontFace", _gloffset_FrontFace },
+   { "glGenBuffers", -1 },
+   { "glGenFramebuffers", -1 },
+   { "glGenRenderbuffers", -1 },
+   { "glGenTextures", _gloffset_GenTextures },
+   { "glGenVertexArraysOES", -1 },
+   { "glGenerateMipmap", -1 },
+   { "glGetActiveAttrib", -1 },
+   { "glGetActiveUniform", -1 },
+   { "glGetAttachedShaders", -1 },
+   { "glGetAttribLocation", -1 },
+   { "glGetBooleanv", _gloffset_GetBooleanv },
+   { "glGetBufferParameteriv", -1 },
+   { "glGetBufferPointervOES", -1 },
+   { "glGetError", _gloffset_GetError },
+   { "glGetFloatv", _gloffset_GetFloatv },
+   { "glGetFramebufferAttachmentParameteriv", -1 },
+   { "glGetIntegerv", _gloffset_GetIntegerv },
+   { "glGetProgramInfoLog", -1 },
+   { "glGetProgramiv", -1 },
+   { "glGetRenderbufferParameteriv", -1 },
+   { "glGetShaderInfoLog", -1 },
+   { "glGetShaderPrecisionFormat", -1 },
+   { "glGetShaderSource", -1 },
+   { "glGetShaderiv", -1 },
+   { "glGetString", _gloffset_GetString },
+   { "glGetTexParameterfv", _gloffset_GetTexParameterfv },
+   { "glGetTexParameteriv", _gloffset_GetTexParameteriv },
+   { "glGetUniformLocation", -1 },
+   { "glGetUniformfv", -1 },
+   { "glGetUniformiv", -1 },
+   { "glGetVertexAttribPointerv", -1 },
+   { "glGetVertexAttribfv", -1 },
+   { "glGetVertexAttribiv", -1 },
+   { "glHint", _gloffset_Hint },
+   { "glIsBuffer", -1 },
+   { "glIsEnabled", _gloffset_IsEnabled },
+   { "glIsFramebuffer", -1 },
+   { "glIsProgram", -1 },
+   { "glIsRenderbuffer", -1 },
+   { "glIsShader", -1 },
+   { "glIsTexture", _gloffset_IsTexture },
+   { "glIsVertexArrayOES", -1 },
+   { "glLineWidth", _gloffset_LineWidth },
+   { "glLinkProgram", -1 },
+   { "glMapBufferOES", -1 },
+   { "glMultiDrawArraysEXT", -1 },
+   { "glMultiDrawElementsEXT", -1 },
+   { "glPixelStorei", _gloffset_PixelStorei },
+   { "glPolygonOffset", _gloffset_PolygonOffset },
+   { "glReadBufferNV", _gloffset_ReadBuffer },
+   { "glReadPixels", _gloffset_ReadPixels },
+   { "glReleaseShaderCompiler", -1 },
+   { "glRenderbufferStorage", -1 },
+   { "glSampleCoverage", -1 },
+   { "glScissor", _gloffset_Scissor },
+   { "glShaderBinary", -1 },
+   { "glShaderSource", -1 },
+   { "glStencilFunc", _gloffset_StencilFunc },
+   { "glStencilFuncSeparate", -1 },
+   { "glStencilMask", _gloffset_StencilMask },
+   { "glStencilMaskSeparate", -1 },
+   { "glStencilOp", _gloffset_StencilOp },
+   { "glStencilOpSeparate", -1 },
+   { "glTexImage2D", _gloffset_TexImage2D },
+   { "glTexImage3DOES", _gloffset_TexImage3D },
+   { "glTexParameterf", _gloffset_TexParameterf },
+   { "glTexParameterfv", _gloffset_TexParameterfv },
+   { "glTexParameteri", _gloffset_TexParameteri },
+   { "glTexParameteriv", _gloffset_TexParameteriv },
+   { "glTexSubImage2D", _gloffset_TexSubImage2D },
+   { "glTexSubImage3DOES", _gloffset_TexSubImage3D },
+   { "glUniform1f", -1 },
+   { "glUniform1fv", -1 },
+   { "glUniform1i", -1 },
+   { "glUniform1iv", -1 },
+   { "glUniform2f", -1 },
+   { "glUniform2fv", -1 },
+   { "glUniform2i", -1 },
+   { "glUniform2iv", -1 },
+   { "glUniform3f", -1 },
+   { "glUniform3fv", -1 },
+   { "glUniform3i", -1 },
+   { "glUniform3iv", -1 },
+   { "glUniform4f", -1 },
+   { "glUniform4fv", -1 },
+   { "glUniform4i", -1 },
+   { "glUniform4iv", -1 },
+   { "glUniformMatrix2fv", -1 },
+   { "glUniformMatrix3fv", -1 },
+   { "glUniformMatrix4fv", -1 },
+   { "glUnmapBufferOES", -1 },
+   { "glUseProgram", -1 },
+   { "glValidateProgram", -1 },
+   { "glVertexAttrib1f", -1 },
+   { "glVertexAttrib1fv", -1 },
+   { "glVertexAttrib2f", -1 },
+   { "glVertexAttrib2fv", -1 },
+   { "glVertexAttrib3f", -1 },
+   { "glVertexAttrib3fv", -1 },
+   { "glVertexAttrib4f", -1 },
+   { "glVertexAttrib4fv", -1 },
+   { "glVertexAttribPointer", -1 },
+   { "glViewport", _gloffset_Viewport },
+   { NULL, -1 }
+};
+
+#endif /* FEATURE_ES2 */