• 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 #if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
28 
29 #include "glxclient.h"
30 #include "glx_error.h"
31 #include "dri2.h"
32 #include "dri_interface.h"
33 #include "dri2_priv.h"
34 
35 struct attribute_test_vector {
36    const char *glx_string;
37    const char *dri_string;
38    int glx_attribute;
39    int dri_attribute;
40 };
41 
42 #define E(g, d) { # g, # d, g, d }
43 
44 static bool got_sigsegv;
45 static jmp_buf jmp;
46 
47 static void
sigsegv_handler(int sig)48 sigsegv_handler(int sig)
49 {
50    (void) sig;
51    got_sigsegv = true;
52    longjmp(jmp, 1);
53 }
54 
55 class dri2_query_renderer_string_test : public ::testing::Test {
56 public:
57    virtual void SetUp();
58    virtual void TearDown();
59 
60    struct sigaction sa;
61    struct sigaction old_sa;
62 };
63 
64 class dri2_query_renderer_integer_test :
65    public dri2_query_renderer_string_test {
66 };
67 
68 static bool queryString_called = false;
69 static int queryString_attribute = -1;
70 
71 static bool queryInteger_called = false;
72 static int queryInteger_attribute = -1;
73 
74 static int
fake_queryInteger(__DRIscreen * screen,int attribute,unsigned int * val)75 fake_queryInteger(__DRIscreen *screen, int attribute, unsigned int *val)
76 {
77    (void) screen;
78 
79    queryInteger_attribute = attribute;
80    queryInteger_called = true;
81 
82    switch (attribute) {
83    case __DRI2_RENDERER_VENDOR_ID:
84       *val = ~__DRI2_RENDERER_VENDOR_ID;
85       return 0;
86    case __DRI2_RENDERER_DEVICE_ID:
87       *val = ~__DRI2_RENDERER_DEVICE_ID;
88       return 0;
89    case __DRI2_RENDERER_VERSION:
90       *val = ~__DRI2_RENDERER_VERSION;
91       return 0;
92    case __DRI2_RENDERER_ACCELERATED:
93       *val = ~__DRI2_RENDERER_ACCELERATED;
94       return 0;
95    case __DRI2_RENDERER_VIDEO_MEMORY:
96       *val = ~__DRI2_RENDERER_VIDEO_MEMORY;
97       return 0;
98    case __DRI2_RENDERER_UNIFIED_MEMORY_ARCHITECTURE:
99       *val = ~__DRI2_RENDERER_UNIFIED_MEMORY_ARCHITECTURE;
100       return 0;
101    case __DRI2_RENDERER_PREFERRED_PROFILE:
102       *val = ~__DRI2_RENDERER_PREFERRED_PROFILE;
103       return 0;
104    case __DRI2_RENDERER_OPENGL_CORE_PROFILE_VERSION:
105       *val = ~__DRI2_RENDERER_OPENGL_CORE_PROFILE_VERSION;
106       return 0;
107    case __DRI2_RENDERER_OPENGL_COMPATIBILITY_PROFILE_VERSION:
108       *val = ~__DRI2_RENDERER_OPENGL_COMPATIBILITY_PROFILE_VERSION;
109       return 0;
110    case __DRI2_RENDERER_OPENGL_ES_PROFILE_VERSION:
111       *val = ~__DRI2_RENDERER_OPENGL_ES_PROFILE_VERSION;
112       return 0;
113    case __DRI2_RENDERER_OPENGL_ES2_PROFILE_VERSION:
114       *val = ~__DRI2_RENDERER_OPENGL_ES2_PROFILE_VERSION;
115       return 0;
116    }
117 
118    return -1;
119 }
120 
121 static int
fake_queryString(__DRIscreen * screen,int attribute,const char ** val)122 fake_queryString(__DRIscreen *screen, int attribute, const char **val)
123 {
124    (void) screen;
125 
126    queryString_attribute = attribute;
127    queryString_called = true;
128 
129    switch (attribute) {
130    case __DRI2_RENDERER_VENDOR_ID:
131       *val = "__DRI2_RENDERER_VENDOR_ID";
132       return 0;
133    case __DRI2_RENDERER_DEVICE_ID:
134       *val = "__DRI2_RENDERER_DEVICE_ID";
135       return 0;
136    }
137 
138    return -1;
139 }
140 
141 static const __DRI2rendererQueryExtension rendererQueryExt = {
142    { __DRI2_RENDERER_QUERY, 1 },
143 
144    fake_queryInteger,
145    fake_queryString
146 };
147 
SetUp()148 void dri2_query_renderer_string_test::SetUp()
149 {
150    got_sigsegv = false;
151 
152    sa.sa_handler = sigsegv_handler;
153    sigemptyset(&sa.sa_mask);
154    sa.sa_flags = 0;
155    sigaction(SIGSEGV, &sa, &old_sa);
156 }
157 
TearDown()158 void dri2_query_renderer_string_test::TearDown()
159 {
160    sigaction(SIGSEGV, &old_sa, NULL);
161 }
162 
163 /**
164  * dri2_query_renderer_string will return an error if the rendererQuery
165  * extension is not present.  It will also not segfault.
166  */
TEST_F(dri2_query_renderer_string_test,DRI2_RENDERER_QUERY_not_supported)167 TEST_F(dri2_query_renderer_string_test, DRI2_RENDERER_QUERY_not_supported)
168 {
169    struct dri2_screen dsc;
170 
171    memset(&dsc, 0, sizeof(dsc));
172 
173    if (setjmp(jmp) == 0) {
174       static const char original_value[] = "0xDEADBEEF";
175       const char *value = original_value;
176       const int success =
177          dri2_query_renderer_string(&dsc.base,
178                                     GLX_RENDERER_VENDOR_ID_MESA, &value);
179 
180       EXPECT_EQ(-1, success);
181       EXPECT_EQ(original_value, value);
182    } else {
183       EXPECT_FALSE(got_sigsegv);
184    }
185 }
186 
187 /**
188  * dri2_query_renderer_string will call queryString with the correct DRI2 enum
189  * for each GLX attribute value.
190  *
191  * \note
192  * This test does \b not perform any checking for invalid GLX attribte values.
193  * Other unit tests verify that invalid values are filtered before
194  * dri2_query_renderer_string is called.
195  */
TEST_F(dri2_query_renderer_string_test,valid_attribute_mapping)196 TEST_F(dri2_query_renderer_string_test, valid_attribute_mapping)
197 {
198    struct dri2_screen dsc;
199    struct attribute_test_vector valid_attributes[] = {
200       E(GLX_RENDERER_VENDOR_ID_MESA,
201         __DRI2_RENDERER_VENDOR_ID),
202       E(GLX_RENDERER_DEVICE_ID_MESA,
203         __DRI2_RENDERER_DEVICE_ID),
204    };
205 
206    memset(&dsc, 0, sizeof(dsc));
207    dsc.rendererQuery = &rendererQueryExt;
208 
209    if (setjmp(jmp) == 0) {
210       for (unsigned i = 0; i < ARRAY_SIZE(valid_attributes); i++) {
211          static const char original_value[] = "original value";
212          const char *value = original_value;
213          const int success =
214             dri2_query_renderer_string(&dsc.base,
215                                        valid_attributes[i].glx_attribute,
216                                        &value);
217 
218          EXPECT_EQ(0, success);
219          EXPECT_EQ(valid_attributes[i].dri_attribute, queryString_attribute)
220             << valid_attributes[i].glx_string;
221          EXPECT_STREQ(valid_attributes[i].dri_string, value)
222             << valid_attributes[i].glx_string;
223       }
224    } else {
225       EXPECT_FALSE(got_sigsegv);
226    }
227 }
228 
229 /**
230  * dri2_query_renderer_integer will return an error if the rendererQuery
231  * extension is not present.  It will also not segfault.
232  */
TEST_F(dri2_query_renderer_integer_test,DRI2_RENDERER_QUERY_not_supported)233 TEST_F(dri2_query_renderer_integer_test, DRI2_RENDERER_QUERY_not_supported)
234 {
235    struct dri2_screen dsc;
236 
237    memset(&dsc, 0, sizeof(dsc));
238 
239    if (setjmp(jmp) == 0) {
240       unsigned int value = 0xDEADBEEF;
241       const int success =
242          dri2_query_renderer_integer(&dsc.base,
243                                     GLX_RENDERER_VENDOR_ID_MESA, &value);
244 
245       EXPECT_EQ(-1, success);
246       EXPECT_EQ(0xDEADBEEF, value);
247    } else {
248       EXPECT_FALSE(got_sigsegv);
249    }
250 }
251 
252 /**
253  * dri2_query_renderer_integer will call queryInteger with the correct DRI2 enum
254  * for each GLX attribute value.
255  *
256  * \note
257  * This test does \b not perform any checking for invalid GLX attribte values.
258  * Other unit tests verify that invalid values are filtered before
259  * dri2_query_renderer_integer is called.
260  */
TEST_F(dri2_query_renderer_integer_test,valid_attribute_mapping)261 TEST_F(dri2_query_renderer_integer_test, valid_attribute_mapping)
262 {
263    struct dri2_screen dsc;
264    struct attribute_test_vector valid_attributes[] = {
265       E(GLX_RENDERER_VENDOR_ID_MESA,
266         __DRI2_RENDERER_VENDOR_ID),
267       E(GLX_RENDERER_DEVICE_ID_MESA,
268         __DRI2_RENDERER_DEVICE_ID),
269       E(GLX_RENDERER_VERSION_MESA,
270         __DRI2_RENDERER_VERSION),
271       E(GLX_RENDERER_ACCELERATED_MESA,
272         __DRI2_RENDERER_ACCELERATED),
273       E(GLX_RENDERER_VIDEO_MEMORY_MESA,
274         __DRI2_RENDERER_VIDEO_MEMORY),
275       E(GLX_RENDERER_UNIFIED_MEMORY_ARCHITECTURE_MESA,
276         __DRI2_RENDERER_UNIFIED_MEMORY_ARCHITECTURE),
277       E(GLX_RENDERER_PREFERRED_PROFILE_MESA,
278         __DRI2_RENDERER_PREFERRED_PROFILE),
279       E(GLX_RENDERER_OPENGL_CORE_PROFILE_VERSION_MESA,
280         __DRI2_RENDERER_OPENGL_CORE_PROFILE_VERSION),
281       E(GLX_RENDERER_OPENGL_COMPATIBILITY_PROFILE_VERSION_MESA,
282         __DRI2_RENDERER_OPENGL_COMPATIBILITY_PROFILE_VERSION),
283       E(GLX_RENDERER_OPENGL_ES_PROFILE_VERSION_MESA,
284         __DRI2_RENDERER_OPENGL_ES_PROFILE_VERSION),
285       E(GLX_RENDERER_OPENGL_ES2_PROFILE_VERSION_MESA,
286         __DRI2_RENDERER_OPENGL_ES2_PROFILE_VERSION),
287    };
288 
289    memset(&dsc, 0, sizeof(dsc));
290    dsc.rendererQuery = &rendererQueryExt;
291 
292    if (setjmp(jmp) == 0) {
293       for (unsigned i = 0; i < ARRAY_SIZE(valid_attributes); i++) {
294          unsigned int value = 0xDEADBEEF;
295          const int success =
296             dri2_query_renderer_integer(&dsc.base,
297                                        valid_attributes[i].glx_attribute,
298                                        &value);
299 
300          EXPECT_EQ(0, success);
301          EXPECT_EQ(valid_attributes[i].dri_attribute, queryInteger_attribute)
302             << valid_attributes[i].glx_string;
303          EXPECT_EQ((unsigned int) ~valid_attributes[i].dri_attribute, value)
304             << valid_attributes[i].glx_string;
305       }
306    } else {
307       EXPECT_FALSE(got_sigsegv);
308    }
309 }
310 
311 #endif /* GLX_DIRECT_RENDERING */
312