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