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