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 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 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 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 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 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 */ 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 */ 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 */ 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 */ 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