1/* 2 * Copyright © 2011 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 <string.h> 25 26#include "glxclient.h" 27#include "glx_error.h" 28 29#include <xcb/glx.h> 30#include "mock_xdisplay.h" 31#include "fake_glx_screen.h" 32 33static bool CreateContextAttribsARB_was_sent; 34static xcb_glx_create_context_attribs_arb_request_t req; 35static uint32_t sent_attribs[1024]; 36static uint32_t next_id; 37 38 39struct glx_screen *psc; 40 41extern "C" Bool 42glx_context_init(struct glx_context *gc, 43 struct glx_screen *psc, struct glx_config *config) 44{ 45 gc->majorOpcode = 123; 46 gc->screen = psc->scr; 47 gc->psc = psc; 48 gc->config = config; 49 gc->isDirect = GL_TRUE; 50 gc->currentContextTag = -1; 51 52 return GL_TRUE; 53} 54 55bool GetGLXScreenConfigs_called = false; 56 57extern "C" struct glx_screen * 58GetGLXScreenConfigs(Display * dpy, int scrn) 59{ 60 (void) dpy; 61 (void) scrn; 62 63 GetGLXScreenConfigs_called = true; 64 return psc; 65} 66 67extern "C" uint32_t 68xcb_generate_id(xcb_connection_t *c) 69{ 70 (void) c; 71 72 return next_id++; 73} 74 75extern "C" xcb_void_cookie_t 76xcb_glx_create_context_attribs_arb_checked(xcb_connection_t *c, 77 xcb_glx_context_t context, 78 uint32_t fbconfig, 79 uint32_t screen, 80 uint32_t share_list, 81 uint8_t is_direct, 82 uint32_t num_attribs, 83 const uint32_t *attribs) 84{ 85 (void) c; 86 87 CreateContextAttribsARB_was_sent = true; 88 req.context = context; 89 req.fbconfig = fbconfig; 90 req.screen = screen; 91 req.share_list = share_list; 92 req.is_direct = is_direct; 93 req.num_attribs = num_attribs; 94 95 if (num_attribs != 0 && attribs != NULL) 96 memcpy(sent_attribs, attribs, num_attribs * 2 * sizeof(uint32_t)); 97 98 xcb_void_cookie_t cookie; 99 cookie.sequence = 0xbadc0de; 100 101 return cookie; 102} 103 104extern "C" xcb_void_cookie_t 105xcb_glx_destroy_context(xcb_connection_t *c, xcb_glx_context_t context) 106{ 107 xcb_void_cookie_t cookie; 108 cookie.sequence = 0xbadc0de; 109 110 return cookie; 111} 112 113extern "C" xcb_generic_error_t * 114xcb_request_check(xcb_connection_t *c, xcb_void_cookie_t cookie) 115{ 116 return NULL; 117} 118 119extern "C" void 120__glXSendErrorForXcb(Display * dpy, const xcb_generic_error_t *err) 121{ 122} 123 124extern "C" void 125__glXSendError(Display * dpy, int_fast8_t errorCode, uint_fast32_t resourceID, 126 uint_fast16_t minorCode, bool coreX11error) 127{ 128} 129 130class glXCreateContextAttribARB_test : public ::testing::Test { 131public: 132 virtual void SetUp(); 133 virtual void TearDown(); 134 135 /** 136 * Replace the existing screen with a direct-rendering screen 137 */ 138 void use_direct_rendering_screen(); 139 140 mock_XDisplay *dpy; 141 GLXContext ctx; 142 struct glx_config fbc; 143}; 144 145void 146glXCreateContextAttribARB_test::SetUp() 147{ 148 CreateContextAttribsARB_was_sent = false; 149 memset(&req, 0, sizeof(req)); 150 next_id = 99; 151 fake_glx_context::contexts_allocated = 0; 152 psc = new fake_glx_screen(NULL, 0, ""); 153 154 this->dpy = new mock_XDisplay(1); 155 156 memset(&this->fbc, 0, sizeof(this->fbc)); 157 this->fbc.fbconfigID = 0xbeefcafe; 158 159 this->ctx = NULL; 160} 161 162void 163glXCreateContextAttribARB_test::TearDown() 164{ 165 if (ctx) 166 delete (fake_glx_context *)ctx; 167 168 delete (fake_glx_screen *)psc; 169 170 delete this->dpy; 171} 172 173void 174glXCreateContextAttribARB_test::use_direct_rendering_screen() 175{ 176 struct glx_screen *direct_psc = 177 new fake_glx_screen_direct(psc->display, 178 psc->scr, 179 psc->serverGLXexts); 180 181 delete (fake_glx_screen *)psc; 182 psc = direct_psc; 183} 184 185/** 186 * \name Verify detection of client-side errors 187 */ 188/*@{*/ 189TEST_F(glXCreateContextAttribARB_test, NULL_display_returns_None) 190{ 191 GLXContext ctx = 192 glXCreateContextAttribsARB(NULL, (GLXFBConfig) &this->fbc, 0, 193 False, NULL); 194 195 EXPECT_EQ(None, ctx); 196 EXPECT_EQ(0, fake_glx_context::contexts_allocated); 197} 198 199TEST_F(glXCreateContextAttribARB_test, NULL_screen_returns_None) 200{ 201 delete (fake_glx_screen *)psc; 202 psc = NULL; 203 204 GLXContext ctx = 205 glXCreateContextAttribsARB(this->dpy, (GLXFBConfig) &this->fbc, 0, 206 False, NULL); 207 208 EXPECT_EQ(None, ctx); 209 EXPECT_EQ(0, fake_glx_context::contexts_allocated); 210} 211/*@}*/ 212 213/** 214 * \name Verify that correct protocol bits are sent to the server. 215 */ 216/*@{*/ 217TEST_F(glXCreateContextAttribARB_test, does_send_protocol) 218{ 219 ctx = glXCreateContextAttribsARB(this->dpy, (GLXFBConfig) &this->fbc, 0, 220 False, NULL); 221 222 EXPECT_TRUE(CreateContextAttribsARB_was_sent); 223} 224 225TEST_F(glXCreateContextAttribARB_test, sent_correct_context) 226{ 227 ctx = glXCreateContextAttribsARB(this->dpy, (GLXFBConfig) &this->fbc, 0, 228 False, NULL); 229 EXPECT_EQ(99u, req.context); 230} 231 232TEST_F(glXCreateContextAttribARB_test, sent_correct_fbconfig) 233{ 234 ctx = glXCreateContextAttribsARB(this->dpy, (GLXFBConfig) &this->fbc, 0, 235 False, NULL); 236 237 EXPECT_EQ(0xbeefcafe, req.fbconfig); 238} 239 240TEST_F(glXCreateContextAttribARB_test, sent_correct_share_list) 241{ 242 GLXContext share = 243 glXCreateContextAttribsARB(this->dpy, (GLXFBConfig) &this->fbc, 0, 244 False, NULL); 245 246 ASSERT_NE((GLXContext) 0, share); 247 248 ctx = glXCreateContextAttribsARB(this->dpy, (GLXFBConfig) &this->fbc, share, 249 False, NULL); 250 251 struct glx_context *glx_ctx = (struct glx_context *) share; 252 EXPECT_EQ(glx_ctx->xid, req.share_list); 253 254 delete (fake_glx_context *)share; 255} 256 257TEST_F(glXCreateContextAttribARB_test, sent_correct_is_direct_for_indirect_screen_and_direct_set_to_true) 258{ 259 ctx = glXCreateContextAttribsARB(this->dpy, (GLXFBConfig) &this->fbc, 0, 260 True, NULL); 261 262 EXPECT_FALSE(req.is_direct); 263} 264 265TEST_F(glXCreateContextAttribARB_test, sent_correct_is_direct_for_indirect_screen_and_direct_set_to_false) 266{ 267 ctx = glXCreateContextAttribsARB(this->dpy, (GLXFBConfig) &this->fbc, 0, 268 False, NULL); 269 270 EXPECT_FALSE(req.is_direct); 271} 272 273TEST_F(glXCreateContextAttribARB_test, sent_correct_is_direct_for_direct_screen_and_direct_set_to_true) 274{ 275 this->use_direct_rendering_screen(); 276 277 ctx = glXCreateContextAttribsARB(this->dpy, (GLXFBConfig) &this->fbc, 0, 278 True, NULL); 279 280 EXPECT_TRUE(req.is_direct); 281} 282 283TEST_F(glXCreateContextAttribARB_test, sent_correct_is_direct_for_direct_screen_and_direct_set_to_false) 284{ 285 this->use_direct_rendering_screen(); 286 287 ctx = glXCreateContextAttribsARB(this->dpy, (GLXFBConfig) &this->fbc, 0, 288 False, NULL); 289 290 EXPECT_FALSE(req.is_direct); 291} 292 293TEST_F(glXCreateContextAttribARB_test, sent_correct_screen) 294{ 295 this->fbc.screen = 7; 296 psc->scr = 7; 297 298 ctx = glXCreateContextAttribsARB(this->dpy, (GLXFBConfig) &this->fbc, 0, 299 False, NULL); 300 301 EXPECT_EQ(7u, req.screen); 302} 303 304TEST_F(glXCreateContextAttribARB_test, sent_correct_num_attribs) 305{ 306 /* Use zeros in the second half of each attribute pair to try and trick the 307 * implementation into termiating the list early. 308 * 309 * Use non-zero in the second half of the last attribute pair to try and 310 * trick the implementation into not terminating the list early enough. 311 */ 312 static const int attribs[] = { 313 1, 0, 314 2, 0, 315 3, 0, 316 4, 0, 317 0, 6, 318 0, 0 319 }; 320 321 ctx = glXCreateContextAttribsARB(this->dpy, (GLXFBConfig) &this->fbc, 0, 322 False, attribs); 323 324 EXPECT_EQ(4u, req.num_attribs); 325} 326 327TEST_F(glXCreateContextAttribARB_test, sent_correct_num_attribs_empty_list) 328{ 329 static const int attribs[] = { 330 0, 331 }; 332 333 ctx = glXCreateContextAttribsARB(this->dpy, (GLXFBConfig) &this->fbc, 0, 334 False, attribs); 335 336 EXPECT_EQ(0u, req.num_attribs); 337} 338 339TEST_F(glXCreateContextAttribARB_test, sent_correct_num_attribs_NULL_list_pointer) 340{ 341 ctx = glXCreateContextAttribsARB(this->dpy, (GLXFBConfig) &this->fbc, 0, 342 False, NULL); 343 344 EXPECT_EQ(0u, req.num_attribs); 345} 346 347TEST_F(glXCreateContextAttribARB_test, sent_correct_attrib_list) 348{ 349 int attribs[] = { 350 GLX_RENDER_TYPE, GLX_RGBA_TYPE, 351 GLX_CONTEXT_MAJOR_VERSION_ARB, 1, 352 GLX_CONTEXT_MINOR_VERSION_ARB, 2, 353 0 354 }; 355 356 ctx = glXCreateContextAttribsARB(this->dpy, (GLXFBConfig) &this->fbc, 0, 357 False, attribs); 358 359 for (unsigned i = 0; i < 6; i++) { 360 EXPECT_EQ((uint32_t) attribs[i], sent_attribs[i]); 361 } 362} 363/*@}*/ 364 365/** 366 * \name Verify details of the returned GLXContext 367 */ 368/*@{*/ 369TEST_F(glXCreateContextAttribARB_test, correct_context) 370{ 371 ctx = glXCreateContextAttribsARB(this->dpy, (GLXFBConfig) &this->fbc, 0, 372 False, NULL); 373 374 /* Since the server did not return an error, the GLXContext should not be 375 * NULL. 376 */ 377 EXPECT_NE((GLXContext)0, ctx); 378 379 /* It shouldn't be the XID of the context either. 380 */ 381 EXPECT_NE((GLXContext)99, ctx); 382} 383 384TEST_F(glXCreateContextAttribARB_test, correct_context_xid) 385{ 386 ctx = glXCreateContextAttribsARB(this->dpy, (GLXFBConfig) &this->fbc, 0, 387 False, NULL); 388 389 /* Since the server did not return an error, the GLXContext should not be 390 * NULL. 391 */ 392 ASSERT_NE((GLXContext)0, ctx); 393 394 struct glx_context *glx_ctx = (struct glx_context *) ctx; 395 EXPECT_EQ(99u, glx_ctx->xid); 396} 397 398TEST_F(glXCreateContextAttribARB_test, correct_context_share_xid) 399{ 400 GLXContext first = 401 glXCreateContextAttribsARB(this->dpy, (GLXFBConfig) &this->fbc, 0, 402 False, NULL); 403 404 ASSERT_NE((GLXContext) 0, first); 405 406 GLXContext second = 407 glXCreateContextAttribsARB(this->dpy, (GLXFBConfig) &this->fbc, first, 408 False, NULL); 409 410 ASSERT_NE((GLXContext) 0, second); 411 412 struct glx_context *share = (struct glx_context *) first; 413 struct glx_context *ctx = (struct glx_context *) second; 414 EXPECT_EQ(share->xid, ctx->share_xid); 415 416 delete (fake_glx_context *)first; 417 delete (fake_glx_context *)second; 418} 419 420TEST_F(glXCreateContextAttribARB_test, correct_context_isDirect_for_indirect_screen_and_direct_set_to_true) 421{ 422 ctx = glXCreateContextAttribsARB(this->dpy, (GLXFBConfig) &this->fbc, 0, 423 True, NULL); 424 425 ASSERT_NE((GLXContext) 0, ctx); 426 427 struct glx_context *gc = (struct glx_context *) ctx; 428 429 EXPECT_FALSE(gc->isDirect); 430} 431 432TEST_F(glXCreateContextAttribARB_test, correct_context_isDirect_for_indirect_screen_and_direct_set_to_false) 433{ 434 ctx = glXCreateContextAttribsARB(this->dpy, (GLXFBConfig) &this->fbc, 0, 435 False, NULL); 436 437 ASSERT_NE((GLXContext) 0, ctx); 438 439 struct glx_context *gc = (struct glx_context *) ctx; 440 441 EXPECT_FALSE(gc->isDirect); 442} 443 444TEST_F(glXCreateContextAttribARB_test, correct_context_isDirect_for_direct_screen_and_direct_set_to_true) 445{ 446 this->use_direct_rendering_screen(); 447 448 ctx = glXCreateContextAttribsARB(this->dpy, (GLXFBConfig) &this->fbc, 0, 449 True, NULL); 450 451 ASSERT_NE((GLXContext) 0, ctx); 452 453 struct glx_context *gc = (struct glx_context *) ctx; 454 455 EXPECT_TRUE(gc->isDirect); 456} 457 458TEST_F(glXCreateContextAttribARB_test, correct_context_isDirect_for_direct_screen_and_direct_set_to_false) 459{ 460 this->use_direct_rendering_screen(); 461 462 ctx = glXCreateContextAttribsARB(this->dpy, (GLXFBConfig) &this->fbc, 0, 463 False, NULL); 464 465 ASSERT_NE((GLXContext) 0, ctx); 466 467 struct glx_context *gc = (struct glx_context *) ctx; 468 469 EXPECT_FALSE(gc->isDirect); 470} 471 472TEST_F(glXCreateContextAttribARB_test, correct_indirect_context_client_state_private) 473{ 474 ctx = glXCreateContextAttribsARB(this->dpy, (GLXFBConfig) &this->fbc, 0, 475 False, NULL); 476 477 ASSERT_NE((GLXContext) 0, ctx); 478 479 struct glx_context *gc = (struct glx_context *) ctx; 480 481 ASSERT_FALSE(gc->isDirect); 482 EXPECT_EQ((struct __GLXattributeRec *) 0xcafebabe, 483 gc->client_state_private); 484} 485 486TEST_F(glXCreateContextAttribARB_test, correct_indirect_context_config) 487{ 488 ctx = glXCreateContextAttribsARB(this->dpy, (GLXFBConfig) &this->fbc, 0, 489 False, NULL); 490 491 ASSERT_NE((GLXContext) 0, ctx); 492 493 struct glx_context *gc = (struct glx_context *) ctx; 494 495 EXPECT_EQ(&this->fbc, gc->config); 496} 497 498TEST_F(glXCreateContextAttribARB_test, correct_context_screen_number) 499{ 500 this->fbc.screen = 7; 501 psc->scr = 7; 502 503 ctx = glXCreateContextAttribsARB(this->dpy, (GLXFBConfig) &this->fbc, 0, 504 False, NULL); 505 506 ASSERT_NE((GLXContext) 0, ctx); 507 508 struct glx_context *gc = (struct glx_context *) ctx; 509 510 EXPECT_EQ(7, gc->screen); 511} 512 513TEST_F(glXCreateContextAttribARB_test, correct_context_screen_pointer) 514{ 515 ctx = glXCreateContextAttribsARB(this->dpy, (GLXFBConfig) &this->fbc, 0, 516 False, NULL); 517 518 ASSERT_NE((GLXContext) 0, ctx); 519 520 struct glx_context *gc = (struct glx_context *) ctx; 521 522 EXPECT_EQ(psc, gc->psc); 523} 524/*@}*/ 525