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