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
26extern "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
35static bool CreateContextAttribsARB_was_sent;
36static xcb_glx_create_context_attribs_arb_request_t req;
37static uint32_t sent_attribs[1024];
38static uint32_t next_id;
39
40
41struct glx_screen *psc;
42
43extern "C" Bool
44glx_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
57extern "C" struct glx_screen *
58GetGLXScreenConfigs(Display * dpy, int scrn)
59{
60   (void) dpy;
61   (void) scrn;
62   return psc;
63}
64
65extern "C" uint32_t
66xcb_generate_id(xcb_connection_t *c)
67{
68   (void) c;
69
70   return next_id++;
71}
72
73extern "C" xcb_void_cookie_t
74xcb_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
102extern "C" xcb_generic_error_t *
103xcb_request_check(xcb_connection_t *c, xcb_void_cookie_t cookie)
104{
105   return NULL;
106}
107
108extern "C" void
109__glXSendErrorForXcb(Display * dpy, const xcb_generic_error_t *err)
110{
111}
112
113extern "C" void
114__glXSendError(Display * dpy, int_fast8_t errorCode, uint_fast32_t resourceID,
115               uint_fast16_t minorCode, bool coreX11error)
116{
117}
118
119class glXCreateContextAttribARB_test : public ::testing::Test {
120public:
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
132void
133glXCreateContextAttribARB_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
147void
148glXCreateContextAttribARB_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/*@{*/
163TEST_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
173TEST_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
182TEST_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/*@{*/
200TEST_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
208TEST_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
216TEST_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
224TEST_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
239TEST_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
247TEST_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
255TEST_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
265TEST_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
275TEST_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
286TEST_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
309TEST_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
321TEST_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
329TEST_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/*@{*/
351TEST_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
367TEST_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
382TEST_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
401TEST_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
414TEST_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
427TEST_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
442TEST_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
457TEST_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
472TEST_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
485TEST_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
501TEST_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