| /* |
| * Copyright © 2011 Intel Corporation |
| * |
| * Permission is hereby granted, free of charge, to any person obtaining a |
| * copy of this software and associated documentation files (the "Software"), |
| * to deal in the Software without restriction, including without limitation |
| * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
| * and/or sell copies of the Software, and to permit persons to whom the |
| * Software is furnished to do so, subject to the following conditions: |
| * |
| * The above copyright notice and this permission notice (including the next |
| * paragraph) shall be included in all copies or substantial portions of the |
| * Software. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
| * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
| * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
| * DEALINGS IN THE SOFTWARE. |
| */ |
| #include <gtest/gtest.h> |
| #include <string.h> |
| |
| #include "glxclient.h" |
| #include "glx_error.h" |
| |
| #include <xcb/glx.h> |
| #include "mock_xdisplay.h" |
| #include "fake_glx_screen.h" |
| |
| static bool CreateContextAttribsARB_was_sent; |
| static xcb_glx_create_context_attribs_arb_request_t req; |
| static uint32_t sent_attribs[1024]; |
| static uint32_t next_id; |
| |
| |
| struct glx_screen *psc; |
| |
| extern "C" Bool |
| glx_context_init(struct glx_context *gc, |
| struct glx_screen *psc, struct glx_config *config) |
| { |
| gc->majorOpcode = 123; |
| gc->screen = psc->scr; |
| gc->psc = psc; |
| gc->config = config; |
| gc->isDirect = GL_TRUE; |
| gc->currentContextTag = -1; |
| |
| return GL_TRUE; |
| } |
| |
| bool GetGLXScreenConfigs_called = false; |
| |
| extern "C" struct glx_screen * |
| GetGLXScreenConfigs(Display * dpy, int scrn) |
| { |
| (void) dpy; |
| (void) scrn; |
| |
| GetGLXScreenConfigs_called = true; |
| return psc; |
| } |
| |
| extern "C" uint32_t |
| xcb_generate_id(xcb_connection_t *c) |
| { |
| (void) c; |
| |
| return next_id++; |
| } |
| |
| 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) |
| { |
| (void) c; |
| |
| CreateContextAttribsARB_was_sent = true; |
| req.context = context; |
| req.fbconfig = fbconfig; |
| req.screen = screen; |
| req.share_list = share_list; |
| req.is_direct = is_direct; |
| req.num_attribs = num_attribs; |
| |
| if (num_attribs != 0 && attribs != NULL) |
| memcpy(sent_attribs, attribs, num_attribs * 2 * sizeof(uint32_t)); |
| |
| xcb_void_cookie_t cookie; |
| cookie.sequence = 0xbadc0de; |
| |
| return cookie; |
| } |
| |
| extern "C" xcb_generic_error_t * |
| xcb_request_check(xcb_connection_t *c, xcb_void_cookie_t cookie) |
| { |
| return NULL; |
| } |
| |
| extern "C" void |
| __glXSendErrorForXcb(Display * dpy, const xcb_generic_error_t *err) |
| { |
| } |
| |
| extern "C" void |
| __glXSendError(Display * dpy, int_fast8_t errorCode, uint_fast32_t resourceID, |
| uint_fast16_t minorCode, bool coreX11error) |
| { |
| } |
| |
| class glXCreateContextAttribARB_test : public ::testing::Test { |
| public: |
| virtual void SetUp(); |
| |
| /** |
| * Replace the existing screen with a direct-rendering screen |
| */ |
| void use_direct_rendering_screen(); |
| |
| mock_XDisplay *dpy; |
| struct glx_config fbc; |
| }; |
| |
| void |
| glXCreateContextAttribARB_test::SetUp() |
| { |
| CreateContextAttribsARB_was_sent = false; |
| memset(&req, 0, sizeof(req)); |
| next_id = 99; |
| fake_glx_context::contexts_allocated = 0; |
| psc = new fake_glx_screen(NULL, 0, ""); |
| |
| this->dpy = new mock_XDisplay(1); |
| |
| memset(&this->fbc, 0, sizeof(this->fbc)); |
| this->fbc.fbconfigID = 0xbeefcafe; |
| } |
| |
| void |
| glXCreateContextAttribARB_test::use_direct_rendering_screen() |
| { |
| struct glx_screen *direct_psc = |
| new fake_glx_screen_direct(psc->display, |
| psc->scr, |
| psc->serverGLXexts); |
| |
| delete psc; |
| psc = direct_psc; |
| } |
| |
| /** |
| * \name Verify detection of client-side errors |
| */ |
| /*@{*/ |
| TEST_F(glXCreateContextAttribARB_test, NULL_display_returns_None) |
| { |
| GLXContext ctx = |
| glXCreateContextAttribsARB(NULL, (GLXFBConfig) &this->fbc, 0, |
| False, NULL); |
| |
| EXPECT_EQ(None, ctx); |
| EXPECT_EQ(0, fake_glx_context::contexts_allocated); |
| } |
| |
| TEST_F(glXCreateContextAttribARB_test, NULL_fbconfig_returns_None) |
| { |
| GLXContext ctx = |
| glXCreateContextAttribsARB(this->dpy, NULL, 0, False, NULL); |
| |
| EXPECT_EQ(None, ctx); |
| EXPECT_EQ(0, fake_glx_context::contexts_allocated); |
| } |
| |
| TEST_F(glXCreateContextAttribARB_test, NULL_screen_returns_None) |
| { |
| delete psc; |
| psc = NULL; |
| |
| GLXContext ctx = |
| glXCreateContextAttribsARB(this->dpy, (GLXFBConfig) &this->fbc, 0, |
| False, NULL); |
| |
| EXPECT_EQ(None, ctx); |
| EXPECT_EQ(0, fake_glx_context::contexts_allocated); |
| } |
| /*@}*/ |
| |
| /** |
| * \name Verify that correct protocol bits are sent to the server. |
| */ |
| /*@{*/ |
| TEST_F(glXCreateContextAttribARB_test, does_send_protocol) |
| { |
| glXCreateContextAttribsARB(this->dpy, (GLXFBConfig) &this->fbc, 0, |
| False, NULL); |
| |
| EXPECT_TRUE(CreateContextAttribsARB_was_sent); |
| } |
| |
| TEST_F(glXCreateContextAttribARB_test, sent_correct_context) |
| { |
| glXCreateContextAttribsARB(this->dpy, (GLXFBConfig) &this->fbc, 0, |
| False, NULL); |
| |
| EXPECT_EQ(99u, req.context); |
| } |
| |
| TEST_F(glXCreateContextAttribARB_test, sent_correct_fbconfig) |
| { |
| glXCreateContextAttribsARB(this->dpy, (GLXFBConfig) &this->fbc, 0, |
| False, NULL); |
| |
| EXPECT_EQ(0xbeefcafe, req.fbconfig); |
| } |
| |
| TEST_F(glXCreateContextAttribARB_test, sent_correct_share_list) |
| { |
| GLXContext share = |
| glXCreateContextAttribsARB(this->dpy, (GLXFBConfig) &this->fbc, 0, |
| False, NULL); |
| |
| ASSERT_NE((GLXContext) 0, share); |
| |
| glXCreateContextAttribsARB(this->dpy, (GLXFBConfig) &this->fbc, share, |
| False, NULL); |
| |
| struct glx_context *glx_ctx = (struct glx_context *) share; |
| EXPECT_EQ(glx_ctx->xid, req.share_list); |
| } |
| |
| TEST_F(glXCreateContextAttribARB_test, sent_correct_is_direct_for_indirect_screen_and_direct_set_to_true) |
| { |
| glXCreateContextAttribsARB(this->dpy, (GLXFBConfig) &this->fbc, 0, |
| True, NULL); |
| |
| EXPECT_FALSE(req.is_direct); |
| } |
| |
| TEST_F(glXCreateContextAttribARB_test, sent_correct_is_direct_for_indirect_screen_and_direct_set_to_false) |
| { |
| glXCreateContextAttribsARB(this->dpy, (GLXFBConfig) &this->fbc, 0, |
| False, NULL); |
| |
| EXPECT_FALSE(req.is_direct); |
| } |
| |
| TEST_F(glXCreateContextAttribARB_test, sent_correct_is_direct_for_direct_screen_and_direct_set_to_true) |
| { |
| this->use_direct_rendering_screen(); |
| |
| glXCreateContextAttribsARB(this->dpy, (GLXFBConfig) &this->fbc, 0, |
| True, NULL); |
| |
| EXPECT_TRUE(req.is_direct); |
| } |
| |
| TEST_F(glXCreateContextAttribARB_test, sent_correct_is_direct_for_direct_screen_and_direct_set_to_false) |
| { |
| this->use_direct_rendering_screen(); |
| |
| glXCreateContextAttribsARB(this->dpy, (GLXFBConfig) &this->fbc, 0, |
| False, NULL); |
| |
| EXPECT_FALSE(req.is_direct); |
| } |
| |
| TEST_F(glXCreateContextAttribARB_test, sent_correct_screen) |
| { |
| this->fbc.screen = 7; |
| psc->scr = 7; |
| |
| glXCreateContextAttribsARB(this->dpy, (GLXFBConfig) &this->fbc, 0, |
| False, NULL); |
| |
| EXPECT_EQ(7u, req.screen); |
| } |
| |
| TEST_F(glXCreateContextAttribARB_test, sent_correct_num_attribs) |
| { |
| /* Use zeros in the second half of each attribute pair to try and trick the |
| * implementation into termiating the list early. |
| * |
| * Use non-zero in the second half of the last attribute pair to try and |
| * trick the implementation into not terminating the list early enough. |
| */ |
| static const int attribs[] = { |
| 1, 0, |
| 2, 0, |
| 3, 0, |
| 4, 0, |
| 0, 6, |
| 0, 0 |
| }; |
| |
| glXCreateContextAttribsARB(this->dpy, (GLXFBConfig) &this->fbc, 0, |
| False, attribs); |
| |
| EXPECT_EQ(4u, req.num_attribs); |
| } |
| |
| TEST_F(glXCreateContextAttribARB_test, sent_correct_num_attribs_empty_list) |
| { |
| static const int attribs[] = { |
| 0, |
| }; |
| |
| glXCreateContextAttribsARB(this->dpy, (GLXFBConfig) &this->fbc, 0, |
| False, attribs); |
| |
| EXPECT_EQ(0u, req.num_attribs); |
| } |
| |
| TEST_F(glXCreateContextAttribARB_test, sent_correct_num_attribs_NULL_list_pointer) |
| { |
| glXCreateContextAttribsARB(this->dpy, (GLXFBConfig) &this->fbc, 0, |
| False, NULL); |
| |
| EXPECT_EQ(0u, req.num_attribs); |
| } |
| |
| TEST_F(glXCreateContextAttribARB_test, sent_correct_attrib_list) |
| { |
| int attribs[] = { |
| GLX_RENDER_TYPE, GLX_RGBA_TYPE, |
| GLX_CONTEXT_MAJOR_VERSION_ARB, 1, |
| GLX_CONTEXT_MINOR_VERSION_ARB, 2, |
| 0 |
| }; |
| |
| glXCreateContextAttribsARB(this->dpy, (GLXFBConfig) &this->fbc, 0, |
| False, attribs); |
| |
| for (unsigned i = 0; i < 6; i++) { |
| EXPECT_EQ((uint32_t) attribs[i], sent_attribs[i]); |
| } |
| } |
| /*@}*/ |
| |
| /** |
| * \name Verify details of the returned GLXContext |
| */ |
| /*@{*/ |
| TEST_F(glXCreateContextAttribARB_test, correct_context) |
| { |
| GLXContext ctx = |
| glXCreateContextAttribsARB(this->dpy, (GLXFBConfig) &this->fbc, 0, |
| False, NULL); |
| |
| /* Since the server did not return an error, the GLXContext should not be |
| * NULL. |
| */ |
| EXPECT_NE((GLXContext)0, ctx); |
| |
| /* It shouldn't be the XID of the context either. |
| */ |
| EXPECT_NE((GLXContext)99, ctx); |
| } |
| |
| TEST_F(glXCreateContextAttribARB_test, correct_context_xid) |
| { |
| GLXContext ctx = |
| glXCreateContextAttribsARB(this->dpy, (GLXFBConfig) &this->fbc, 0, |
| False, NULL); |
| |
| /* Since the server did not return an error, the GLXContext should not be |
| * NULL. |
| */ |
| ASSERT_NE((GLXContext)0, ctx); |
| |
| struct glx_context *glx_ctx = (struct glx_context *) ctx; |
| EXPECT_EQ(99u, glx_ctx->xid); |
| } |
| |
| TEST_F(glXCreateContextAttribARB_test, correct_context_share_xid) |
| { |
| GLXContext first = |
| glXCreateContextAttribsARB(this->dpy, (GLXFBConfig) &this->fbc, 0, |
| False, NULL); |
| |
| ASSERT_NE((GLXContext) 0, first); |
| |
| GLXContext second = |
| glXCreateContextAttribsARB(this->dpy, (GLXFBConfig) &this->fbc, first, |
| False, NULL); |
| |
| ASSERT_NE((GLXContext) 0, second); |
| |
| struct glx_context *share = (struct glx_context *) first; |
| struct glx_context *ctx = (struct glx_context *) second; |
| EXPECT_EQ(share->xid, ctx->share_xid); |
| } |
| |
| TEST_F(glXCreateContextAttribARB_test, correct_context_isDirect_for_indirect_screen_and_direct_set_to_true) |
| { |
| GLXContext ctx = |
| glXCreateContextAttribsARB(this->dpy, (GLXFBConfig) &this->fbc, 0, |
| True, NULL); |
| |
| ASSERT_NE((GLXContext) 0, ctx); |
| |
| struct glx_context *gc = (struct glx_context *) ctx; |
| |
| EXPECT_FALSE(gc->isDirect); |
| } |
| |
| TEST_F(glXCreateContextAttribARB_test, correct_context_isDirect_for_indirect_screen_and_direct_set_to_false) |
| { |
| GLXContext ctx = |
| glXCreateContextAttribsARB(this->dpy, (GLXFBConfig) &this->fbc, 0, |
| False, NULL); |
| |
| ASSERT_NE((GLXContext) 0, ctx); |
| |
| struct glx_context *gc = (struct glx_context *) ctx; |
| |
| EXPECT_FALSE(gc->isDirect); |
| } |
| |
| TEST_F(glXCreateContextAttribARB_test, correct_context_isDirect_for_direct_screen_and_direct_set_to_true) |
| { |
| this->use_direct_rendering_screen(); |
| |
| GLXContext ctx = |
| glXCreateContextAttribsARB(this->dpy, (GLXFBConfig) &this->fbc, 0, |
| True, NULL); |
| |
| ASSERT_NE((GLXContext) 0, ctx); |
| |
| struct glx_context *gc = (struct glx_context *) ctx; |
| |
| EXPECT_TRUE(gc->isDirect); |
| } |
| |
| TEST_F(glXCreateContextAttribARB_test, correct_context_isDirect_for_direct_screen_and_direct_set_to_false) |
| { |
| this->use_direct_rendering_screen(); |
| |
| GLXContext ctx = |
| glXCreateContextAttribsARB(this->dpy, (GLXFBConfig) &this->fbc, 0, |
| False, NULL); |
| |
| ASSERT_NE((GLXContext) 0, ctx); |
| |
| struct glx_context *gc = (struct glx_context *) ctx; |
| |
| EXPECT_FALSE(gc->isDirect); |
| } |
| |
| TEST_F(glXCreateContextAttribARB_test, correct_indirect_context_client_state_private) |
| { |
| GLXContext ctx = |
| glXCreateContextAttribsARB(this->dpy, (GLXFBConfig) &this->fbc, 0, |
| False, NULL); |
| |
| ASSERT_NE((GLXContext) 0, ctx); |
| |
| struct glx_context *gc = (struct glx_context *) ctx; |
| |
| ASSERT_FALSE(gc->isDirect); |
| EXPECT_EQ((struct __GLXattributeRec *) 0xcafebabe, |
| gc->client_state_private); |
| } |
| |
| TEST_F(glXCreateContextAttribARB_test, correct_indirect_context_config) |
| { |
| GLXContext ctx = |
| glXCreateContextAttribsARB(this->dpy, (GLXFBConfig) &this->fbc, 0, |
| False, NULL); |
| |
| ASSERT_NE((GLXContext) 0, ctx); |
| |
| struct glx_context *gc = (struct glx_context *) ctx; |
| |
| EXPECT_EQ(&this->fbc, gc->config); |
| } |
| |
| TEST_F(glXCreateContextAttribARB_test, correct_context_screen_number) |
| { |
| this->fbc.screen = 7; |
| psc->scr = 7; |
| |
| GLXContext ctx = |
| glXCreateContextAttribsARB(this->dpy, (GLXFBConfig) &this->fbc, 0, |
| False, NULL); |
| |
| ASSERT_NE((GLXContext) 0, ctx); |
| |
| struct glx_context *gc = (struct glx_context *) ctx; |
| |
| EXPECT_EQ(7, gc->screen); |
| } |
| |
| TEST_F(glXCreateContextAttribARB_test, correct_context_screen_pointer) |
| { |
| GLXContext ctx = |
| glXCreateContextAttribsARB(this->dpy, (GLXFBConfig) &this->fbc, 0, |
| False, NULL); |
| |
| ASSERT_NE((GLXContext) 0, ctx); |
| |
| struct glx_context *gc = (struct glx_context *) ctx; |
| |
| EXPECT_EQ(psc, gc->psc); |
| } |
| /*@}*/ |