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