1 /* Copyright © 2013 Intel Corporation
2  *
3  * Permission is hereby granted, free of charge, to any person obtaining a
4  * copy of this software and associated documentation files (the "Software"),
5  * to deal in the Software without restriction, including without limitation
6  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
7  * and/or sell copies of the Software, and to permit persons to whom the
8  * Software is furnished to do so, subject to the following conditions:
9  *
10  * The above copyright notice and this permission notice (including the next
11  * paragraph) shall be included in all copies or substantial portions of the
12  * Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
20  * IN THE SOFTWARE.
21  */
22 #include "piglit-util-gl.h"
23 #include "piglit-glx-util.h"
24 #include "query-renderer-common.h"
25 
26 struct test_vector {
27 	const char *name_string;
28 	int attribute;
29 	int value_count;
30 };
31 
32 #define ENUM(name, count) { # name, name, count }
33 
34 static const struct test_vector all_valid_integer_enums[] = {
35         ENUM(GLX_RENDERER_VENDOR_ID_MESA, 1),
36         ENUM(GLX_RENDERER_DEVICE_ID_MESA, 1),
37         ENUM(GLX_RENDERER_VERSION_MESA, 3),
38         ENUM(GLX_RENDERER_ACCELERATED_MESA, 1),
39         ENUM(GLX_RENDERER_VIDEO_MEMORY_MESA, 1),
40         ENUM(GLX_RENDERER_UNIFIED_MEMORY_ARCHITECTURE_MESA, 1),
41         ENUM(GLX_RENDERER_PREFERRED_PROFILE_MESA, 1),
42         ENUM(GLX_RENDERER_OPENGL_CORE_PROFILE_VERSION_MESA, 2),
43         ENUM(GLX_RENDERER_OPENGL_COMPATIBILITY_PROFILE_VERSION_MESA, 2),
44         ENUM(GLX_RENDERER_OPENGL_ES_PROFILE_VERSION_MESA, 2),
45         ENUM(GLX_RENDERER_OPENGL_ES2_PROFILE_VERSION_MESA, 2),
46 };
47 
48 static const struct test_vector all_valid_string_enums[] = {
49         ENUM(GLX_RENDERER_VENDOR_ID_MESA, 0),
50         ENUM(GLX_RENDERER_DEVICE_ID_MESA, 0),
51 };
52 
53 static bool
verify_integer_values(const char * name,Bool success,const struct test_vector * test,const unsigned * buffer,unsigned buffer_size,bool silent)54 verify_integer_values(const char *name, Bool success,
55 		      const struct test_vector *test,
56 		      const unsigned *buffer, unsigned buffer_size,
57 		      bool silent)
58 {
59 	char text[512];
60 	unsigned text_size;
61 	bool pass = true;
62 	unsigned j;
63 
64 	if (!success) {
65 		fprintf(stderr, "%s(%s) failed.\n", name, test->name_string);
66 
67 		/* If the call failed, don't bother checking that the correct
68 		 * number of values were written.
69 		 */
70 		return false;
71 	}
72 
73 	if (!silent) {
74 		text_size = snprintf(text, sizeof(text), "%s(%s) values:\n    ",
75 				     name,
76 				     test->name_string);
77 		for (j = 0; j < test->value_count; j++) {
78 			text_size += snprintf(&text[text_size],
79 					      sizeof(text) - text_size,
80 					      "%d ",
81 					      buffer[j]);
82 		}
83 
84 		printf("%s\n", text);
85 	}
86 
87 	for (j = 0; j < test->value_count; j++) {
88 		if (buffer[j] == 0xDEADBEEF) {
89 			fprintf(stderr,
90 				"%s(%s) only wrote %d values, expected %d.\n",
91 				name,
92 				test->name_string,
93 				j,
94 				test->value_count);
95 			pass = false;
96 			break;
97 		}
98 	}
99 
100 	for (j = test->value_count; j < buffer_size; j++) {
101 		if (buffer[j] != 0xDEADBEEF) {
102 			fprintf(stderr,
103 				"%s(%s) wrote at least %d values, expected "
104 				"only %d.\n",
105 				name,
106 				test->name_string,
107 				j + 1,
108 				test->value_count);
109 			pass = false;
110 			break;
111 		}
112 	}
113 
114 	/* value sanity check */
115 	switch (test->attribute) {
116 	case GLX_RENDERER_PREFERRED_PROFILE_MESA: {
117 	    unsigned legal = GLX_CONTEXT_CORE_PROFILE_BIT_ARB |
118 			     GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB |
119 			     GLX_CONTEXT_ES_PROFILE_BIT_EXT |
120 			     GLX_CONTEXT_ES2_PROFILE_BIT_EXT;
121 	    if (buffer[0] & ~legal) {
122 		fprintf(stderr, "Unknown bits set in preferred profile "
123 			"bitmask: 0x%x\n", buffer[0] & ~legal);
124 		pass = false;
125 	    }
126             if (!buffer[0]) {
127                 fprintf(stderr, "No preferred API profile!\n");
128                 pass = false;
129             } else if (buffer[0] & (buffer[0] - 1)) {
130                 fprintf(stderr, "More than one preferred API profile\n");
131                 pass = false;
132             }
133 	    break;
134 	    }
135 	default:
136 	    break;
137 	}
138 
139 	return pass;
140 }
141 
142 static bool
subtest_QueryRendererInteger(Display * dpy)143 subtest_QueryRendererInteger(Display *dpy)
144 {
145 	static const char subtest_name[] =
146 		"glXQueryRendererIntegerMESA and "
147 		"glXQueryCurrentRendererIntegerMESA";
148 
149 	bool pass = true;
150 	unsigned i;
151 
152 	for (i = 0; i < ARRAY_SIZE(all_valid_integer_enums); i++) {
153 		unsigned buffer_a[16];
154 		unsigned buffer_b[ARRAY_SIZE(buffer_a)];
155 		Bool success;
156 		unsigned j;
157 
158 		for (j = 0; j < ARRAY_SIZE(buffer_a); j++) {
159 			buffer_a[j] = 0xDEADBEEF;
160 			buffer_b[j] = 0xDEADBEEF;
161 		}
162 
163 		success =
164 			glXQueryRendererIntegerMESA(dpy, 0, 0,
165 						    all_valid_integer_enums[i].attribute,
166 						    buffer_a);
167 		pass = verify_integer_values("glXQueryRendererIntegerMESA",
168 					     success,
169 					     &all_valid_integer_enums[i],
170 					     buffer_a,
171 					     ARRAY_SIZE(buffer_a),
172 					     false)
173 			&& pass;
174 
175 		success =
176 			glXQueryCurrentRendererIntegerMESA(
177 						    all_valid_integer_enums[i].attribute,
178 						    buffer_b);
179 		pass = verify_integer_values("glXQueryCurrentRendererIntegerMESA",
180 					     success,
181 					     &all_valid_integer_enums[i],
182 					     buffer_b,
183 					     ARRAY_SIZE(buffer_b),
184 					     true)
185 			&& pass;
186 
187 		for (j = 0; j < all_valid_integer_enums[i].value_count; j++) {
188 			if (buffer_a[j] != buffer_b[j]) {
189 				fprintf(stderr,
190 					"glXQueryRendererIntegerMESA and "
191 					"glXQueryCurrentRendererIntegerMESA "
192 					"disagree about %s value %d: "
193 					"%d != %d\n",
194 					all_valid_integer_enums[i].name_string,
195 					j,
196 					buffer_a[j],
197 					buffer_b[j]);
198 				pass = false;
199 			}
200 		}
201 	}
202 
203 	piglit_report_subtest_result(pass ? PIGLIT_PASS : PIGLIT_FAIL,
204 				     subtest_name);
205 	return pass;
206 }
207 
208 static bool
subtest_QueryRendererString(Display * dpy)209 subtest_QueryRendererString(Display *dpy)
210 {
211 	static const char subtest_name[] =
212 		"glXQueryRendererStringMESA and "
213 		"glXQueryCurrentRendererStringMESA";
214 
215 	bool pass = true;
216 	unsigned i;
217 
218 	for (i = 0; i < ARRAY_SIZE(all_valid_string_enums); i++) {
219 		const char *string_a;
220 		const char *string_b;
221 
222 		string_a =
223 			glXQueryRendererStringMESA(dpy, 0, 0,
224 						   all_valid_string_enums[i].attribute);
225 		if (string_a == NULL) {
226 			fprintf(stderr,
227 				"glXQueryRendererStringMESA(%s) failed.\n",
228 				all_valid_string_enums[i].name_string);
229 			pass = false;
230 		} else {
231 			printf("glXQueryRendererStringMESA(%s) value:\n"
232 			       "    %s\n",
233 			       all_valid_string_enums[i].name_string,
234 			       string_a);
235 		}
236 
237 		string_b = glXQueryCurrentRendererStringMESA(all_valid_string_enums[i].attribute);
238 		if (string_b == NULL) {
239 			fprintf(stderr,
240 				"glXQueryRendererStringMESA(%s) failed.\n",
241 				all_valid_string_enums[i].name_string);
242 			pass = false;
243 		}
244 
245 		if (string_a != NULL && string_b != NULL
246 		    && strcmp(string_a, string_b) != 0) {
247 			fprintf(stderr,
248 				"glXQueryRendererIntegerMESA and "
249 				"glXQueryCurrentRendererIntegerMESA "
250 				"disagree about %s: %s != %s\n",
251 				all_valid_string_enums[i].name_string,
252 				string_a,
253 				string_b);
254 			pass = false;
255 		}
256 	}
257 
258 	piglit_report_subtest_result(pass ? PIGLIT_PASS : PIGLIT_FAIL,
259 				     subtest_name);
260 	return pass;
261 }
262 
main(int argc,char ** argv)263 int main(int argc, char **argv)
264 {
265 	bool pass = true;
266 	Display *dpy = NULL;
267 	GLXFBConfig fbconfig = None;
268 	XVisualInfo *visinfo = NULL;
269 	Window win = None;
270 	GLXWindow glxWin = None;
271 	GLXContext ctx;
272 
273 	dpy = piglit_get_glx_display();
274 
275 	piglit_require_glx_version(dpy, 1, 4);
276 
277 	initialize_function_pointers(dpy);
278 
279 	visinfo = piglit_get_glx_visual(dpy);
280 	fbconfig = piglit_glx_get_fbconfig_for_visinfo(dpy, visinfo);
281 
282 	win = piglit_get_glx_window_unmapped(dpy, visinfo);
283 	glxWin = glXCreateWindow(dpy, fbconfig, win, NULL);
284 
285 	ctx = glXCreateNewContext(dpy, fbconfig, GLX_RGBA_TYPE, NULL, True);
286 	if (ctx == NULL) {
287 		fprintf(stderr,	"Unable to create OpenGL context!\n");
288 		piglit_report_result(PIGLIT_FAIL);
289 	}
290 
291         glXMakeContextCurrent(dpy, glxWin, glxWin, ctx);
292         piglit_dispatch_default_init(PIGLIT_DISPATCH_GL);
293 
294 	pass = subtest_QueryRendererInteger(dpy) && pass;
295 	pass = subtest_QueryRendererString(dpy) && pass;
296 
297         glXMakeContextCurrent(dpy, 0, 0, 0);
298 
299 	piglit_report_result(pass ? PIGLIT_PASS : PIGLIT_FAIL);
300 	return 0;
301 }
302