randr: ProcRRGetMonitors(): collect reply payload in temporary buffer

Instead of arbitrary count of individual WriteToClient() calls on small
chunks, collect the whole payload in a buffer and write it out all at once.

This also makes possible to use generic macros for reply sending, as well
as further simplifications in the write-out path.

Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/1794>
This commit is contained in:
Enrico Weigelt, metux IT consult 2024-07-29 18:23:15 +02:00 committed by Marge Bot
parent 203f59c6d3
commit 1bc6ca30a9

View File

@ -604,11 +604,13 @@ ProcRRGetMonitors(ClientPtr client)
noutputs += monitors[m].numOutputs; noutputs += monitors[m].numOutputs;
} }
int payload_len = noutputs * sizeof(CARD32) + nmonitors * sizeof(xRRMonitorInfo);
xRRGetMonitorsReply rep = { xRRGetMonitorsReply rep = {
.type = X_Reply, .type = X_Reply,
.sequenceNumber = client->sequence, .sequenceNumber = client->sequence,
.timestamp = RRMonitorTimestamp(screen), .timestamp = RRMonitorTimestamp(screen),
.length = noutputs + nmonitors * bytes_to_int32(sizeof(xRRMonitorInfo)), .length = bytes_to_int32(payload_len),
.nmonitors = nmonitors, .nmonitors = nmonitors,
.noutputs = noutputs, .noutputs = noutputs,
}; };
@ -622,9 +624,18 @@ ProcRRGetMonitors(ClientPtr client)
} }
WriteToClient(client, sizeof(xRRGetMonitorsReply), &rep); WriteToClient(client, sizeof(xRRGetMonitorsReply), &rep);
char *payload_buf = calloc(1, payload_len);
if (!payload_buf) {
RRMonitorFreeList(monitors, nmonitors);
return BadAlloc;
}
char *walk = payload_buf;
for (m = 0; m < nmonitors; m++) { for (m = 0; m < nmonitors; m++) {
RRMonitorPtr monitor = &monitors[m]; RRMonitorPtr monitor = &monitors[m];
xRRMonitorInfo info = { xRRMonitorInfo *info = (xRRMonitorInfo*) walk;
*info = (xRRMonitorInfo) {
.name = monitor->name, .name = monitor->name,
.primary = monitor->primary, .primary = monitor->primary,
.automatic = monitor->automatic, .automatic = monitor->automatic,
@ -637,26 +648,27 @@ ProcRRGetMonitors(ClientPtr client)
.heightInMillimeters = monitor->geometry.mmHeight, .heightInMillimeters = monitor->geometry.mmHeight,
}; };
if (client->swapped) { if (client->swapped) {
swapl(&info.name); swapl(&info->name);
swaps(&info.noutput); swaps(&info->noutput);
swaps(&info.x); swaps(&info->x);
swaps(&info.y); swaps(&info->y);
swaps(&info.width); swaps(&info->width);
swaps(&info.height); swaps(&info->height);
swapl(&info.widthInMillimeters); swapl(&info->widthInMillimeters);
swapl(&info.heightInMillimeters); swapl(&info->heightInMillimeters);
} }
RROutput outputs[monitor->numOutputs]; walk += sizeof(xRRMonitorInfo);
memcpy(outputs, monitor->outputs, monitor->numOutputs * sizeof (RROutput)); memcpy(walk, monitor->outputs, monitor->numOutputs * sizeof (RROutput));
if (client->swapped) if (client->swapped)
SwapLongs(outputs, monitor->numOutputs); SwapLongs((CARD32*)walk, monitor->numOutputs);
WriteToClient(client, sizeof(xRRMonitorInfo), &info); walk += monitor->numOutputs * sizeof (RROutput);
WriteToClient(client, sizeof(outputs), outputs);
} }
WriteToClient(client, payload_len, payload_buf);
free(payload_buf);
RRMonitorFreeList(monitors, nmonitors); RRMonitorFreeList(monitors, nmonitors);
return Success; return Success;