xref: /aosp_15_r20/external/libepoxy/test/wgl_per_context_funcptrs.c (revision 706d0b42ae4182339789e08d473a0b312ecdc60f)
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