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