| /*------------------------------------------------------------------------- |
| * drawElements Quality Program Tester Core |
| * ---------------------------------------- |
| * |
| * Copyright (c) 2016 The Khronos Group Inc. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| *//*! |
| * \file |
| * \brief X11 using XCB utilities. |
| *//*--------------------------------------------------------------------*/ |
| |
| #include "tcuLnxX11Xcb.hpp" |
| #include "deMemory.h" |
| |
| namespace tcu |
| { |
| namespace lnx |
| { |
| namespace x11 |
| { |
| |
| XcbDisplay::DisplayState XcbDisplay::s_displayState = XcbDisplay::DISPLAY_STATE_UNKNOWN; |
| |
| bool XcbDisplay::hasDisplay (const char* name) |
| { |
| if (s_displayState == DISPLAY_STATE_UNKNOWN) |
| { |
| xcb_connection_t *connection = xcb_connect(name, NULL); |
| if (connection && !xcb_connection_has_error(connection) ) |
| { |
| s_displayState = DISPLAY_STATE_AVAILABLE; |
| xcb_disconnect(connection); |
| } |
| else |
| { |
| s_displayState = DISPLAY_STATE_UNAVAILABLE; |
| } |
| } |
| return s_displayState == DISPLAY_STATE_AVAILABLE ? true : false; |
| } |
| |
| XcbDisplay::XcbDisplay (EventState& platform, const char* name) |
| : DisplayBase (platform) |
| { |
| m_connection = xcb_connect(name, NULL); |
| const xcb_setup_t *setup = xcb_get_setup(m_connection); |
| xcb_screen_iterator_t iterator = xcb_setup_roots_iterator(setup); |
| m_screen = iterator.data; |
| } |
| |
| XcbDisplay::~XcbDisplay (void) |
| { |
| xcb_disconnect (m_connection); |
| } |
| |
| void XcbDisplay::processEvents (void) |
| { |
| xcb_generic_event_t *ev; |
| while ((ev = xcb_poll_for_event(m_connection))) |
| { |
| deFree(ev); |
| /* Manage your event */ |
| } |
| } |
| |
| XcbWindow::XcbWindow (XcbDisplay& display, int width, int height, xcb_visualid_t* visual) |
| : WindowBase () |
| , m_display (display) |
| { |
| xcb_connection_t* connection = m_display.getConnection(); |
| uint32_t values[2]; |
| m_window = xcb_generate_id(connection); |
| m_colormap = xcb_generate_id(connection); |
| |
| if (visual == DE_NULL) |
| visual = &m_display.getScreen()->root_visual; |
| |
| values[0] = m_display.getScreen()->white_pixel; |
| values[1] = XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_PROPERTY_CHANGE; |
| |
| xcb_create_window ( |
| connection, // Connection |
| XCB_COPY_FROM_PARENT, // depth (same as root) |
| m_window, // window Id |
| display.getScreen()->root, // parent window |
| 0, 0, // x, y |
| static_cast<uint16_t >(width), // width |
| static_cast<uint16_t >(height), // height |
| 10, // border_width |
| XCB_WINDOW_CLASS_INPUT_OUTPUT, // class |
| *visual, // visual |
| XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK, // masks |
| values //not used yet |
| ); |
| |
| xcb_create_colormap ( |
| connection, |
| XCB_COLORMAP_ALLOC_NONE, |
| m_colormap, |
| m_window, |
| *visual |
| ); |
| |
| xcb_alloc_color_reply_t* rep = xcb_alloc_color_reply(connection, xcb_alloc_color(connection, m_colormap, 65535, 0, 0), NULL); |
| deFree(rep); |
| xcb_flush (connection); |
| } |
| |
| XcbWindow::~XcbWindow (void) |
| { |
| xcb_flush (m_display.getConnection()); |
| xcb_free_colormap(m_display.getConnection(), m_colormap); |
| xcb_destroy_window(m_display.getConnection(), m_window); |
| } |
| |
| void XcbWindow::setVisibility (bool visible) |
| { |
| if (visible == m_visible) |
| return; |
| |
| if (visible) |
| xcb_map_window(m_display.getConnection(), m_window); |
| else |
| xcb_unmap_window(m_display.getConnection(), m_window); |
| |
| m_visible = visible; |
| xcb_flush (m_display.getConnection()); |
| |
| } |
| |
| void XcbWindow::processEvents (void) |
| { |
| // A bit of a hack, since we don't really handle all the events. |
| m_display.processEvents(); |
| } |
| |
| void XcbWindow::getDimensions (int* width, int* height) const |
| { |
| xcb_get_geometry_reply_t *geom; |
| geom = xcb_get_geometry_reply(m_display.getConnection(), xcb_get_geometry(m_display.getConnection(), m_window), NULL); |
| *height = static_cast<int>(geom->height); |
| *width = static_cast<int>(geom->width); |
| deFree(geom); |
| } |
| |
| void XcbWindow::setDimensions (int width, int height) |
| { |
| const uint32_t values[] = {static_cast<uint32_t >(width), static_cast<uint32_t >(height)}; |
| xcb_void_cookie_t result; |
| xcb_connection_t* display = m_display.getConnection(); |
| result = xcb_configure_window(display, m_window, XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT, values); |
| DE_ASSERT(DE_NULL == xcb_request_check(display,result)); |
| xcb_flush (display); |
| |
| for(;;) |
| { |
| xcb_generic_event_t* event = xcb_poll_for_event(display); |
| int w, h; |
| if(event != DE_NULL) |
| { |
| if (XCB_PROPERTY_NOTIFY == (event->response_type & ~0x80)) |
| { |
| const xcb_property_notify_event_t* pnEvent = (xcb_property_notify_event_t*)event; |
| if (pnEvent->atom == XCB_ATOM_RESOLUTION) |
| { |
| deFree(event); |
| break; |
| } |
| } |
| deFree(event); |
| } |
| getDimensions (&w,&h); |
| if (h==height || w==width) |
| break; |
| } |
| } |
| |
| } // xcb |
| } // lnx |
| } // tcu |