void QXcbShmImage::put(xcb_window_t window, const QPoint &target, const QRect &source)
{
    Q_XCB_NOOP(connection());
    if (m_gc_window != window) {
        if (m_gc)
            Q_XCB_CALL(xcb_free_gc(xcb_connection(), m_gc));

        m_gc = xcb_generate_id(xcb_connection());
        Q_XCB_CALL(xcb_create_gc(xcb_connection(), m_gc, window, 0, 0));

        m_gc_window = window;
    }

    Q_XCB_NOOP(connection());
    if (m_shm_info.shmaddr) {
        xcb_image_shm_put(xcb_connection(),
                          window,
                          m_gc,
                          m_xcb_image,
                          m_shm_info,
                          source.x(),
                          source.y(),
                          target.x(),
                          target.y(),
                          source.width(),
                          source.height(),
                          false);
    } else {
        // If we upload the whole image in a single chunk, the result might be
        // larger than the server's maximum request size and stuff breaks.
        // To work around that, we upload the image in chunks where each chunk
        // is small enough for a single request.
        int src_x = source.x();
        int src_y = source.y();
        int target_x = target.x();
        int target_y = target.y();
        int width = source.width();
        int height = source.height();

        // We must make sure that each request is not larger than max_req_size.
        // Each request takes req_size + m_xcb_image->stride * height bytes.
        uint32_t max_req_size = xcb_get_maximum_request_length(xcb_connection());
        uint32_t req_size = sizeof(xcb_put_image_request_t);
        int rows_per_put = (max_req_size - req_size) / m_xcb_image->stride;

        // This assert could trigger if a single row has more pixels than fit in
        // a single PutImage request. However, max_req_size is guaranteed to be
        // at least 16384 bytes. That should be enough for quite large images.
        Q_ASSERT(rows_per_put > 0);

        while (height > 0) {
            int rows = std::min(height, rows_per_put);

            xcb_image_t *subimage = xcb_image_subimage(m_xcb_image, src_x, src_y, width, rows,
                                                       0, 0, 0);
            xcb_image_put(xcb_connection(),
                          window,
                          m_gc,
                          subimage,
                          target_x,
                          target_y,
                          0);

            xcb_image_destroy(subimage);

            src_y += rows;
            target_y += rows;
            height -= rows;
        }
    }
    Q_XCB_NOOP(connection());

    m_dirty = m_dirty | source;

    xcb_flush(xcb_connection());
    Q_XCB_NOOP(connection());
}
void
_ecore_xcb_extensions_finalize(void)
{
   LOGFN(__FILE__, __LINE__, __FUNCTION__);

   xcb_get_extension_data(_ecore_xcb_conn, &xcb_big_requests_id);
   xcb_get_extension_data(_ecore_xcb_conn, &xcb_shm_id);

#ifdef ECORE_XCB_SHAPE
   _ecore_xcb_shape_finalize();
#endif

#ifdef ECORE_XCB_SCREENSAVER
   _ecore_xcb_screensaver_finalize();
#endif

#ifdef ECORE_XCB_SYNC
   _ecore_xcb_sync_finalize();
#endif

#ifdef ECORE_XCB_RANDR
   _ecore_xcb_randr_finalize();
#endif

#ifdef ECORE_XCB_XFIXES
   _ecore_xcb_xfixes_finalize();
#endif

#ifdef ECORE_XCB_DAMAGE
   _ecore_xcb_damage_finalize();
#endif

#ifdef ECORE_XCB_RENDER
   _ecore_xcb_render_finalize();
#endif

#ifdef ECORE_XCB_COMPOSITE
   _ecore_xcb_composite_finalize();
#endif

#ifdef ECORE_XCB_DPMS
   _ecore_xcb_dpms_finalize();
#endif

#ifdef ECORE_XCB_CURSOR
   _ecore_xcb_cursor_finalize();
#endif

#ifdef ECORE_XCB_XINERAMA
   _ecore_xcb_xinerama_finalize();
#endif

#ifdef ECORE_XCB_XINPUT
   _ecore_xcb_input_finalize();
#endif

#ifdef ECORE_XCB_GESTURE
   _ecore_xcb_gesture_finalize();
#endif

#ifdef ECORE_XCB_XPRESENT
   _ecore_xcb_present_finalize();
#endif

/* #ifdef ECORE_XCB_DRI */
/*    _ecore_xcb_dri_finalize(); */
/* #endif */

#ifdef ECORE_XCB_XTEST
   _ecore_xcb_xtest_finalize();
#endif

   xcb_get_maximum_request_length(_ecore_xcb_conn);
}
Exemple #3
0
 virtual
 uint32_t
 get_maximum_request_length(void) const
 {
   return xcb_get_maximum_request_length(m_c.get());
 }
