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); }
virtual uint32_t get_maximum_request_length(void) const { return xcb_get_maximum_request_length(m_c.get()); }
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; }