summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorEric Anholt <eric@anholt.net>2014-03-28 12:06:47 -0700
committerEric Anholt <eric@anholt.net>2014-03-28 16:33:19 -0700
commitea12f935c14351a26a721fc6ffee6c67b53b0e15 (patch)
treeca2101a59d339dccc62bb4a39a2fa0a8abd87611 /test
parentb1d875ef0b4558a138e633cdcd275d11b669eb89 (diff)
downloadlibepoxy-ea12f935c14351a26a721fc6ffee6c67b53b0e15.tar.gz
wgl: Add a test for MakeCurrent returning different function pointers.
Huh, my old rule of "untested code is broken code" didn't hold up, for once.
Diffstat (limited to 'test')
-rw-r--r--test/Makefile.am3
-rw-r--r--test/wgl_per_context_funcptrs.c166
2 files changed, 169 insertions, 0 deletions
diff --git a/test/Makefile.am b/test/Makefile.am
index 25f965f..f462fbe 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -110,6 +110,7 @@ endif
if BUILD_WGL
WGL_TESTS = \
wgl_core_and_exts$(EXEEXT) \
+ wgl_per_context_funcptrs$(EXEEXT) \
wgl_usefontbitmaps$(EXEEXT) \
wgl_usefontbitmaps_unicode$(EXEEXT) \
$()
@@ -172,6 +173,8 @@ khronos_typedefs_SOURCES = \
wgl_core_and_exts_LDADD = $(EPOXY) libwgl_common.la -lgdi32
+wgl_per_context_funcptrs_LDADD = $(EPOXY) libwgl_common.la -lgdi32
+
wgl_usefontbitmaps_LDADD = $(EPOXY) libwgl_common.la -lgdi32
wgl_usefontbitmaps_unicode_SOURCES = wgl_usefontbitmaps.c
wgl_usefontbitmaps_unicode_LDADD = $(EPOXY) libwgl_common.la -lgdi32
diff --git a/test/wgl_per_context_funcptrs.c b/test/wgl_per_context_funcptrs.c
new file mode 100644
index 0000000..6ed49df
--- /dev/null
+++ b/test/wgl_per_context_funcptrs.c
@@ -0,0 +1,166 @@
+/*
+ * Copyright © 2013 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.
+ */
+
+/**
+ * @file wgl_per_context_funcptrs.c
+ *
+ * Tests that epoxy works correctly when wglGetProcAddress() returns
+ * different function pointers for different contexts.
+ *
+ * wgl allows that to be the case when the device or pixel format are
+ * different. We don't know if the underlying implementation actually
+ * *will* return different function pointers, so force the issue by
+ * overriding wglGetProcAddress() to return our function pointers with
+ * magic behavior. This way we can test epoxy's implementation
+ * regardless.
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <assert.h>
+
+#include "wgl_common.h"
+#include <epoxy/gl.h>
+
+#define CREATESHADER_CTX1_VAL 1001
+#define CREATESHADER_CTX2_VAL 1002
+
+static HGLRC ctx1, ctx2, current_context;
+static bool pass = true;
+
+#define OVERRIDE_API __declspec(dllexport) __stdcall
+
+OVERRIDE_API GLuint override_glCreateShader_ctx1(GLenum target);
+OVERRIDE_API GLuint override_glCreateShader_ctx2(GLenum target);
+OVERRIDE_API PROC override_wglGetProcAddress(LPCSTR name);
+
+OVERRIDE_API GLuint
+override_glCreateShader_ctx1(GLenum target)
+{
+ if (current_context != ctx1) {
+ fprintf(stderr, "ctx1 called while other context current\n");
+ pass = false;
+ }
+ return CREATESHADER_CTX1_VAL;
+}
+
+OVERRIDE_API GLuint
+override_glCreateShader_ctx2(GLenum target)
+{
+ if (current_context != ctx2) {
+ fprintf(stderr, "ctx2 called while other context current\n");
+ pass = false;
+ }
+ return CREATESHADER_CTX2_VAL;
+}
+
+OVERRIDE_API PROC
+override_wglGetProcAddress(LPCSTR name)
+{
+ assert(strcmp(name, "glCreateShader") == 0);
+
+ if (current_context == ctx1) {
+ return (PROC)override_glCreateShader_ctx1;
+ } else {
+ assert(current_context == ctx2);
+ return (PROC)override_glCreateShader_ctx2;
+ }
+}
+
+static void
+test_createshader(HDC hdc, HGLRC ctx)
+{
+ GLuint shader, expected;
+ int ctxnum;
+
+ wglMakeCurrent(hdc, ctx);
+ current_context = ctx;
+
+ /* Install our GPA override so we can force per-context function
+ * pointers.
+ */
+ wglGetProcAddress = override_wglGetProcAddress;
+
+ if (ctx == ctx1) {
+ expected = CREATESHADER_CTX1_VAL;
+ ctxnum = 1;
+ } else {
+ assert(ctx == ctx2);
+ expected = CREATESHADER_CTX2_VAL;
+ ctxnum = 2;
+ }
+
+ shader = glCreateShader(GL_FRAGMENT_SHADER);
+ printf("ctx%d: Returned %d\n", ctxnum, shader);
+ if (shader != expected) {
+ fprintf(stderr, " expected %d\n", expected);
+ pass = false;
+ }
+}
+
+static int
+test_function(HDC hdc)
+{
+ ctx1 = wglCreateContext(hdc);
+ ctx2 = wglCreateContext(hdc);
+ if (!ctx1 || !ctx2) {
+ fprintf(stderr, "Failed to create wgl contexts\n");
+ return 1;
+ }
+
+ if (!wglMakeCurrent(hdc, ctx1)) {
+ fprintf(stderr, "Failed to make context current\n");
+ return 1;
+ }
+
+ if (epoxy_gl_version() < 20) {
+ /* We could possibly do a 1.3 entrypoint or something instead. */
+ fprintf(stderr, "Test relies on overriding a GL 2.0 entrypoint\n");
+ return 77;
+ }
+
+ /* Force resolving epoxy_wglGetProcAddress. */
+ wglGetProcAddress("glCreateShader");
+
+ test_createshader(hdc, ctx1);
+ test_createshader(hdc, ctx1);
+ test_createshader(hdc, ctx2);
+ test_createshader(hdc, ctx2);
+ test_createshader(hdc, ctx1);
+ test_createshader(hdc, ctx2);
+
+ wglMakeCurrent(NULL, NULL);
+ wglDeleteContext(ctx1);
+ wglDeleteContext(ctx2);
+
+ return !pass;
+}
+
+int
+main(int argc, char **argv)
+{
+ make_window_and_test(test_function);
+
+ /* UNREACHED */
+ return 1;
+}