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);