Avoid exceeding max request length by xcb_put_image. Bug: angleproject:7954 Change-Id: I87efa1c4149b3e3894aa1fbd5afb4e175b677576 Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/70628 Commit-Queue: Roman Lavrov <romanl@google.com> Reviewed-by: Shahbaz Youssefi <syoussefi@google.com> Tested-by: Roman Lavrov <romanl@google.com> Kokoro-Result: kokoro <noreply+kokoro@google.com>
diff --git a/src/WSI/XcbSurfaceKHR.cpp b/src/WSI/XcbSurfaceKHR.cpp index c5a3d54..37e23df 100644 --- a/src/WSI/XcbSurfaceKHR.cpp +++ b/src/WSI/XcbSurfaceKHR.cpp
@@ -188,20 +188,26 @@ int bytesPerPixel = static_cast<int>(image->getImage()->getFormat(VK_IMAGE_ASPECT_COLOR_BIT).bytes()); int width = stride / bytesPerPixel; auto buffer = reinterpret_cast<uint8_t *>(image->getImageMemory()->getOffsetPointer(0)); - size_t bufferSize = extent.height * stride; - libXCB->xcb_put_image( - connection, - XCB_IMAGE_FORMAT_Z_PIXMAP, - window, - gc, - width, - extent.height, - 0, 0, // dst x, y - 0, // left_pad - depth, - bufferSize, // data_len - buffer // data - ); + size_t max_request_size = static_cast<size_t>(libXCB->xcb_get_maximum_request_length(connection)) * 4; + size_t max_strides = (max_request_size - sizeof(xcb_put_image_request_t)) / stride; + for(size_t y = 0; y < extent.height; y += max_strides) + { + size_t num_strides = std::min(max_strides, extent.height - y); + libXCB->xcb_put_image( + connection, + XCB_IMAGE_FORMAT_Z_PIXMAP, + window, + gc, + width, + num_strides, + 0, y, // dst x, y + 0, // left_pad + depth, + num_strides * stride, // data_len + buffer + y * stride // data + ); + } + assert(libXCB->xcb_connection_has_error(connection) == 0); } else {
diff --git a/src/WSI/libXCB.cpp b/src/WSI/libXCB.cpp index 212884c..e0784cc 100644 --- a/src/WSI/libXCB.cpp +++ b/src/WSI/libXCB.cpp
@@ -30,6 +30,8 @@ getFuncAddress(libxcb, "xcb_copy_area", &xcb_copy_area); getFuncAddress(libxcb, "xcb_free_pixmap", &xcb_free_pixmap); getFuncAddress(libxcb, "xcb_get_extension_data", &xcb_get_extension_data); + getFuncAddress(libxcb, "xcb_connection_has_error", &xcb_connection_has_error); + getFuncAddress(libxcb, "xcb_get_maximum_request_length", &xcb_get_maximum_request_length); getFuncAddress(libshm, "xcb_shm_query_version", &xcb_shm_query_version); getFuncAddress(libshm, "xcb_shm_query_version_reply", &xcb_shm_query_version_reply);
diff --git a/src/WSI/libXCB.hpp b/src/WSI/libXCB.hpp index ad957ca..2a8a490 100644 --- a/src/WSI/libXCB.hpp +++ b/src/WSI/libXCB.hpp
@@ -33,6 +33,8 @@ xcb_void_cookie_t (*xcb_copy_area)(xcb_connection_t *conn, xcb_drawable_t src_drawable, xcb_drawable_t dst_drawable, xcb_gcontext_t gc, int16_t src_x, int16_t src_y, int16_t dst_x, int16_t dst_y, uint16_t width, uint16_t height); xcb_void_cookie_t (*xcb_free_pixmap)(xcb_connection_t *conn, xcb_pixmap_t pixmap); xcb_query_extension_reply_t *(*xcb_get_extension_data)(xcb_connection_t *c, xcb_extension_t *extension) = nullptr; + int (*xcb_connection_has_error)(xcb_connection_t *c); + uint32_t (*xcb_get_maximum_request_length)(xcb_connection_t *c); xcb_shm_query_version_cookie_t (*xcb_shm_query_version)(xcb_connection_t *c); xcb_shm_query_version_reply_t *(*xcb_shm_query_version_reply)(xcb_connection_t *c, xcb_shm_query_version_cookie_t cookie, xcb_generic_error_t **e);