glx: Sync <GL/glxext.h> with Khronos
[mesa.git] / src / glx / tests / query_renderer_unittest.cpp
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
21 * DEALINGS IN THE SOFTWARE.
22 */
23 #include <gtest/gtest.h>
24 #include <signal.h>
25 #include <setjmp.h>
26
27 #include "glxclient.h"
28 #include "glx_error.h"
29
30 extern bool GetGLXScreenConfigs_called;
31 extern struct glx_screen *psc;
32
33 struct attribute_test_vector {
34 const char *string;
35 int value;
36 };
37
38 #define E(x) { # x, x }
39
40
41
42 static bool got_sigsegv;
43 static jmp_buf jmp;
44
45 static void
46 sigsegv_handler(int sig)
47 {
48 (void) sig;
49 got_sigsegv = true;
50 longjmp(jmp, 1);
51 }
52
53 static bool query_renderer_string_called = false;
54 static bool query_renderer_integer_called = false;
55
56 static int
57 fake_query_renderer_integer(struct glx_screen *psc, int attribute,
58 unsigned int *value)
59 {
60 (void) psc;
61 (void) attribute;
62 (void) value;
63
64 query_renderer_integer_called = true;
65
66 return -1;
67 }
68
69 static int
70 fake_query_renderer_string(struct glx_screen *psc, int attribute,
71 const char **value)
72 {
73 (void) psc;
74 (void) attribute;
75 (void) value;
76
77 query_renderer_string_called = true;
78
79 return -1;
80 }
81
82 struct glx_screen_vtable fake_vtable = {
83 NULL,
84 NULL,
85 fake_query_renderer_integer,
86 fake_query_renderer_string
87 };
88
89 class query_renderer_string_test : public ::testing::Test {
90 public:
91 virtual void SetUp();
92 virtual void TearDown();
93
94 struct glx_screen scr;
95 struct sigaction sa;
96 struct sigaction old_sa;
97 Display dpy;
98 };
99
100 class query_renderer_integer_test : public query_renderer_string_test {
101 };
102
103 void query_renderer_string_test::SetUp()
104 {
105 memset(&scr, 0, sizeof(scr));
106 scr.vtable = &fake_vtable;
107 psc = &scr;
108
109 got_sigsegv = false;
110
111 sa.sa_handler = sigsegv_handler;
112 sigemptyset(&sa.sa_mask);
113 sa.sa_flags = 0;
114 sigaction(SIGSEGV, &sa, &old_sa);
115 }
116
117 void query_renderer_string_test::TearDown()
118 {
119 sigaction(SIGSEGV, &old_sa, NULL);
120 }
121
122 /**
123 * glXQueryRendererStringMESA will return \c NULL if the query_render_string
124 * vtable entry is \c NULL. It will also not segfault.
125 */
126 TEST_F(query_renderer_string_test, null_query_render_string)
127 {
128 struct glx_screen_vtable vtable = {
129 NULL,
130 NULL,
131 NULL,
132 NULL
133 };
134
135 scr.vtable = &vtable;
136
137 if (setjmp(jmp) == 0) {
138 const char *str =
139 glXQueryRendererStringMESA(&dpy, 0, 0, GLX_RENDERER_VENDOR_ID_MESA);
140 EXPECT_EQ((char *)0, str);
141 } else {
142 EXPECT_FALSE(got_sigsegv);
143 }
144 }
145
146 /**
147 * glXQueryRendererStringMESA will not call the screen query_render_string
148 * function with an invalid GLX enum value, and it will return NULL.
149 */
150 TEST_F(query_renderer_string_test, invalid_attribute)
151 {
152 static const attribute_test_vector invalid_attributes[] = {
153 /* These values are just plain invalid for use with this extension.
154 */
155 E(0),
156 E(GLX_VENDOR),
157 E(GLX_VERSION),
158 E(GLX_EXTENSIONS),
159 E(GLX_RENDERER_VENDOR_ID_MESA + 0x10000),
160 E(GLX_RENDERER_DEVICE_ID_MESA + 0x10000),
161
162 /* These enums are part of the extension, but they are not allowed for
163 * the string query.
164 */
165 E(GLX_RENDERER_VERSION_MESA),
166 E(GLX_RENDERER_ACCELERATED_MESA),
167 E(GLX_RENDERER_VIDEO_MEMORY_MESA),
168 E(GLX_RENDERER_UNIFIED_MEMORY_ARCHITECTURE_MESA),
169 E(GLX_RENDERER_PREFERRED_PROFILE_MESA),
170 E(GLX_RENDERER_OPENGL_CORE_PROFILE_VERSION_MESA),
171 E(GLX_RENDERER_OPENGL_COMPATIBILITY_PROFILE_VERSION_MESA),
172 E(GLX_RENDERER_OPENGL_ES_PROFILE_VERSION_MESA),
173 E(GLX_RENDERER_OPENGL_ES2_PROFILE_VERSION_MESA),
174 };
175
176 for (unsigned i = 0; i < ARRAY_SIZE(invalid_attributes); i++) {
177 query_renderer_integer_called = false;
178 query_renderer_string_called = false;
179
180 const char *str =
181 glXQueryRendererStringMESA(&dpy, 0, 0, invalid_attributes[i].value);
182 EXPECT_EQ((char *)0, str) << invalid_attributes[i].string;
183 EXPECT_FALSE(query_renderer_integer_called)
184 << invalid_attributes[i].string;
185 EXPECT_FALSE(query_renderer_string_called)
186 << invalid_attributes[i].string;
187 }
188 }
189
190 /**
191 * glXQueryRendererStringMESA will not call GetGLXScreenConfigs if the display
192 * pointer is \c NULL. It will also not segfault.
193 */
194 TEST_F(query_renderer_string_test, null_display_pointer)
195 {
196 if (setjmp(jmp) == 0) {
197 GetGLXScreenConfigs_called = false;
198
199 const char *str =
200 glXQueryRendererStringMESA(NULL, 0, 0, GLX_RENDERER_VENDOR_ID_MESA);
201 EXPECT_EQ((char *)0, str);
202 EXPECT_FALSE(GetGLXScreenConfigs_called);
203 } else {
204 EXPECT_FALSE(got_sigsegv);
205 }
206 }
207
208 /**
209 * glXQueryRendererStringMESA will return error if GetGLXScreenConfigs returns
210 * NULL. It will also not segfault.
211 */
212 TEST_F(query_renderer_string_test, null_screen_pointer)
213 {
214 psc = NULL;
215
216 if (setjmp(jmp) == 0) {
217 GetGLXScreenConfigs_called = false;
218
219 const char *str =
220 glXQueryRendererStringMESA(&dpy, 0, 0, GLX_RENDERER_VENDOR_ID_MESA);
221 EXPECT_EQ((char *)0, str);
222 EXPECT_TRUE(GetGLXScreenConfigs_called);
223 } else {
224 EXPECT_FALSE(got_sigsegv);
225 }
226 }
227
228 /**
229 * glXQueryRendererStringMESA will not call the screen query_render_string
230 * function if the renderer is invalid, and it will return NULL.
231 */
232 TEST_F(query_renderer_string_test, invalid_renderer_index)
233 {
234 static const int invalid_renderer_indices[] = {
235 -1,
236 1,
237 999,
238 };
239
240 if (setjmp(jmp) == 0) {
241 for (unsigned i = 0; i < ARRAY_SIZE(invalid_renderer_indices); i++) {
242 const char *str =
243 glXQueryRendererStringMESA(&dpy, 0,
244 invalid_renderer_indices[i],
245 GLX_RENDERER_VENDOR_ID_MESA);
246 EXPECT_EQ((char *)0, str) << invalid_renderer_indices[i];
247 EXPECT_FALSE(query_renderer_integer_called)
248 << invalid_renderer_indices[i];
249 EXPECT_FALSE(query_renderer_string_called)
250 << invalid_renderer_indices[i];
251 }
252 } else {
253 EXPECT_FALSE(got_sigsegv);
254 }
255 }
256
257 /**
258 * glXQueryCurrentRendererStringMESA will return error if there is no context
259 * current. It will also not segfault.
260 */
261 TEST_F(query_renderer_string_test, no_current_context)
262 {
263 if (setjmp(jmp) == 0) {
264 const char *str =
265 glXQueryCurrentRendererStringMESA(GLX_RENDERER_VENDOR_ID_MESA);
266 EXPECT_EQ((char *)0, str);
267 } else {
268 EXPECT_FALSE(got_sigsegv);
269 }
270 }
271
272 /**
273 * glXQueryCurrentRendererIntegerMESA will return \c NULL if the
274 * query_render_string vtable entry is \c NULL. It will also not segfault.
275 */
276 TEST_F(query_renderer_integer_test, null_query_render_string)
277 {
278 struct glx_screen_vtable vtable = {
279 NULL,
280 NULL,
281 NULL,
282 NULL
283 };
284
285 scr.vtable = &vtable;
286
287 if (setjmp(jmp) == 0) {
288 unsigned value = 0xDEADBEEF;
289 Bool success = glXQueryRendererIntegerMESA(&dpy, 0, 0,
290 GLX_RENDERER_VENDOR_ID_MESA,
291 &value);
292 EXPECT_FALSE(success);
293 EXPECT_EQ(0xDEADBEEF, value);
294 } else {
295 EXPECT_FALSE(got_sigsegv);
296 }
297 }
298
299 /**
300 * glXQueryCurrentRendererIntegerMESA will not call the screen
301 * query_render_string function with an invalid GLX enum value, and it will
302 * return NULL.
303 */
304 TEST_F(query_renderer_integer_test, invalid_attribute)
305 {
306 static const attribute_test_vector invalid_attributes[] = {
307 /* These values are just plain invalid for use with this extension.
308 */
309 E(0),
310 E(GLX_VENDOR),
311 E(GLX_VERSION),
312 E(GLX_EXTENSIONS),
313 E(GLX_RENDERER_VENDOR_ID_MESA + 0x10000),
314 E(GLX_RENDERER_DEVICE_ID_MESA + 0x10000),
315 E(GLX_RENDERER_VERSION_MESA + 0x10000),
316 E(GLX_RENDERER_ACCELERATED_MESA + 0x10000),
317 E(GLX_RENDERER_VIDEO_MEMORY_MESA + 0x10000),
318 E(GLX_RENDERER_UNIFIED_MEMORY_ARCHITECTURE_MESA + 0x10000),
319 E(GLX_RENDERER_PREFERRED_PROFILE_MESA + 0x10000),
320 E(GLX_RENDERER_OPENGL_CORE_PROFILE_VERSION_MESA + 0x10000),
321 E(GLX_RENDERER_OPENGL_COMPATIBILITY_PROFILE_VERSION_MESA + 0x10000),
322 E(GLX_RENDERER_OPENGL_ES_PROFILE_VERSION_MESA + 0x10000),
323 E(GLX_RENDERER_OPENGL_ES2_PROFILE_VERSION_MESA + 0x10000),
324 };
325
326 for (unsigned i = 0; i < ARRAY_SIZE(invalid_attributes); i++) {
327 query_renderer_integer_called = false;
328 query_renderer_string_called = false;
329
330 unsigned value = 0xDEADBEEF;
331 Bool success =
332 glXQueryRendererIntegerMESA(&dpy, 0, 0,
333 invalid_attributes[i].value,
334 &value);
335 EXPECT_FALSE(success) << invalid_attributes[i].string;
336 EXPECT_EQ(0xDEADBEEF, value) << invalid_attributes[i].string;
337 EXPECT_FALSE(query_renderer_integer_called)
338 << invalid_attributes[i].string;
339 EXPECT_FALSE(query_renderer_string_called)
340 << invalid_attributes[i].string;
341 }
342 }
343
344 /**
345 * glXQueryCurrentRendererIntegerMESA will not call GetGLXScreenConfigs if the
346 * display pointer is \c NULL. It will also not segfault.
347 */
348 TEST_F(query_renderer_integer_test, null_display_pointer)
349 {
350 if (setjmp(jmp) == 0) {
351 GetGLXScreenConfigs_called = false;
352
353 unsigned value = 0xDEADBEEF;
354 Bool success =
355 glXQueryRendererIntegerMESA(NULL, 0, 0, GLX_RENDERER_VENDOR_ID_MESA,
356 &value);
357 EXPECT_FALSE(success);
358 EXPECT_EQ(0xDEADBEEF, value);
359 EXPECT_FALSE(GetGLXScreenConfigs_called);
360 } else {
361 EXPECT_FALSE(got_sigsegv);
362 }
363 }
364
365 /**
366 * glXQueryCurrentRendererIntegerMESA will return error if GetGLXScreenConfigs
367 * returns NULL. It will also not segfault.
368 */
369 TEST_F(query_renderer_integer_test, null_screen_pointer)
370 {
371 psc = NULL;
372
373 if (setjmp(jmp) == 0) {
374 GetGLXScreenConfigs_called = false;
375
376 unsigned value = 0xDEADBEEF;
377 Bool success =
378 glXQueryRendererIntegerMESA(&dpy, 0, 0, GLX_RENDERER_VENDOR_ID_MESA,
379 &value);
380 EXPECT_FALSE(success);
381 EXPECT_EQ(0xDEADBEEF, value);
382 EXPECT_TRUE(GetGLXScreenConfigs_called);
383 } else {
384 EXPECT_FALSE(got_sigsegv);
385 }
386 }
387
388 /**
389 * glXQueryRendererIntegerMESA will not call the screen query_render_integer
390 * function if the renderer is invalid, and it will return NULL.
391 */
392 TEST_F(query_renderer_integer_test, invalid_renderer_index)
393 {
394 static const int invalid_renderer_indices[] = {
395 -1,
396 1,
397 999,
398 };
399
400 if (setjmp(jmp) == 0) {
401 for (unsigned i = 0; i < ARRAY_SIZE(invalid_renderer_indices); i++) {
402 unsigned value = 0xDEADBEEF;
403 Bool success =
404 glXQueryRendererIntegerMESA(&dpy, 0,
405 invalid_renderer_indices[i],
406 GLX_RENDERER_VENDOR_ID_MESA,
407 &value);
408 EXPECT_FALSE(success) << invalid_renderer_indices[i];
409 EXPECT_EQ(0xDEADBEEF, value) << invalid_renderer_indices[i];
410 EXPECT_FALSE(query_renderer_integer_called)
411 << invalid_renderer_indices[i];
412 EXPECT_FALSE(query_renderer_string_called)
413 << invalid_renderer_indices[i];
414 }
415 } else {
416 EXPECT_FALSE(got_sigsegv);
417 }
418 }
419
420 /**
421 * glXQueryCurrentRendererIntegerMESA will return error if there is no context
422 * current. It will also not segfault.
423 */
424 TEST_F(query_renderer_integer_test, no_current_context)
425 {
426 if (setjmp(jmp) == 0) {
427 unsigned value = 0xDEADBEEF;
428 Bool success =
429 glXQueryCurrentRendererIntegerMESA(GLX_RENDERER_VENDOR_ID_MESA,
430 &value);
431 EXPECT_FALSE(success);
432 EXPECT_EQ(0xDEADBEEF, value);
433 } else {
434 EXPECT_FALSE(got_sigsegv);
435 }
436 }