1 /*
2 * Copyright © 2013 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 */
23
24 /**
25 * @file wgl_per_context_funcptrs.c
26 *
27 * Tests that epoxy works correctly when wglGetProcAddress() returns
28 * different function pointers for different contexts.
29 *
30 * wgl allows that to be the case when the device or pixel format are
31 * different. We don't know if the underlying implementation actually
32 * *will* return different function pointers, so force the issue by
33 * overriding wglGetProcAddress() to return our function pointers with
34 * magic behavior. This way we can test epoxy's implementation
35 * regardless.
36 */
37
38 #include <stdio.h>
39 #include <assert.h>
40
41 #include "wgl_common.h"
42 #include <epoxy/gl.h>
43
44 #define CREATESHADER_CTX1_VAL 1001
45 #define CREATESHADER_CTX2_VAL 1002
46
47 static HGLRC ctx1, ctx2, current_context;
48 static bool pass = true;
49
50 #define OVERRIDE_API(type) __declspec(dllexport) type __stdcall
51
52 OVERRIDE_API (GLuint) override_glCreateShader_ctx1(GLenum target);
53 OVERRIDE_API (GLuint) override_glCreateShader_ctx2(GLenum target);
54 OVERRIDE_API (PROC) override_wglGetProcAddress(LPCSTR name);
55
56 OVERRIDE_API (GLuint)
override_glCreateShader_ctx1(GLenum target)57 override_glCreateShader_ctx1(GLenum target)
58 {
59 if (current_context != ctx1) {
60 fputs("ctx1 called while other context current\n", stderr);
61 pass = false;
62 }
63 return CREATESHADER_CTX1_VAL;
64 }
65
66 OVERRIDE_API (GLuint)
override_glCreateShader_ctx2(GLenum target)67 override_glCreateShader_ctx2(GLenum target)
68 {
69 if (current_context != ctx2) {
70 fputs("ctx2 called while other context current\n", stderr);
71 pass = false;
72 }
73 return CREATESHADER_CTX2_VAL;
74 }
75
76 OVERRIDE_API (PROC)
override_wglGetProcAddress(LPCSTR name)77 override_wglGetProcAddress(LPCSTR name)
78 {
79 assert(strcmp(name, "glCreateShader") == 0);
80
81 if (current_context == ctx1) {
82 return (PROC)override_glCreateShader_ctx1;
83 } else {
84 assert(current_context == ctx2);
85 return (PROC)override_glCreateShader_ctx2;
86 }
87 }
88
89 static void
test_createshader(HDC hdc,HGLRC ctx)90 test_createshader(HDC hdc, HGLRC ctx)
91 {
92 GLuint shader, expected;
93 int ctxnum;
94
95 wglMakeCurrent(hdc, ctx);
96 current_context = ctx;
97
98 /* Install our GPA override so we can force per-context function
99 * pointers.
100 */
101 wglGetProcAddress = override_wglGetProcAddress;
102
103 if (ctx == ctx1) {
104 expected = CREATESHADER_CTX1_VAL;
105 ctxnum = 1;
106 } else {
107 assert(ctx == ctx2);
108 expected = CREATESHADER_CTX2_VAL;
109 ctxnum = 2;
110 }
111
112 shader = glCreateShader(GL_FRAGMENT_SHADER);
113 printf("ctx%d: Returned %d\n", ctxnum, shader);
114 if (shader != expected) {
115 fprintf(stderr, " expected %d\n", expected);
116 pass = false;
117 }
118 }
119
120 static int
test_function(HDC hdc)121 test_function(HDC hdc)
122 {
123 ctx1 = wglCreateContext(hdc);
124 ctx2 = wglCreateContext(hdc);
125 if (!ctx1 || !ctx2) {
126 fputs("Failed to create wgl contexts\n", stderr);
127 return 1;
128 }
129
130 if (!wglMakeCurrent(hdc, ctx1)) {
131 fputs("Failed to make context current\n", stderr);
132 return 1;
133 }
134
135 if (epoxy_gl_version() < 20) {
136 /* We could possibly do a 1.3 entrypoint or something instead. */
137 fputs("Test relies on overriding a GL 2.0 entrypoint\n", stderr);
138 return 77;
139 }
140
141 /* Force resolving epoxy_wglGetProcAddress. */
142 wglGetProcAddress("glCreateShader");
143
144 test_createshader(hdc, ctx1);
145 test_createshader(hdc, ctx1);
146 test_createshader(hdc, ctx2);
147 test_createshader(hdc, ctx2);
148 test_createshader(hdc, ctx1);
149 test_createshader(hdc, ctx2);
150
151 wglMakeCurrent(NULL, NULL);
152 wglDeleteContext(ctx1);
153 wglDeleteContext(ctx2);
154
155 return !pass;
156 }
157
158 int
main(int argc,char ** argv)159 main(int argc, char **argv)
160 {
161 make_window_and_test(test_function);
162
163 /* UNREACHED */
164 return 1;
165 }
166