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 
28 #include <xcb/glx.h>
29 
30 #include "mock_xdisplay.h"
31 #include "fake_glx_screen.h"
32 
33 /**
34  * \name Wrappers around some X structures to make the more usable for tests
35  */
36 /*@{*/
37 class fake_glx_screen;
38 
39 class fake_glx_display : public glx_display {
40 public:
fake_glx_display(mock_XDisplay * dpy,int major,int minor)41    fake_glx_display(mock_XDisplay *dpy, int major, int minor)
42    {
43       this->next = 0;
44       this->dpy = dpy;
45       this->minorVersion = minor;
46       this->glXDrawHash = 0;
47 
48       this->screens = new glx_screen *[dpy->nscreens];
49       memset(this->screens, 0, sizeof(struct glx_screen *) * dpy->nscreens);
50    }
51 
~fake_glx_display()52    ~fake_glx_display()
53    {
54       for (int i = 0; i < this->dpy->nscreens; i++) {
55          if (this->screens[i] != NULL)
56             delete (fake_glx_screen *)this->screens[i];
57       }
58 
59       delete [] this->screens;
60    }
61 
62    void init_screen(int i, const char *ext);
63 };
64 
65 class glX_send_client_info_test : public ::testing::Test {
66 public:
67    glX_send_client_info_test();
68    virtual ~glX_send_client_info_test();
69    virtual void SetUp();
70    virtual void TearDown();
71 
72    void common_protocol_expected_false_test(unsigned major, unsigned minor,
73 					    const char *glx_ext, bool *value);
74 
75    void common_protocol_expected_true_test(unsigned major, unsigned minor,
76 					   const char *glx_ext, bool *value);
77 
78    void create_single_screen_display(unsigned major, unsigned minor,
79 				     const char *glx_ext);
80 
81    void destroy_display();
82 
83 protected:
84    fake_glx_display *glx_dpy;
85    mock_XDisplay *display;
86 };
87 
88 void
init_screen(int i,const char * ext)89 fake_glx_display::init_screen(int i, const char *ext)
90 {
91    if (this->screens[i] != NULL)
92       delete this->screens[i];
93 
94    this->screens[i] = new fake_glx_screen(this, i, ext);
95 }
96 /*@}*/
97 
98 static const char ext[] = "GL_XXX_dummy";
99 
100 static bool ClientInfo_was_sent;
101 static bool SetClientInfoARB_was_sent;
102 static bool SetClientInfo2ARB_was_sent;
103 static xcb_connection_t *connection_used;
104 static int gl_ext_length;
105 static char *gl_ext_string;
106 static int glx_ext_length;
107 static char *glx_ext_string;
108 static int num_gl_versions;
109 static uint32_t *gl_versions;
110 static int glx_major;
111 static int glx_minor;
112 
113 extern "C" xcb_connection_t *
XGetXCBConnection(Display * dpy)114 XGetXCBConnection(Display *dpy)
115 {
116    return (xcb_connection_t *) 0xdeadbeef;
117 }
118 
119 extern "C" xcb_void_cookie_t
xcb_glx_client_info(xcb_connection_t * c,uint32_t major_version,uint32_t minor_version,uint32_t str_len,const char * string)120 xcb_glx_client_info(xcb_connection_t *c,
121 		    uint32_t major_version,
122 		    uint32_t minor_version,
123 		    uint32_t str_len,
124 		    const char *string)
125 {
126    xcb_void_cookie_t cookie;
127 
128    ClientInfo_was_sent = true;
129    connection_used = c;
130 
131    gl_ext_string = new char[str_len];
132    memcpy(gl_ext_string, string, str_len);
133    gl_ext_length = str_len;
134 
135    glx_major = major_version;
136    glx_minor = minor_version;
137 
138    cookie.sequence = 0;
139    return cookie;
140 }
141 
142 extern "C" xcb_void_cookie_t
xcb_glx_set_client_info_arb(xcb_connection_t * c,uint32_t major_version,uint32_t minor_version,uint32_t num_versions,uint32_t gl_str_len,uint32_t glx_str_len,const uint32_t * versions,const char * gl_string,const char * glx_string)143 xcb_glx_set_client_info_arb(xcb_connection_t *c,
144 			    uint32_t major_version,
145 			    uint32_t minor_version,
146 			    uint32_t num_versions,
147 			    uint32_t gl_str_len,
148 			    uint32_t glx_str_len,
149 			    const uint32_t *versions,
150 			    const char *gl_string,
151 			    const char *glx_string)
152 {
153    xcb_void_cookie_t cookie;
154 
155    SetClientInfoARB_was_sent = true;
156    connection_used = c;
157 
158    gl_ext_string = new char[gl_str_len];
159    memcpy(gl_ext_string, gl_string, gl_str_len);
160    gl_ext_length = gl_str_len;
161 
162    glx_ext_string = new char[glx_str_len];
163    memcpy(glx_ext_string, glx_string, glx_str_len);
164    glx_ext_length = glx_str_len;
165 
166    gl_versions = new uint32_t[num_versions * 2];
167    memcpy(gl_versions, versions, sizeof(uint32_t) * num_versions * 2);
168    num_gl_versions = num_versions;
169 
170    glx_major = major_version;
171    glx_minor = minor_version;
172 
173    cookie.sequence = 0;
174    return cookie;
175 }
176 
177 extern "C" xcb_void_cookie_t
xcb_glx_set_client_info_2arb(xcb_connection_t * c,uint32_t major_version,uint32_t minor_version,uint32_t num_versions,uint32_t gl_str_len,uint32_t glx_str_len,const uint32_t * versions,const char * gl_string,const char * glx_string)178 xcb_glx_set_client_info_2arb(xcb_connection_t *c,
179 			     uint32_t major_version,
180 			     uint32_t minor_version,
181 			     uint32_t num_versions,
182 			     uint32_t gl_str_len,
183 			     uint32_t glx_str_len,
184 			     const uint32_t *versions,
185 			     const char *gl_string,
186 			     const char *glx_string)
187 {
188    xcb_void_cookie_t cookie;
189 
190    SetClientInfo2ARB_was_sent = true;
191    connection_used = c;
192 
193    gl_ext_string = new char[gl_str_len];
194    memcpy(gl_ext_string, gl_string, gl_str_len);
195    gl_ext_length = gl_str_len;
196 
197    glx_ext_string = new char[glx_str_len];
198    memcpy(glx_ext_string, glx_string, glx_str_len);
199    glx_ext_length = glx_str_len;
200 
201    gl_versions = new uint32_t[num_versions * 3];
202    memcpy(gl_versions, versions, sizeof(uint32_t) * num_versions * 3);
203    num_gl_versions = num_versions;
204 
205    glx_major = major_version;
206    glx_minor = minor_version;
207 
208    cookie.sequence = 0;
209    return cookie;
210 }
211 
212 extern "C" char *
__glXGetClientGLExtensionString()213 __glXGetClientGLExtensionString()
214 {
215    char *str = (char *) malloc(sizeof(ext));
216 
217    memcpy(str, ext, sizeof(ext));
218    return str;
219 }
220 
glX_send_client_info_test()221 glX_send_client_info_test::glX_send_client_info_test()
222    : glx_dpy(0), display(0)
223 {
224    /* empty */
225 }
226 
~glX_send_client_info_test()227 glX_send_client_info_test::~glX_send_client_info_test()
228 {
229    if (glx_dpy)
230       delete glx_dpy;
231 
232    if (display)
233       delete display;
234 }
235 
236 void
SetUp()237 glX_send_client_info_test::SetUp()
238 {
239    ClientInfo_was_sent = false;
240    SetClientInfoARB_was_sent = false;
241    SetClientInfo2ARB_was_sent = false;
242    connection_used = (xcb_connection_t *) ~0;
243    gl_ext_length = 0;
244    gl_ext_string = (char *) 0;
245    glx_ext_length = 0;
246    glx_ext_string = (char *) 0;
247    num_gl_versions = 0;
248    gl_versions = (uint32_t *) 0;
249    glx_major = 0;
250    glx_minor = 0;
251 }
252 
253 void
TearDown()254 glX_send_client_info_test::TearDown()
255 {
256    if (gl_ext_string)
257       delete [] gl_ext_string;
258    if (glx_ext_string)
259       delete [] glx_ext_string;
260    if (gl_versions)
261       delete [] gl_versions;
262 }
263 
264 void
create_single_screen_display(unsigned major,unsigned minor,const char * glx_ext)265 glX_send_client_info_test::create_single_screen_display(unsigned major,
266 							unsigned minor,
267 							const char *glx_ext)
268 {
269    this->display = new mock_XDisplay(1);
270 
271    this->glx_dpy = new fake_glx_display(this->display, major, minor);
272    this->glx_dpy->init_screen(0, glx_ext);
273 }
274 
275 void
common_protocol_expected_false_test(unsigned major,unsigned minor,const char * glx_ext,bool * value)276 glX_send_client_info_test::common_protocol_expected_false_test(unsigned major,
277 							       unsigned minor,
278 							       const char *glx_ext,
279 							       bool *value)
280 {
281    create_single_screen_display(major, minor, glx_ext);
282    __glX_send_client_info(this->glx_dpy);
283    EXPECT_FALSE(*value);
284 }
285 
286 void
common_protocol_expected_true_test(unsigned major,unsigned minor,const char * glx_ext,bool * value)287 glX_send_client_info_test::common_protocol_expected_true_test(unsigned major,
288 							      unsigned minor,
289 							      const char *glx_ext,
290 							      bool *value)
291 {
292    create_single_screen_display(major, minor, glx_ext);
293    __glX_send_client_info(this->glx_dpy);
294    EXPECT_TRUE(*value);
295 }
296 
TEST_F(glX_send_client_info_test,doesnt_send_ClientInfo_for_1_0)297 TEST_F(glX_send_client_info_test, doesnt_send_ClientInfo_for_1_0)
298 {
299    /* The glXClientInfo protocol was added in GLX 1.1.  Verify that no
300     * glXClientInfo is sent to a GLX server that only has GLX 1.0.
301     */
302    common_protocol_expected_false_test(1, 0, "", &ClientInfo_was_sent);
303 }
304 
TEST_F(glX_send_client_info_test,doesnt_send_SetClientInfoARB_for_1_0)305 TEST_F(glX_send_client_info_test, doesnt_send_SetClientInfoARB_for_1_0)
306 {
307    /* The glXSetClientInfoARB protocol was added in GLX 1.4 with the
308     * GLX_ARB_create_context extension.  Verify that no glXSetClientInfoARB is
309     * sent to a GLX server that only has GLX 1.0 regardless of the extension
310     * setting.
311     */
312    common_protocol_expected_false_test(1, 0,
313 				       "GLX_ARB_create_context",
314 				       &SetClientInfoARB_was_sent);
315 }
316 
TEST_F(glX_send_client_info_test,doesnt_send_SetClientInfoARB_for_1_1)317 TEST_F(glX_send_client_info_test, doesnt_send_SetClientInfoARB_for_1_1)
318 {
319    /* The glXSetClientInfoARB protocol was added in GLX 1.4 with the
320     * GLX_ARB_create_context extension.  Verify that no glXSetClientInfoARB is
321     * sent to a GLX server that only has GLX 1.0 regardless of the extension
322     * setting.
323     */
324    common_protocol_expected_false_test(1, 1,
325 				       "GLX_ARB_create_context",
326 				       &SetClientInfoARB_was_sent);
327 }
328 
TEST_F(glX_send_client_info_test,doesnt_send_SetClientInfoARB_for_1_4_with_empty_extensions)329 TEST_F(glX_send_client_info_test, doesnt_send_SetClientInfoARB_for_1_4_with_empty_extensions)
330 {
331    /* The glXSetClientInfoARB protocol was added in GLX 1.4 with the
332     * GLX_ARB_create_context extension.  Verify that no glXSetClientInfoARB is
333     * sent to a GLX server that has GLX 1.4 but has an empty extension string
334     * (i.e., no extensions at all).
335     */
336    common_protocol_expected_false_test(1, 4,
337 				       "",
338 				       &SetClientInfoARB_was_sent);
339 }
340 
TEST_F(glX_send_client_info_test,doesnt_send_SetClientInfoARB_for_1_4_without_extension)341 TEST_F(glX_send_client_info_test, doesnt_send_SetClientInfoARB_for_1_4_without_extension)
342 {
343    /* The glXSetClientInfoARB protocol was added in GLX 1.4 with the
344     * GLX_ARB_create_context extension.  Verify that no glXSetClientInfoARB is
345     * sent to a GLX server that has GLX 1.4 but doesn't have the extension.
346     */
347    common_protocol_expected_false_test(1, 4,
348 				       "GLX_EXT_texture_from_pixmap",
349 				       &SetClientInfoARB_was_sent);
350 }
351 
TEST_F(glX_send_client_info_test,doesnt_send_SetClientInfoARB_for_1_4_with_wrong_extension)352 TEST_F(glX_send_client_info_test, doesnt_send_SetClientInfoARB_for_1_4_with_wrong_extension)
353 {
354    /* The glXSetClientInfoARB protocol was added in GLX 1.4 with the
355     * GLX_ARB_create_context extension.  Verify that no glXSetClientInfoARB is
356     * sent to a GLX server that has GLX 1.4 but does not have the extension.
357     *
358     * This test differs from
359     * doesnt_send_SetClientInfoARB_for_1_4_without_extension in that an
360     * extension exists that looks like the correct extension but isn't.
361     */
362    common_protocol_expected_false_test(1, 4,
363 				       "GLX_ARB_create_context2",
364 				       &SetClientInfoARB_was_sent);
365 }
366 
TEST_F(glX_send_client_info_test,doesnt_send_SetClientInfoARB_for_1_4_with_profile_extension)367 TEST_F(glX_send_client_info_test, doesnt_send_SetClientInfoARB_for_1_4_with_profile_extension)
368 {
369    /* The glXSetClientInfoARB protocol was added in GLX 1.4 with the
370     * GLX_ARB_create_context extension.  Verify that no glXSetClientInfoARB is
371     * sent to a GLX server that has GLX 1.4 but does not have the extension.
372     *
373     * This test differs from
374     * doesnt_send_SetClientInfoARB_for_1_4_without_extension in that an
375     * extension exists that looks like the correct extension but isn't.
376     */
377    common_protocol_expected_false_test(1, 4,
378 				       "GLX_ARB_create_context_profile",
379 				       &SetClientInfoARB_was_sent);
380 }
381 
TEST_F(glX_send_client_info_test,doesnt_send_SetClientInfo2ARB_for_1_0)382 TEST_F(glX_send_client_info_test, doesnt_send_SetClientInfo2ARB_for_1_0)
383 {
384    /* The glXSetClientInfo2ARB protocol was added in GLX 1.4 with the
385     * GLX_ARB_create_context_profile extension.  Verify that no
386     * glXSetClientInfo2ARB is sent to a GLX server that only has GLX 1.0
387     * regardless of the extension setting.
388     */
389    common_protocol_expected_false_test(1, 0,
390 				       "GLX_ARB_create_context_profile",
391 				       &SetClientInfo2ARB_was_sent);
392 }
393 
TEST_F(glX_send_client_info_test,doesnt_send_SetClientInfo2ARB_for_1_1)394 TEST_F(glX_send_client_info_test, doesnt_send_SetClientInfo2ARB_for_1_1)
395 {
396    /* The glXSetClientInfo2ARB protocol was added in GLX 1.4 with the
397     * GLX_ARB_create_context_profile extension.  Verify that no
398     * glXSetClientInfo2ARB is sent to a GLX server that only has GLX 1.1
399     * regardless of the extension setting.
400     */
401    common_protocol_expected_false_test(1, 1,
402 				       "GLX_ARB_create_context_profile",
403 				       &SetClientInfo2ARB_was_sent);
404 }
405 
TEST_F(glX_send_client_info_test,doesnt_send_SetClientInfo2ARB_for_1_4_with_empty_extensions)406 TEST_F(glX_send_client_info_test, doesnt_send_SetClientInfo2ARB_for_1_4_with_empty_extensions)
407 {
408    /* The glXSetClientInfo2ARB protocol was added in GLX 1.4 with the
409     * GLX_ARB_create_context_profile extension.  Verify that no
410     * glXSetClientInfo2ARB is sent to a GLX server that has GLX 1.4 but has an
411     * empty extension string (i.e., no extensions at all).
412     */
413    common_protocol_expected_false_test(1, 4,
414 				       "",
415 				       &SetClientInfo2ARB_was_sent);
416 }
417 
TEST_F(glX_send_client_info_test,doesnt_send_SetClientInfo2ARB_for_1_4_without_extension)418 TEST_F(glX_send_client_info_test, doesnt_send_SetClientInfo2ARB_for_1_4_without_extension)
419 {
420    /* The glXSetClientInfo2ARB protocol was added in GLX 1.4 with the
421     * GLX_ARB_create_context_profile extension.  Verify that no
422     * glXSetClientInfo2ARB is sent to a GLX server that has GLX 1.4 but
423     * doesn't have the extension.
424     */
425    common_protocol_expected_false_test(1, 4,
426 				       "GLX_EXT_texture_from_pixmap",
427 				       &SetClientInfo2ARB_was_sent);
428 }
429 
TEST_F(glX_send_client_info_test,doesnt_send_SetClientInfo2ARB_for_1_4_with_wrong_extension)430 TEST_F(glX_send_client_info_test, doesnt_send_SetClientInfo2ARB_for_1_4_with_wrong_extension)
431 {
432    /* The glXSetClientInfo2ARB protocol was added in GLX 1.4 with the
433     * GLX_ARB_create_context_profile extension.  Verify that no
434     * glXSetClientInfo2ARB is sent to a GLX server that has GLX 1.4 but does
435     * not have the extension.
436     *
437     * This test differs from
438     * doesnt_send_SetClientInfo2ARB_for_1_4_without_extension in that an
439     * extension exists that looks like the correct extension but isn't.
440     */
441    common_protocol_expected_false_test(1, 4,
442 				       "GLX_ARB_create_context_profile2",
443 				       &SetClientInfo2ARB_was_sent);
444 }
445 
TEST_F(glX_send_client_info_test,does_send_ClientInfo_for_1_1)446 TEST_F(glX_send_client_info_test, does_send_ClientInfo_for_1_1)
447 {
448    /* The glXClientInfo protocol was added in GLX 1.1.  Verify that
449     * glXClientInfo is sent to a GLX server that has GLX 1.1.
450     */
451    common_protocol_expected_true_test(1, 1,
452 				      "",
453 				      &ClientInfo_was_sent);
454 }
455 
TEST_F(glX_send_client_info_test,does_send_SetClientInfoARB_for_1_4_with_extension)456 TEST_F(glX_send_client_info_test, does_send_SetClientInfoARB_for_1_4_with_extension)
457 {
458    /* The glXSetClientInfoARB protocol was added in GLX 1.4 with the
459     * GLX_ARB_create_context extension.  Verify that glXSetClientInfoARB is
460     * sent to a GLX server that has GLX 1.4 and the extension.
461     */
462    common_protocol_expected_true_test(1, 4,
463 				      "GLX_ARB_create_context",
464 				      &SetClientInfoARB_was_sent);
465 }
466 
TEST_F(glX_send_client_info_test,does_send_SetClientInfo2ARB_for_1_4_with_just_profile_extension)467 TEST_F(glX_send_client_info_test, does_send_SetClientInfo2ARB_for_1_4_with_just_profile_extension)
468 {
469    /* The glXSetClientInfoARB protocol was added in GLX 1.4 with the
470     * GLX_ARB_create_context extension.  Verify that glXSetClientInfoARB is
471     * sent to a GLX server that has GLX 1.4 and the extension.
472     */
473    common_protocol_expected_true_test(1, 4,
474 				      "GLX_ARB_create_context_profile",
475 				      &SetClientInfo2ARB_was_sent);
476 }
477 
TEST_F(glX_send_client_info_test,does_send_SetClientInfo2ARB_for_1_4_with_both_extensions)478 TEST_F(glX_send_client_info_test, does_send_SetClientInfo2ARB_for_1_4_with_both_extensions)
479 {
480    /* The glXSetClientInfoARB protocol was added in GLX 1.4 with the
481     * GLX_ARB_create_context extension.  Verify that glXSetClientInfoARB is
482     * sent to a GLX server that has GLX 1.4 and the extension.
483     */
484    common_protocol_expected_true_test(1, 4,
485 				      "GLX_ARB_create_context "
486 				      "GLX_ARB_create_context_profile",
487 				      &SetClientInfo2ARB_was_sent);
488 }
489 
TEST_F(glX_send_client_info_test,does_send_SetClientInfo2ARB_for_1_4_with_both_extensions_reversed)490 TEST_F(glX_send_client_info_test, does_send_SetClientInfo2ARB_for_1_4_with_both_extensions_reversed)
491 {
492    /* The glXSetClientInfoARB protocol was added in GLX 1.4 with the
493     * GLX_ARB_create_context extension.  Verify that glXSetClientInfoARB is
494     * sent to a GLX server that has GLX 1.4 and the extension.
495     */
496    common_protocol_expected_true_test(1, 4,
497 				      "GLX_ARB_create_context_profile "
498 				      "GLX_ARB_create_context",
499 				      &SetClientInfo2ARB_was_sent);
500 }
501 
TEST_F(glX_send_client_info_test,uses_correct_connection)502 TEST_F(glX_send_client_info_test, uses_correct_connection)
503 {
504    create_single_screen_display(1, 1, "");
505    __glX_send_client_info(this->glx_dpy);
506    EXPECT_EQ((xcb_connection_t *) 0xdeadbeef, connection_used);
507 }
508 
TEST_F(glX_send_client_info_test,sends_correct_gl_extension_string)509 TEST_F(glX_send_client_info_test, sends_correct_gl_extension_string)
510 {
511    create_single_screen_display(1, 1, "");
512    __glX_send_client_info(this->glx_dpy);
513 
514    ASSERT_EQ((int) sizeof(ext), gl_ext_length);
515    ASSERT_NE((char *) 0, gl_ext_string);
516    EXPECT_EQ(0, memcmp(gl_ext_string, ext, sizeof(ext)));
517 }
518 
TEST_F(glX_send_client_info_test,gl_versions_are_sane)519 TEST_F(glX_send_client_info_test, gl_versions_are_sane)
520 {
521    create_single_screen_display(1, 4, "GLX_ARB_create_context");
522    __glX_send_client_info(this->glx_dpy);
523 
524    ASSERT_NE(0, num_gl_versions);
525 
526    unsigned versions_below_3_0 = 0;
527    for (int i = 0; i < num_gl_versions; i++) {
528       EXPECT_LT(0u, gl_versions[i * 2]);
529       EXPECT_GE(4u, gl_versions[i * 2]);
530 
531       /* Verify that the minor version advertised with the major version makes
532        * sense.
533        */
534       switch (gl_versions[i * 2]) {
535       case 1:
536 	 EXPECT_GE(5u, gl_versions[i * 2 + 1]);
537 	 versions_below_3_0++;
538 	 break;
539       case 2:
540 	 EXPECT_GE(1u, gl_versions[i * 2 + 1]);
541 	 versions_below_3_0++;
542 	 break;
543       case 3:
544 	 EXPECT_GE(3u, gl_versions[i * 2 + 1]);
545 	 break;
546       case 4:
547 	 EXPECT_GE(2u, gl_versions[i * 2 + 1]);
548 	 break;
549       }
550    }
551 
552    /* From the GLX_ARB_create_context spec:
553     *
554     *     "Only the highest supported version below 3.0 should be sent, since
555     *     OpenGL 2.1 is backwards compatible with all earlier versions."
556     */
557    EXPECT_LE(versions_below_3_0, 1u);
558 }
559 
TEST_F(glX_send_client_info_test,gl_versions_and_profiles_are_sane)560 TEST_F(glX_send_client_info_test, gl_versions_and_profiles_are_sane)
561 {
562    create_single_screen_display(1, 4, "GLX_ARB_create_context_profile");
563    __glX_send_client_info(this->glx_dpy);
564 
565    ASSERT_NE(0, num_gl_versions);
566 
567    const uint32_t all_valid_bits = GLX_CONTEXT_CORE_PROFILE_BIT_ARB
568       | GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
569    const uint32_t es_bit = GLX_CONTEXT_ES2_PROFILE_BIT_EXT;
570 
571    unsigned versions_below_3_0 = 0;
572 
573    for (int i = 0; i < num_gl_versions; i++) {
574       EXPECT_LT(0u, gl_versions[i * 3]);
575       EXPECT_GE(4u, gl_versions[i * 3]);
576 
577       /* Verify that the minor version advertised with the major version makes
578        * sense.
579        */
580       switch (gl_versions[i * 3]) {
581       case 1:
582          if (gl_versions[i * 3 + 2] & es_bit) {
583             EXPECT_GE(1u, gl_versions[i * 3 + 1]);
584             EXPECT_EQ(es_bit, gl_versions[i * 3 + 2]);
585          } else {
586             EXPECT_GE(5u, gl_versions[i * 3 + 1]);
587             EXPECT_EQ(0u, gl_versions[i * 3 + 2]);
588             versions_below_3_0++;
589          }
590 	 break;
591       case 2:
592          if (gl_versions[i * 3 + 2] & es_bit) {
593             EXPECT_EQ(0u, gl_versions[i * 3 + 1]);
594             EXPECT_EQ(es_bit, gl_versions[i * 3 + 2]);
595          } else {
596             EXPECT_GE(1u, gl_versions[i * 3 + 1]);
597             EXPECT_EQ(0u, gl_versions[i * 3 + 2]);
598             versions_below_3_0++;
599          }
600 	 break;
601       case 3:
602 	 EXPECT_GE(3u, gl_versions[i * 3 + 1]);
603 
604 	 /* Profiles were not introduced until OpenGL 3.2.
605 	  */
606 	 if (gl_versions[i * 3 + 1] < 2) {
607 	    EXPECT_EQ(0u, gl_versions[i * 3 + 2] & ~(es_bit));
608 	 } else if (gl_versions[i * 3 + 1] == 2) {
609 	    EXPECT_EQ(0u, gl_versions[i * 3 + 2] & ~(all_valid_bits | es_bit));
610 	 } else {
611 	    EXPECT_EQ(0u, gl_versions[i * 3 + 2] & ~(all_valid_bits));
612          }
613 	 break;
614       case 4:
615 	 EXPECT_GE(6u, gl_versions[i * 3 + 1]);
616 	 EXPECT_EQ(0u, gl_versions[i * 3 + 2] & ~(all_valid_bits));
617 	 break;
618       }
619    }
620 
621    /* From the GLX_ARB_create_context_profile spec:
622     *
623     *     "Only the highest supported version below 3.0 should be sent, since
624     *     OpenGL 2.1 is backwards compatible with all earlier versions."
625     */
626    EXPECT_LE(versions_below_3_0, 1u);
627 }
628 
TEST_F(glX_send_client_info_test,glx_version_is_1_4_for_1_1)629 TEST_F(glX_send_client_info_test, glx_version_is_1_4_for_1_1)
630 {
631    create_single_screen_display(1, 1, "");
632    __glX_send_client_info(this->glx_dpy);
633 
634    EXPECT_EQ(1, glx_major);
635    EXPECT_EQ(4, glx_minor);
636 }
637 
TEST_F(glX_send_client_info_test,glx_version_is_1_4_for_1_4)638 TEST_F(glX_send_client_info_test, glx_version_is_1_4_for_1_4)
639 {
640    create_single_screen_display(1, 4, "");
641    __glX_send_client_info(this->glx_dpy);
642 
643    EXPECT_EQ(1, glx_major);
644    EXPECT_EQ(4, glx_minor);
645 }
646 
TEST_F(glX_send_client_info_test,glx_version_is_1_4_for_1_4_with_ARB_create_context)647 TEST_F(glX_send_client_info_test, glx_version_is_1_4_for_1_4_with_ARB_create_context)
648 {
649    create_single_screen_display(1, 4, "GLX_ARB_create_context");
650    __glX_send_client_info(this->glx_dpy);
651 
652    EXPECT_EQ(1, glx_major);
653    EXPECT_EQ(4, glx_minor);
654 }
655 
TEST_F(glX_send_client_info_test,glx_version_is_1_4_for_1_4_with_ARB_create_context_profile)656 TEST_F(glX_send_client_info_test, glx_version_is_1_4_for_1_4_with_ARB_create_context_profile)
657 {
658    create_single_screen_display(1, 4, "GLX_ARB_create_context_profile");
659    __glX_send_client_info(this->glx_dpy);
660 
661    EXPECT_EQ(1, glx_major);
662    EXPECT_EQ(4, glx_minor);
663 }
664 
TEST_F(glX_send_client_info_test,glx_version_is_1_4_for_1_5)665 TEST_F(glX_send_client_info_test, glx_version_is_1_4_for_1_5)
666 {
667    create_single_screen_display(1, 5, "");
668    __glX_send_client_info(this->glx_dpy);
669 
670    EXPECT_EQ(1, glx_major);
671    EXPECT_EQ(4, glx_minor);
672 }
673 
TEST_F(glX_send_client_info_test,glx_extensions_has_GLX_ARB_create_context)674 TEST_F(glX_send_client_info_test, glx_extensions_has_GLX_ARB_create_context)
675 {
676    create_single_screen_display(1, 4, "GLX_ARB_create_context");
677    __glX_send_client_info(this->glx_dpy);
678 
679    ASSERT_NE(0, glx_ext_length);
680    ASSERT_NE((char *) 0, glx_ext_string);
681 
682    bool found_GLX_ARB_create_context = false;
683    const char *const needle = "GLX_ARB_create_context";
684    const unsigned len = strlen(needle);
685    char *haystack = glx_ext_string;
686    while (haystack != NULL) {
687       char *match = strstr(haystack, needle);
688 
689       if (match[len] == '\0' || match[len] == ' ') {
690 	 found_GLX_ARB_create_context = true;
691 	 break;
692       }
693 
694       haystack = match + len;
695    }
696 
697    EXPECT_TRUE(found_GLX_ARB_create_context);
698 }
699 
TEST_F(glX_send_client_info_test,glx_extensions_has_GLX_ARB_create_context_profile)700 TEST_F(glX_send_client_info_test, glx_extensions_has_GLX_ARB_create_context_profile)
701 {
702    create_single_screen_display(1, 4, "GLX_ARB_create_context_profile");
703    __glX_send_client_info(this->glx_dpy);
704 
705    ASSERT_NE(0, glx_ext_length);
706    ASSERT_NE((char *) 0, glx_ext_string);
707 
708    bool found_GLX_ARB_create_context_profile = false;
709    const char *const needle = "GLX_ARB_create_context_profile";
710    const unsigned len = strlen(needle);
711    char *haystack = glx_ext_string;
712    while (haystack != NULL) {
713       char *match = strstr(haystack, needle);
714 
715       if (match[len] == '\0' || match[len] == ' ') {
716 	 found_GLX_ARB_create_context_profile = true;
717 	 break;
718       }
719 
720       haystack = match + len;
721    }
722 
723    EXPECT_TRUE(found_GLX_ARB_create_context_profile);
724 }
725