Merge branch 'master' into 'master'

XGetSubImage: improve efficiency by reducing number of temporary heap allocations

Closes #114

See merge request xorg/lib/libx11!239
This commit is contained in:
qneko 2026-01-30 16:47:15 +00:00
commit 8be5f3d30b

View file

@ -143,12 +143,72 @@ XImage *XGetSubImage(
int dest_x,
int dest_y)
{
XImage *temp_image;
temp_image = XGetImage(dpy, d, x, y, width, height,
plane_mask, format);
if (!temp_image)
return (XImage *)NULL;
_XSetImage(temp_image, dest_image, dest_x, dest_y);
XDestroyImage(temp_image);
return (dest_image);
register xGetImageReq *req;
xGetImageReply rep;
char *data;
unsigned long subimage_bytes_per_line;
unsigned long nbytes_in_reply;
unsigned long nbytes_necessary;
/* if the destination image is not the right format, convert it */
if(dest_image->format != format)
{
XImage *temp_image;
temp_image = XGetImage(dpy, d, x, y, width, height,
plane_mask, format);
if (!temp_image)
return (XImage *)NULL;
_XSetImage(temp_image, dest_image, dest_x, dest_y);
XDestroyImage(temp_image);
return (dest_image);
}
if(dest_x < 0) dest_x = -dest_x;
if(dest_x < 0) dest_y = -dest_y;
width = dest_x + width < dest_image->width ? width : dest_image->width - dest_x;
height = dest_y + height < dest_image->height ? height : dest_image->height - dest_y;
subimage_bytes_per_line = width * (unsigned long)(dest_image->bits_per_pixel / 8);
LockDisplay(dpy);
GetReq (GetImage, req);
req->drawable = d;
req->x = x;
req->y = y;
req->width = width;
req->height = height;
req->planeMask = plane_mask;
req->format = format;
if (_XReply (dpy, (xReply *) &rep, 0, xFalse) == 0 ||
rep.length == 0) {
UnlockDisplay(dpy);
SyncHandle();
return (XImage *)NULL;
}
if (rep.length < (INT_MAX >> 2)) {
nbytes_in_reply = (unsigned long)rep.length << 2;
nbytes_necessary = width * height * (unsigned long)(dest_image->bits_per_pixel / 8);
data = dest_image->data + (unsigned long)(dest_y * dest_image->width + dest_x) * (unsigned long)(dest_image->bits_per_pixel / 8);
} else {
_XEatDataWords(dpy, rep.length);
UnlockDisplay(dpy);
SyncHandle();
return (XImage *) NULL;
}
for (char *row = data, *end = data + height * dest_image->bytes_per_line;
row < end;
row += dest_image->bytes_per_line) {
_XRead (dpy, row, subimage_bytes_per_line);
}
_XEatData (dpy, nbytes_in_reply - nbytes_necessary);
UnlockDisplay(dpy);
SyncHandle();
return (dest_image);
}