Compare commits

...

4 Commits

Author SHA1 Message Date
Enrico Weigelt, metux IT consult b70b72077c Xext: xvmc: skip reply payload assembly when no data to send
Instead of trying to calloc() zero-size blocks when there's no actual payload
to send, skip the whole part. This also helps reducing analyzer noise.

Manpages of various BSDs don't tell whether it's safe to pass zero size
at all, so it's better not trying to do so.

Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
2025-05-15 13:37:31 +02:00
Enrico Weigelt, metux IT consult 0fad1274f2 Xext: xvmc: simplify reply struct initialization
* use static initialization where possible
* put the lists into one one block, so they can be written in one pass
* simplify size computations

Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
2025-05-14 14:38:17 +02:00
Enrico Weigelt, metux IT consult 71ef8dbebc Xext: xvmc: use locally scoped counter variables
Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
2025-05-12 18:32:12 +02:00
Enrico Weigelt, metux IT consult 5ef75bc9ee Xext: xvmc: simplify dispatcher
The dispatcher functions are much more complex than they're usually are
(just switch/case statement). Bring them in line with the standard scheme
used in the Xserver, so further steps become easier.

Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
2025-05-12 18:32:12 +02:00

View File

@ -112,7 +112,6 @@ ProcXvMCQueryVersion(ClientPtr client)
xvmcQueryVersionReply rep = { xvmcQueryVersionReply rep = {
.type = X_Reply, .type = X_Reply,
.sequenceNumber = client->sequence, .sequenceNumber = client->sequence,
.length = 0,
.major = SERVER_XVMC_MAJOR_VERSION, .major = SERVER_XVMC_MAJOR_VERSION,
.minor = SERVER_XVMC_MINOR_VERSION .minor = SERVER_XVMC_MINOR_VERSION
}; };
@ -128,13 +127,8 @@ static int
ProcXvMCListSurfaceTypes(ClientPtr client) ProcXvMCListSurfaceTypes(ClientPtr client)
{ {
XvPortPtr pPort; XvPortPtr pPort;
int i;
XvMCScreenPtr pScreenPriv; XvMCScreenPtr pScreenPriv;
xvmcListSurfaceTypesReply rep;
xvmcSurfaceInfo info;
XvMCAdaptorPtr adaptor = NULL; XvMCAdaptorPtr adaptor = NULL;
XvMCSurfaceInfoPtr surface;
int num_surfaces;
REQUEST(xvmcListSurfaceTypesReq); REQUEST(xvmcListSurfaceTypesReq);
REQUEST_SIZE_MATCH(xvmcListSurfaceTypesReq); REQUEST_SIZE_MATCH(xvmcListSurfaceTypesReq);
@ -145,7 +139,7 @@ ProcXvMCListSurfaceTypes(ClientPtr client)
ScreenPtr pScreen = pPort->pAdaptor->pScreen; ScreenPtr pScreen = pPort->pAdaptor->pScreen;
if ((pScreenPriv = XVMC_GET_PRIVATE(pScreen))) { /* any this screen */ if ((pScreenPriv = XVMC_GET_PRIVATE(pScreen))) { /* any this screen */
for (i = 0; i < pScreenPriv->num_adaptors; i++) { for (int i = 0; i < pScreenPriv->num_adaptors; i++) {
if (pPort->pAdaptor == pScreenPriv->adaptors[i].xv_adaptor) { if (pPort->pAdaptor == pScreenPriv->adaptors[i].xv_adaptor) {
adaptor = &(pScreenPriv->adaptors[i]); adaptor = &(pScreenPriv->adaptors[i]);
break; break;
@ -154,28 +148,36 @@ ProcXvMCListSurfaceTypes(ClientPtr client)
} }
} }
num_surfaces = (adaptor) ? adaptor->num_surfaces : 0; int num_surfaces = (adaptor) ? adaptor->num_surfaces : 0;
rep = (xvmcListSurfaceTypesReply) { xvmcSurfaceInfo *info = NULL;
if (num_surfaces) {
info = calloc(sizeof(xvmcSurfaceInfo), num_surfaces);
if (!info)
return BadAlloc;
for (int i = 0; i < num_surfaces; i++) {
XvMCSurfaceInfoPtr surface = adaptor->surfaces[i];
info[i].surface_type_id = surface->surface_type_id;
info[i].chroma_format = surface->chroma_format;
info[i].max_width = surface->max_width;
info[i].max_height = surface->max_height;
info[i].subpicture_max_width = surface->subpicture_max_width;
info[i].subpicture_max_height = surface->subpicture_max_height;
info[i].mc_type = surface->mc_type;
info[i].flags = surface->flags;
}
}
xvmcListSurfaceTypesReply rep = {
.type = X_Reply, .type = X_Reply,
.sequenceNumber = client->sequence, .sequenceNumber = client->sequence,
.num = num_surfaces, .num = num_surfaces,
.length = bytes_to_int32(num_surfaces * sizeof(xvmcSurfaceInfo)), .length = bytes_to_int32(sizeof(xvmcSurfaceInfo) * num_surfaces),
}; };
WriteToClient(client, sizeof(xvmcListSurfaceTypesReply), &rep); WriteToClient(client, sizeof(xvmcListSurfaceTypesReply), &rep);
WriteToClient(client, sizeof(xvmcSurfaceInfo) * num_surfaces, info);
for (i = 0; i < num_surfaces; i++) { free(info);
surface = adaptor->surfaces[i];
info.surface_type_id = surface->surface_type_id;
info.chroma_format = surface->chroma_format;
info.max_width = surface->max_width;
info.max_height = surface->max_height;
info.subpicture_max_width = surface->subpicture_max_width;
info.subpicture_max_height = surface->subpicture_max_height;
info.mc_type = surface->mc_type;
info.flags = surface->flags;
WriteToClient(client, sizeof(xvmcSurfaceInfo), &info);
}
return Success; return Success;
} }
@ -186,13 +188,12 @@ ProcXvMCCreateContext(ClientPtr client)
XvPortPtr pPort; XvPortPtr pPort;
CARD32 *data = NULL; CARD32 *data = NULL;
int dwords = 0; int dwords = 0;
int i, result, adapt_num = -1; int result, adapt_num = -1;
ScreenPtr pScreen; ScreenPtr pScreen;
XvMCContextPtr pContext; XvMCContextPtr pContext;
XvMCScreenPtr pScreenPriv; XvMCScreenPtr pScreenPriv;
XvMCAdaptorPtr adaptor = NULL; XvMCAdaptorPtr adaptor = NULL;
XvMCSurfaceInfoPtr surface = NULL; XvMCSurfaceInfoPtr surface = NULL;
xvmcCreateContextReply rep;
REQUEST(xvmcCreateContextReq); REQUEST(xvmcCreateContextReq);
REQUEST_SIZE_MATCH(xvmcCreateContextReq); REQUEST_SIZE_MATCH(xvmcCreateContextReq);
@ -207,7 +208,7 @@ ProcXvMCCreateContext(ClientPtr client)
if (!(pScreenPriv = XVMC_GET_PRIVATE(pScreen))) /* none this screen */ if (!(pScreenPriv = XVMC_GET_PRIVATE(pScreen))) /* none this screen */
return BadMatch; return BadMatch;
for (i = 0; i < pScreenPriv->num_adaptors; i++) { for (int i = 0; i < pScreenPriv->num_adaptors; i++) {
if (pPort->pAdaptor == pScreenPriv->adaptors[i].xv_adaptor) { if (pPort->pAdaptor == pScreenPriv->adaptors[i].xv_adaptor) {
adaptor = &(pScreenPriv->adaptors[i]); adaptor = &(pScreenPriv->adaptors[i]);
adapt_num = i; adapt_num = i;
@ -218,7 +219,7 @@ ProcXvMCCreateContext(ClientPtr client)
if (adapt_num < 0) /* none this port */ if (adapt_num < 0) /* none this port */
return BadMatch; return BadMatch;
for (i = 0; i < adaptor->num_surfaces; i++) { for (int i = 0; i < adaptor->num_surfaces; i++) {
if (adaptor->surfaces[i]->surface_type_id == stuff->surface_type_id) { if (adaptor->surfaces[i]->surface_type_id == stuff->surface_type_id) {
surface = adaptor->surfaces[i]; surface = adaptor->surfaces[i];
break; break;
@ -257,7 +258,7 @@ ProcXvMCCreateContext(ClientPtr client)
return BadAlloc; return BadAlloc;
} }
rep = (xvmcCreateContextReply) { xvmcCreateContextReply rep = {
.type = X_Reply, .type = X_Reply,
.sequenceNumber = client->sequence, .sequenceNumber = client->sequence,
.length = dwords, .length = dwords,
@ -303,7 +304,6 @@ ProcXvMCCreateSurface(ClientPtr client)
XvMCContextPtr pContext; XvMCContextPtr pContext;
XvMCSurfacePtr pSurface; XvMCSurfacePtr pSurface;
XvMCScreenPtr pScreenPriv; XvMCScreenPtr pScreenPriv;
xvmcCreateSurfaceReply rep;
REQUEST(xvmcCreateSurfaceReq); REQUEST(xvmcCreateSurfaceReq);
REQUEST_SIZE_MATCH(xvmcCreateSurfaceReq); REQUEST_SIZE_MATCH(xvmcCreateSurfaceReq);
@ -336,7 +336,7 @@ ProcXvMCCreateSurface(ClientPtr client)
return BadAlloc; return BadAlloc;
} }
rep = (xvmcCreateSurfaceReply) { xvmcCreateSurfaceReply rep = {
.type = X_Reply, .type = X_Reply,
.sequenceNumber = client->sequence, .sequenceNumber = client->sequence,
.length = dwords .length = dwords
@ -377,11 +377,10 @@ ProcXvMCCreateSubpicture(ClientPtr client)
{ {
Bool image_supported = FALSE; Bool image_supported = FALSE;
CARD32 *data = NULL; CARD32 *data = NULL;
int i, result, dwords = 0; int result, dwords = 0;
XvMCContextPtr pContext; XvMCContextPtr pContext;
XvMCSubpicturePtr pSubpicture; XvMCSubpicturePtr pSubpicture;
XvMCScreenPtr pScreenPriv; XvMCScreenPtr pScreenPriv;
xvmcCreateSubpictureReply rep;
XvMCAdaptorPtr adaptor; XvMCAdaptorPtr adaptor;
XvMCSurfaceInfoPtr surface = NULL; XvMCSurfaceInfoPtr surface = NULL;
@ -398,7 +397,7 @@ ProcXvMCCreateSubpicture(ClientPtr client)
adaptor = &(pScreenPriv->adaptors[pContext->adapt_num]); adaptor = &(pScreenPriv->adaptors[pContext->adapt_num]);
/* find which surface this context supports */ /* find which surface this context supports */
for (i = 0; i < adaptor->num_surfaces; i++) { for (int i = 0; i < adaptor->num_surfaces; i++) {
if (adaptor->surfaces[i]->surface_type_id == pContext->surface_type_id) { if (adaptor->surfaces[i]->surface_type_id == pContext->surface_type_id) {
surface = adaptor->surfaces[i]; surface = adaptor->surfaces[i];
break; break;
@ -412,7 +411,7 @@ ProcXvMCCreateSubpicture(ClientPtr client)
if (!surface->compatible_subpictures) if (!surface->compatible_subpictures)
return BadMatch; return BadMatch;
for (i = 0; i < surface->compatible_subpictures->num_xvimages; i++) { for (int i = 0; i < surface->compatible_subpictures->num_xvimages; i++) {
if (surface->compatible_subpictures->xvimage_ids[i] == if (surface->compatible_subpictures->xvimage_ids[i] ==
stuff->xvimage_id) { stuff->xvimage_id) {
image_supported = TRUE; image_supported = TRUE;
@ -456,7 +455,7 @@ ProcXvMCCreateSubpicture(ClientPtr client)
return BadAlloc; return BadAlloc;
} }
rep = (xvmcCreateSubpictureReply) { xvmcCreateSubpictureReply rep = {
.type = X_Reply, .type = X_Reply,
.sequenceNumber = client->sequence, .sequenceNumber = client->sequence,
.length = dwords, .length = dwords,
@ -504,14 +503,11 @@ static int
ProcXvMCListSubpictureTypes(ClientPtr client) ProcXvMCListSubpictureTypes(ClientPtr client)
{ {
XvPortPtr pPort; XvPortPtr pPort;
xvmcListSubpictureTypesReply rep;
XvMCScreenPtr pScreenPriv; XvMCScreenPtr pScreenPriv;
ScreenPtr pScreen; ScreenPtr pScreen;
XvMCAdaptorPtr adaptor = NULL; XvMCAdaptorPtr adaptor = NULL;
XvMCSurfaceInfoPtr surface = NULL; XvMCSurfaceInfoPtr surface = NULL;
xvImageFormatInfo info;
XvImagePtr pImage; XvImagePtr pImage;
int i, j;
REQUEST(xvmcListSubpictureTypesReq); REQUEST(xvmcListSubpictureTypesReq);
REQUEST_SIZE_MATCH(xvmcListSubpictureTypesReq); REQUEST_SIZE_MATCH(xvmcListSubpictureTypesReq);
@ -526,7 +522,7 @@ ProcXvMCListSubpictureTypes(ClientPtr client)
if (!(pScreenPriv = XVMC_GET_PRIVATE(pScreen))) if (!(pScreenPriv = XVMC_GET_PRIVATE(pScreen)))
return BadMatch; /* None this screen */ return BadMatch; /* None this screen */
for (i = 0; i < pScreenPriv->num_adaptors; i++) { for (int i = 0; i < pScreenPriv->num_adaptors; i++) {
if (pPort->pAdaptor == pScreenPriv->adaptors[i].xv_adaptor) { if (pPort->pAdaptor == pScreenPriv->adaptors[i].xv_adaptor) {
adaptor = &(pScreenPriv->adaptors[i]); adaptor = &(pScreenPriv->adaptors[i]);
break; break;
@ -536,7 +532,7 @@ ProcXvMCListSubpictureTypes(ClientPtr client)
if (!adaptor) if (!adaptor)
return BadMatch; return BadMatch;
for (i = 0; i < adaptor->num_surfaces; i++) { for (int i = 0; i < adaptor->num_surfaces; i++) {
if (adaptor->surfaces[i]->surface_type_id == stuff->surface_type_id) { if (adaptor->surfaces[i]->surface_type_id == stuff->surface_type_id) {
surface = adaptor->surfaces[i]; surface = adaptor->surfaces[i];
break; break;
@ -546,62 +542,70 @@ ProcXvMCListSubpictureTypes(ClientPtr client)
if (!surface) if (!surface)
return BadMatch; return BadMatch;
rep = (xvmcListSubpictureTypesReply) { int num = (surface->compatible_subpictures ?
.type = X_Reply, surface->compatible_subpictures->num_xvimages : 0);
.sequenceNumber = client->sequence,
.num = 0
};
if (surface->compatible_subpictures)
rep.num = surface->compatible_subpictures->num_xvimages;
rep.length = bytes_to_int32(rep.num * sizeof(xvImageFormatInfo)); xvImageFormatInfo *info = NULL;
if (num) {
info = calloc(sizeof(xvImageFormatInfo), num);
if (!info)
return BadAlloc;
WriteToClient(client, sizeof(xvmcListSubpictureTypesReply), &rep); for (int i = 0; i < num; i++) {
for (i = 0; i < rep.num; i++) {
pImage = NULL; pImage = NULL;
for (j = 0; j < adaptor->num_subpictures; j++) { for (int j = 0; j < adaptor->num_subpictures; j++) {
if (surface->compatible_subpictures->xvimage_ids[i] == if (surface->compatible_subpictures->xvimage_ids[i] ==
adaptor->subpictures[j]->id) { adaptor->subpictures[j]->id) {
pImage = adaptor->subpictures[j]; pImage = adaptor->subpictures[j];
break; break;
} }
} }
if (!pImage) if (!pImage) {
free(info);
return BadImplementation; return BadImplementation;
info.id = pImage->id;
info.type = pImage->type;
info.byte_order = pImage->byte_order;
memcpy(&info.guid, pImage->guid, 16);
info.bpp = pImage->bits_per_pixel;
info.num_planes = pImage->num_planes;
info.depth = pImage->depth;
info.red_mask = pImage->red_mask;
info.green_mask = pImage->green_mask;
info.blue_mask = pImage->blue_mask;
info.format = pImage->format;
info.y_sample_bits = pImage->y_sample_bits;
info.u_sample_bits = pImage->u_sample_bits;
info.v_sample_bits = pImage->v_sample_bits;
info.horz_y_period = pImage->horz_y_period;
info.horz_u_period = pImage->horz_u_period;
info.horz_v_period = pImage->horz_v_period;
info.vert_y_period = pImage->vert_y_period;
info.vert_u_period = pImage->vert_u_period;
info.vert_v_period = pImage->vert_v_period;
memcpy(&info.comp_order, pImage->component_order, 32);
info.scanline_order = pImage->scanline_order;
WriteToClient(client, sizeof(xvImageFormatInfo), &info);
} }
info[i].id = pImage->id;
info[i].type = pImage->type;
info[i].byte_order = pImage->byte_order;
memcpy(&info[i].guid, pImage->guid, 16);
info[i].bpp = pImage->bits_per_pixel;
info[i].num_planes = pImage->num_planes;
info[i].depth = pImage->depth;
info[i].red_mask = pImage->red_mask;
info[i].green_mask = pImage->green_mask;
info[i].blue_mask = pImage->blue_mask;
info[i].format = pImage->format;
info[i].y_sample_bits = pImage->y_sample_bits;
info[i].u_sample_bits = pImage->u_sample_bits;
info[i].v_sample_bits = pImage->v_sample_bits;
info[i].horz_y_period = pImage->horz_y_period;
info[i].horz_u_period = pImage->horz_u_period;
info[i].horz_v_period = pImage->horz_v_period;
info[i].vert_y_period = pImage->vert_y_period;
info[i].vert_u_period = pImage->vert_u_period;
info[i].vert_v_period = pImage->vert_v_period;
memcpy(&info[i].comp_order, pImage->component_order, 32);
info[i].scanline_order = pImage->scanline_order;
}
}
xvmcListSubpictureTypesReply rep = {
.type = X_Reply,
.sequenceNumber = client->sequence,
.num = num,
.length = bytes_to_int32(sizeof(info)),
};
WriteToClient(client, sizeof(xvmcListSubpictureTypesReply), &rep);
WriteToClient(client, sizeof(xvImageFormatInfo) * num, info);
free(info);
return Success; return Success;
} }
static int static int
ProcXvMCGetDRInfo(ClientPtr client) ProcXvMCGetDRInfo(ClientPtr client)
{ {
xvmcGetDRInfoReply rep;
XvPortPtr pPort; XvPortPtr pPort;
ScreenPtr pScreen; ScreenPtr pScreen;
XvMCScreenPtr pScreenPriv; XvMCScreenPtr pScreenPriv;
@ -618,21 +622,30 @@ ProcXvMCGetDRInfo(ClientPtr client)
pScreen = pPort->pAdaptor->pScreen; pScreen = pPort->pAdaptor->pScreen;
pScreenPriv = XVMC_GET_PRIVATE(pScreen); pScreenPriv = XVMC_GET_PRIVATE(pScreen);
rep = (xvmcGetDRInfoReply) { int nameLen = strlen(pScreenPriv->clientDriverName) + 1;
int busIDLen = strlen(pScreenPriv->busID) + 1;
// buffer holds two zero-terminated strings, padded to 4-byte ints
const size_t buflen = pad_to_int32(nameLen+busIDLen);
char *buf = calloc(1, buflen);
if (!buf)
return BadAlloc;
memcpy(buf, pScreenPriv->clientDriverName, nameLen);
memcpy(buf+nameLen, pScreenPriv->busID, busIDLen);
xvmcGetDRInfoReply rep = {
.type = X_Reply, .type = X_Reply,
.sequenceNumber = client->sequence, .sequenceNumber = client->sequence,
.major = pScreenPriv->major, .major = pScreenPriv->major,
.minor = pScreenPriv->minor, .minor = pScreenPriv->minor,
.patchLevel = pScreenPriv->patchLevel, .patchLevel = pScreenPriv->patchLevel,
.nameLen = bytes_to_int32(strlen(pScreenPriv->clientDriverName) + 1), .nameLen = nameLen,
.busIDLen = bytes_to_int32(strlen(pScreenPriv->busID) + 1), .busIDLen = busIDLen,
.length = bytes_to_int32(sizeof(buf)),
.isLocal = 1 .isLocal = 1
}; };
rep.length = rep.nameLen + rep.busIDLen;
rep.nameLen <<= 2;
rep.busIDLen <<= 2;
/* /*
* Read back to the client what she has put in the shared memory * Read back to the client what she has put in the shared memory
* segment she prepared for us. * segment she prepared for us.
@ -660,34 +673,41 @@ ProcXvMCGetDRInfo(ClientPtr client)
#endif /* HAS_XVMCSHM */ #endif /* HAS_XVMCSHM */
WriteToClient(client, sizeof(xvmcGetDRInfoReply), &rep); WriteToClient(client, sizeof(xvmcGetDRInfoReply), &rep);
if (rep.length) { WriteToClient(client, buflen, buf);
WriteToClient(client, rep.nameLen, pScreenPriv->clientDriverName); free(buf);
WriteToClient(client, rep.busIDLen, pScreenPriv->busID);
}
return Success; return Success;
} }
int (*ProcXvMCVector[xvmcNumRequest]) (ClientPtr) = {
ProcXvMCQueryVersion,
ProcXvMCListSurfaceTypes,
ProcXvMCCreateContext,
ProcXvMCDestroyContext,
ProcXvMCCreateSurface,
ProcXvMCDestroySurface,
ProcXvMCCreateSubpicture,
ProcXvMCDestroySubpicture,
ProcXvMCListSubpictureTypes, ProcXvMCGetDRInfo};
static int static int
ProcXvMCDispatch(ClientPtr client) ProcXvMCDispatch(ClientPtr client)
{ {
REQUEST(xReq); REQUEST(xReq);
switch (stuff->data)
if (stuff->data < xvmcNumRequest) {
return (*ProcXvMCVector[stuff->data]) (client); case xvmc_QueryVersion:
else return ProcXvMCQueryVersion(client);
case xvmc_ListSurfaceTypes:
return ProcXvMCListSurfaceTypes(client);
case xvmc_CreateContext:
return ProcXvMCCreateContext(client);
case xvmc_DestroyContext:
return ProcXvMCDestroyContext(client);
case xvmc_CreateSurface:
return ProcXvMCCreateSurface(client);
case xvmc_DestroySurface:
return ProcXvMCDestroySurface(client);
case xvmc_CreateSubpicture:
return ProcXvMCCreateSubpicture(client);
case xvmc_DestroySubpicture:
return ProcXvMCDestroySubpicture(client);
case xvmc_ListSubpictureTypes:
return ProcXvMCListSubpictureTypes(client);
case xvmc_GetDRInfo:
return ProcXvMCGetDRInfo(client);
default:
return BadRequest; return BadRequest;
} }
}
static int _X_COLD static int _X_COLD
SProcXvMCDispatch(ClientPtr client) SProcXvMCDispatch(ClientPtr client)
@ -781,7 +801,6 @@ XvMCFindXvImage(XvPortPtr pPort, CARD32 id)
ScreenPtr pScreen = pPort->pAdaptor->pScreen; ScreenPtr pScreen = pPort->pAdaptor->pScreen;
XvMCScreenPtr pScreenPriv; XvMCScreenPtr pScreenPriv;
XvMCAdaptorPtr adaptor = NULL; XvMCAdaptorPtr adaptor = NULL;
int i;
if (!dixPrivateKeyRegistered(XvMCScreenKey)) if (!dixPrivateKeyRegistered(XvMCScreenKey))
return NULL; return NULL;
@ -789,7 +808,7 @@ XvMCFindXvImage(XvPortPtr pPort, CARD32 id)
if (!(pScreenPriv = XVMC_GET_PRIVATE(pScreen))) if (!(pScreenPriv = XVMC_GET_PRIVATE(pScreen)))
return NULL; return NULL;
for (i = 0; i < pScreenPriv->num_adaptors; i++) { for (int i = 0; i < pScreenPriv->num_adaptors; i++) {
if (pPort->pAdaptor == pScreenPriv->adaptors[i].xv_adaptor) { if (pPort->pAdaptor == pScreenPriv->adaptors[i].xv_adaptor) {
adaptor = &(pScreenPriv->adaptors[i]); adaptor = &(pScreenPriv->adaptors[i]);
break; break;
@ -799,7 +818,7 @@ XvMCFindXvImage(XvPortPtr pPort, CARD32 id)
if (!adaptor) if (!adaptor)
return NULL; return NULL;
for (i = 0; i < adaptor->num_subpictures; i++) { for (int i = 0; i < adaptor->num_subpictures; i++) {
if (adaptor->subpictures[i]->id == id) { if (adaptor->subpictures[i]->id == id) {
pImage = adaptor->subpictures[i]; pImage = adaptor->subpictures[i];
break; break;