• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
sigsegv_handler(int sig)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
fake_query_renderer_integer(struct glx_screen * psc,int attribute,unsigned int * value)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
fake_query_renderer_string(struct glx_screen * psc,int attribute,const char ** value)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 
SetUp()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 
TearDown()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  */
TEST_F(query_renderer_string_test,null_query_render_string)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  */
TEST_F(query_renderer_string_test,invalid_attribute)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       E(GLX_RENDERER_ID_MESA),
175    };
176 
177    for (unsigned i = 0; i < ARRAY_SIZE(invalid_attributes); i++) {
178       query_renderer_integer_called = false;
179       query_renderer_string_called = false;
180 
181       const char *str =
182          glXQueryRendererStringMESA(&dpy, 0, 0, invalid_attributes[i].value);
183       EXPECT_EQ((char *)0, str) << invalid_attributes[i].string;
184       EXPECT_FALSE(query_renderer_integer_called)
185          << invalid_attributes[i].string;
186       EXPECT_FALSE(query_renderer_string_called)
187          << invalid_attributes[i].string;
188    }
189 }
190 
191 /**
192  * glXQueryRendererStringMESA will not call GetGLXScreenConfigs if the display
193  * pointer is \c NULL.  It will also not segfault.
194  */
TEST_F(query_renderer_string_test,null_display_pointer)195 TEST_F(query_renderer_string_test, null_display_pointer)
196 {
197    if (setjmp(jmp) == 0) {
198       GetGLXScreenConfigs_called = false;
199 
200       const char *str =
201          glXQueryRendererStringMESA(NULL, 0, 0, GLX_RENDERER_VENDOR_ID_MESA);
202       EXPECT_EQ((char *)0, str);
203       EXPECT_FALSE(GetGLXScreenConfigs_called);
204    } else {
205       EXPECT_FALSE(got_sigsegv);
206    }
207 }
208 
209 /**
210  * glXQueryRendererStringMESA will return error if GetGLXScreenConfigs returns
211  * NULL.  It will also not segfault.
212  */
TEST_F(query_renderer_string_test,null_screen_pointer)213 TEST_F(query_renderer_string_test, null_screen_pointer)
214 {
215    psc = NULL;
216 
217    if (setjmp(jmp) == 0) {
218       GetGLXScreenConfigs_called = false;
219 
220       const char *str =
221          glXQueryRendererStringMESA(&dpy, 0, 0, GLX_RENDERER_VENDOR_ID_MESA);
222       EXPECT_EQ((char *)0, str);
223       EXPECT_TRUE(GetGLXScreenConfigs_called);
224    } else {
225       EXPECT_FALSE(got_sigsegv);
226    }
227 }
228 
229 /**
230  * glXQueryRendererStringMESA will not call the screen query_render_string
231  * function if the renderer is invalid, and it will return NULL.
232  */
TEST_F(query_renderer_string_test,invalid_renderer_index)233 TEST_F(query_renderer_string_test, invalid_renderer_index)
234 {
235    static const int invalid_renderer_indices[] = {
236       -1,
237       1,
238       999,
239    };
240 
241    if (setjmp(jmp) == 0) {
242       for (unsigned i = 0; i < ARRAY_SIZE(invalid_renderer_indices); i++) {
243          const char *str =
244             glXQueryRendererStringMESA(&dpy, 0,
245                                        invalid_renderer_indices[i],
246                                        GLX_RENDERER_VENDOR_ID_MESA);
247          EXPECT_EQ((char *)0, str) << invalid_renderer_indices[i];
248          EXPECT_FALSE(query_renderer_integer_called)
249             << invalid_renderer_indices[i];
250          EXPECT_FALSE(query_renderer_string_called)
251             << invalid_renderer_indices[i];
252       }
253    } else {
254       EXPECT_FALSE(got_sigsegv);
255    }
256 }
257 
258 /**
259  * glXQueryCurrentRendererStringMESA will return error if there is no context
260  * current.  It will also not segfault.
261  */
TEST_F(query_renderer_string_test,no_current_context)262 TEST_F(query_renderer_string_test, no_current_context)
263 {
264    if (setjmp(jmp) == 0) {
265       const char *str =
266          glXQueryCurrentRendererStringMESA(GLX_RENDERER_VENDOR_ID_MESA);
267       EXPECT_EQ((char *)0, str);
268    } else {
269       EXPECT_FALSE(got_sigsegv);
270    }
271 }
272 
273 /**
274  * glXQueryCurrentRendererIntegerMESA will return \c NULL if the
275  * query_render_string vtable entry is \c NULL.  It will also not segfault.
276  */
TEST_F(query_renderer_integer_test,null_query_render_string)277 TEST_F(query_renderer_integer_test, null_query_render_string)
278 {
279    struct glx_screen_vtable vtable = {
280       NULL,
281       NULL,
282       NULL,
283       NULL
284    };
285 
286    scr.vtable = &vtable;
287 
288    if (setjmp(jmp) == 0) {
289       unsigned value = 0xDEADBEEF;
290       Bool success = glXQueryRendererIntegerMESA(&dpy, 0, 0,
291                                                  GLX_RENDERER_VENDOR_ID_MESA,
292                                                  &value);
293       EXPECT_FALSE(success);
294       EXPECT_EQ(0xDEADBEEF, value);
295    } else {
296       EXPECT_FALSE(got_sigsegv);
297    }
298 }
299 
300 /**
301  * glXQueryCurrentRendererIntegerMESA will not call the screen
302  * query_render_string function with an invalid GLX enum value, and it will
303  * return NULL.
304  */
TEST_F(query_renderer_integer_test,invalid_attribute)305 TEST_F(query_renderer_integer_test, invalid_attribute)
306 {
307    static const attribute_test_vector invalid_attributes[] = {
308       /* These values are just plain invalid for use with this extension.
309        */
310       E(0),
311       E(GLX_VENDOR),
312       E(GLX_VERSION),
313       E(GLX_EXTENSIONS),
314       E(GLX_RENDERER_VENDOR_ID_MESA + 0x10000),
315       E(GLX_RENDERER_DEVICE_ID_MESA + 0x10000),
316       E(GLX_RENDERER_VERSION_MESA + 0x10000),
317       E(GLX_RENDERER_ACCELERATED_MESA + 0x10000),
318       E(GLX_RENDERER_VIDEO_MEMORY_MESA + 0x10000),
319       E(GLX_RENDERER_UNIFIED_MEMORY_ARCHITECTURE_MESA + 0x10000),
320       E(GLX_RENDERER_PREFERRED_PROFILE_MESA + 0x10000),
321       E(GLX_RENDERER_OPENGL_CORE_PROFILE_VERSION_MESA + 0x10000),
322       E(GLX_RENDERER_OPENGL_COMPATIBILITY_PROFILE_VERSION_MESA + 0x10000),
323       E(GLX_RENDERER_OPENGL_ES_PROFILE_VERSION_MESA + 0x10000),
324       E(GLX_RENDERER_OPENGL_ES2_PROFILE_VERSION_MESA + 0x10000),
325       E(GLX_RENDERER_ID_MESA + 0x10000),
326    };
327 
328    for (unsigned i = 0; i < ARRAY_SIZE(invalid_attributes); i++) {
329       query_renderer_integer_called = false;
330       query_renderer_string_called = false;
331 
332       unsigned value = 0xDEADBEEF;
333       Bool success =
334          glXQueryRendererIntegerMESA(&dpy, 0, 0,
335                                      invalid_attributes[i].value,
336                                      &value);
337       EXPECT_FALSE(success) << invalid_attributes[i].string;
338       EXPECT_EQ(0xDEADBEEF, value) << invalid_attributes[i].string;
339       EXPECT_FALSE(query_renderer_integer_called)
340          << invalid_attributes[i].string;
341       EXPECT_FALSE(query_renderer_string_called)
342          << invalid_attributes[i].string;
343    }
344 }
345 
346 /**
347  * glXQueryCurrentRendererIntegerMESA will not call GetGLXScreenConfigs if the
348  * display pointer is \c NULL.  It will also not segfault.
349  */
TEST_F(query_renderer_integer_test,null_display_pointer)350 TEST_F(query_renderer_integer_test, null_display_pointer)
351 {
352    if (setjmp(jmp) == 0) {
353       GetGLXScreenConfigs_called = false;
354 
355       unsigned value = 0xDEADBEEF;
356       Bool success =
357          glXQueryRendererIntegerMESA(NULL, 0, 0, GLX_RENDERER_VENDOR_ID_MESA,
358                                      &value);
359       EXPECT_FALSE(success);
360       EXPECT_EQ(0xDEADBEEF, value);
361       EXPECT_FALSE(GetGLXScreenConfigs_called);
362    } else {
363       EXPECT_FALSE(got_sigsegv);
364    }
365 }
366 
367 /**
368  * glXQueryCurrentRendererIntegerMESA will return error if GetGLXScreenConfigs
369  * returns NULL.  It will also not segfault.
370  */
TEST_F(query_renderer_integer_test,null_screen_pointer)371 TEST_F(query_renderer_integer_test, null_screen_pointer)
372 {
373    psc = NULL;
374 
375    if (setjmp(jmp) == 0) {
376       GetGLXScreenConfigs_called = false;
377 
378       unsigned value = 0xDEADBEEF;
379       Bool success =
380          glXQueryRendererIntegerMESA(&dpy, 0, 0, GLX_RENDERER_VENDOR_ID_MESA,
381             &value);
382       EXPECT_FALSE(success);
383       EXPECT_EQ(0xDEADBEEF, value);
384       EXPECT_TRUE(GetGLXScreenConfigs_called);
385    } else {
386       EXPECT_FALSE(got_sigsegv);
387    }
388 }
389 
390 /**
391  * glXQueryRendererIntegerMESA will not call the screen query_render_integer
392  * function if the renderer is invalid, and it will return NULL.
393  */
TEST_F(query_renderer_integer_test,invalid_renderer_index)394 TEST_F(query_renderer_integer_test, invalid_renderer_index)
395 {
396    static const int invalid_renderer_indices[] = {
397       -1,
398       1,
399       999,
400    };
401 
402    if (setjmp(jmp) == 0) {
403       for (unsigned i = 0; i < ARRAY_SIZE(invalid_renderer_indices); i++) {
404          unsigned value = 0xDEADBEEF;
405          Bool success =
406             glXQueryRendererIntegerMESA(&dpy, 0,
407                                         invalid_renderer_indices[i],
408                                         GLX_RENDERER_VENDOR_ID_MESA,
409                                         &value);
410          EXPECT_FALSE(success) << invalid_renderer_indices[i];
411          EXPECT_EQ(0xDEADBEEF, value) << invalid_renderer_indices[i];
412          EXPECT_FALSE(query_renderer_integer_called)
413             << invalid_renderer_indices[i];
414          EXPECT_FALSE(query_renderer_string_called)
415             << invalid_renderer_indices[i];
416       }
417    } else {
418       EXPECT_FALSE(got_sigsegv);
419    }
420 }
421 
422 /**
423  * glXQueryCurrentRendererIntegerMESA will return error if there is no context
424  * current.  It will also not segfault.
425  */
TEST_F(query_renderer_integer_test,no_current_context)426 TEST_F(query_renderer_integer_test, no_current_context)
427 {
428    if (setjmp(jmp) == 0) {
429       unsigned value = 0xDEADBEEF;
430       Bool success =
431          glXQueryCurrentRendererIntegerMESA(GLX_RENDERER_VENDOR_ID_MESA,
432                                             &value);
433       EXPECT_FALSE(success);
434       EXPECT_EQ(0xDEADBEEF, value);
435    } else {
436       EXPECT_FALSE(got_sigsegv);
437    }
438 }
439