Exemple #4
0
unsigned int xcb_send_request(xcb_connection_t *c, int flags, struct iovec *vector, const xcb_protocol_request_t *req)
{
    uint64_t request;
    uint32_t prefix[2];
    int veclen = req->count;
    enum workarounds workaround = WORKAROUND_NONE;

    if(c->has_error)
        return 0;

    assert(c != 0);
    assert(vector != 0);
    assert(req->count > 0);

    if(!(flags & XCB_REQUEST_RAW))
    {
        static const char pad[3];
        unsigned int i;
        uint16_t shortlen = 0;
        size_t longlen = 0;
        assert(vector[0].iov_len >= 4);
        /* set the major opcode, and the minor opcode for extensions */
        if(req->ext)
        {
            const xcb_query_extension_reply_t *extension = xcb_get_extension_data(c, req->ext);
            if(!(extension && extension->present))
            {
                _xcb_conn_shutdown(c, XCB_CONN_CLOSED_EXT_NOTSUPPORTED);
                return 0;
            }
            ((uint8_t *) vector[0].iov_base)[0] = extension->major_opcode;
            ((uint8_t *) vector[0].iov_base)[1] = req->opcode;
        }
        else
            ((uint8_t *) vector[0].iov_base)[0] = req->opcode;

        /* put together the length field, possibly using BIGREQUESTS */
        for(i = 0; i < req->count; ++i)
        {
            longlen += vector[i].iov_len;
            if(!vector[i].iov_base)
            {
                vector[i].iov_base = (char *) pad;
                assert(vector[i].iov_len <= sizeof(pad));
            }
        }
        assert((longlen & 3) == 0);
        longlen >>= 2;

        if(longlen <= c->setup->maximum_request_length)
        {
            /* we don't need BIGREQUESTS. */
            shortlen = longlen;
            longlen = 0;
        }
        else if(longlen > xcb_get_maximum_request_length(c))
        {
            _xcb_conn_shutdown(c, XCB_CONN_CLOSED_REQ_LEN_EXCEED);
            return 0; /* server can't take this; maybe need BIGREQUESTS? */
        }

        /* set the length field. */
        ((uint16_t *) vector[0].iov_base)[1] = shortlen;
        if(!shortlen)
        {
            prefix[0] = ((uint32_t *) vector[0].iov_base)[0];
            prefix[1] = ++longlen;
            vector[0].iov_base = (uint32_t *) vector[0].iov_base + 1;
            vector[0].iov_len -= sizeof(uint32_t);
            --vector, ++veclen;
            vector[0].iov_base = prefix;
            vector[0].iov_len = sizeof(prefix);
        }
    }
    flags &= ~XCB_REQUEST_RAW;

    /* do we need to work around the X server bug described in glx.xml? */
    /* XXX: GetFBConfigs won't use BIG-REQUESTS in any sane
     * configuration, but that should be handled here anyway. */
    if(req->ext && !req->isvoid && !strcmp(req->ext->name, "GLX") &&
            ((req->opcode == 17 && ((uint32_t *) vector[0].iov_base)[1] == 0x10004) ||
             req->opcode == 21))
        workaround = WORKAROUND_GLX_GET_FB_CONFIGS_BUG;

    /* get a sequence number and arrange for delivery. */
    pthread_mutex_lock(&c->iolock);
    /* wait for other writing threads to get out of my way. */
    while(c->out.writing)
        pthread_cond_wait(&c->out.cond, &c->iolock);
    get_socket_back(c);

    /* send GetInputFocus (sync_req) when 64k-2 requests have been sent without
     * a reply. */
    if(req->isvoid && c->out.request == c->in.request_expected + (1 << 16) - 2)
        send_sync(c);
    /* Also send sync_req (could use NoOp) at 32-bit wrap to avoid having
     * applications see sequence 0 as that is used to indicate
     * an error in sending the request */
    if((unsigned int) (c->out.request + 1) == 0)
        send_sync(c);

    /* The above send_sync calls could drop the I/O lock, but this
     * thread will still exclude any other thread that tries to write,
     * so the sequence number postconditions still hold. */
    send_request(c, req->isvoid, workaround, flags, vector, veclen);
    request = c->has_error ? 0 : c->out.request;
    pthread_mutex_unlock(&c->iolock);
    return request;
}