diff options
Diffstat (limited to 'xorg-server/randr/rrscreen.c')
-rw-r--r-- | xorg-server/randr/rrscreen.c | 217 |
1 files changed, 198 insertions, 19 deletions
diff --git a/xorg-server/randr/rrscreen.c b/xorg-server/randr/rrscreen.c index c564d1f96..8d562108a 100644 --- a/xorg-server/randr/rrscreen.c +++ b/xorg-server/randr/rrscreen.c @@ -22,8 +22,6 @@ #include "randrstr.h" -static const int padlength[4] = { 0, 3, 2, 1 }; - static CARD16 RR10CurrentSizeID(ScreenPtr pScreen); @@ -46,8 +44,7 @@ RREditConnectionInfo(ScreenPtr pScreen) connSetup = (xConnSetup *) ConnectionInfo; vendor = (char *) connSetup + sizeof(xConnSetup); formats = (xPixmapFormat *) ((char *) vendor + - connSetup->nbytesVendor + - padlength[connSetup->nbytesVendor & 3]); + pad_to_int32(connSetup->nbytesVendor)); root = (xWindowRoot *) ((char *) formats + sizeof(xPixmapFormat) * screenInfo.numPixmapFormats); @@ -72,8 +69,6 @@ RRSendConfigNotify(ScreenPtr pScreen) { WindowPtr pWin = pScreen->root; xEvent event; - - event.u.u.type = ConfigureNotify; event.u.configureNotify.window = pWin->drawable.id; event.u.configureNotify.aboveSibling = None; event.u.configureNotify.x = 0; @@ -85,6 +80,7 @@ RRSendConfigNotify(ScreenPtr pScreen) event.u.configureNotify.height = pWin->drawable.height; event.u.configureNotify.borderWidth = wBorderWidth(pWin); event.u.configureNotify.override = pWin->overrideRedirect; + event.u.u.type = ConfigureNotify; DeliverEvents(pWin, &event, 1, NullWindow); } @@ -96,6 +92,7 @@ RRDeliverScreenEvent(ClientPtr client, WindowPtr pWin, ScreenPtr pScreen) RRCrtcPtr crtc = pScrPriv->numCrtcs ? pScrPriv->crtcs[0] : NULL; WindowPtr pRoot = pScreen->root; + se.type = RRScreenChangeNotify + RREventBase; se.rotation = (CARD8) (crtc ? crtc->rotation : RR_Rotate_0); se.timestamp = pScrPriv->lastSetTime.milliseconds; @@ -106,6 +103,7 @@ RRDeliverScreenEvent(ClientPtr client, WindowPtr pWin, ScreenPtr pScreen) se.sizeID = RR10CurrentSizeID(pScreen); + if (se.rotation & (RR_Rotate_90 | RR_Rotate_270)) { se.widthInPixels = pScreen->height; se.heightInPixels = pScreen->width; @@ -203,6 +201,7 @@ ProcRRGetScreenSizeRange(ClientPtr client) pScreen = pWin->drawable.pScreen; pScrPriv = rrGetScrPriv(pScreen); + rep.type = X_Reply; rep.pad = 0; rep.sequenceNumber = client->sequence; @@ -228,7 +227,7 @@ ProcRRGetScreenSizeRange(ClientPtr client) swaps(&rep.maxWidth); swaps(&rep.maxHeight); } - WriteToClient(client, sizeof(xRRGetScreenSizeRangeReply), (char *) &rep); + WriteToClient(client, sizeof(xRRGetScreenSizeRangeReply), &rep); return Success; } @@ -292,6 +291,172 @@ ProcRRSetScreenSize(ClientPtr client) return Success; } + +#define update_totals(gpuscreen, pScrPriv) do { \ + total_crtcs += pScrPriv->numCrtcs; \ + total_outputs += pScrPriv->numOutputs; \ + modes = RRModesForScreen(gpuscreen, &num_modes); \ + if (!modes) \ + return BadAlloc; \ + for (j = 0; j < num_modes; j++) \ + total_name_len += modes[j]->mode.nameLength; \ + total_modes += num_modes; \ + free(modes); \ +} while(0) + +static inline void swap_modeinfos(xRRModeInfo *modeinfos, int i) +{ + swapl(&modeinfos[i].id); + swaps(&modeinfos[i].width); + swaps(&modeinfos[i].height); + swapl(&modeinfos[i].dotClock); + swaps(&modeinfos[i].hSyncStart); + swaps(&modeinfos[i].hSyncEnd); + swaps(&modeinfos[i].hTotal); + swaps(&modeinfos[i].hSkew); + swaps(&modeinfos[i].vSyncStart); + swaps(&modeinfos[i].vSyncEnd); + swaps(&modeinfos[i].vTotal); + swaps(&modeinfos[i].nameLength); + swapl(&modeinfos[i].modeFlags); +} + +#define update_arrays(gpuscreen, pScrPriv) do { \ + for (j = 0; j < pScrPriv->numCrtcs; j++) { \ + crtcs[crtc_count] = pScrPriv->crtcs[j]->id; \ + if (client->swapped) \ + swapl(&crtcs[crtc_count]); \ + crtc_count++; \ + } \ + for (j = 0; j < pScrPriv->numOutputs; j++) { \ + outputs[output_count] = pScrPriv->outputs[j]->id; \ + if (client->swapped) \ + swapl(&outputs[output_count]); \ + output_count++; \ + } \ + { \ + RRModePtr mode; \ + modes = RRModesForScreen(gpuscreen, &num_modes); \ + for (j = 0; j < num_modes; j++) { \ + mode = modes[j]; \ + modeinfos[mode_count] = mode->mode; \ + if (client->swapped) { \ + swap_modeinfos(modeinfos, mode_count); \ + } \ + memcpy(names, mode->name, mode->mode.nameLength); \ + names += mode->mode.nameLength; \ + mode_count++; \ + } \ + free(modes); \ + } \ + } while (0) + +static int +rrGetMultiScreenResources(ClientPtr client, Bool query, ScreenPtr pScreen) +{ + int j; + int total_crtcs, total_outputs, total_modes, total_name_len; + int crtc_count, output_count, mode_count; + ScreenPtr iter; + rrScrPrivPtr pScrPriv; + int num_modes; + RRModePtr *modes; + xRRGetScreenResourcesReply rep; + unsigned long extraLen; + CARD8 *extra; + RRCrtc *crtcs; + RROutput *outputs; + xRRModeInfo *modeinfos; + CARD8 *names; + + /* we need to iterate all the GPU masters and all their output slaves */ + total_crtcs = 0; + total_outputs = 0; + total_modes = 0; + total_name_len = 0; + + pScrPriv = rrGetScrPriv(pScreen); + + if (query && pScrPriv) + if (!RRGetInfo(pScreen, query)) + return BadAlloc; + + update_totals(pScreen, pScrPriv); + + xorg_list_for_each_entry(iter, &pScreen->output_slave_list, output_head) { + pScrPriv = rrGetScrPriv(iter); + + if (query) + if (!RRGetInfo(iter, query)) + return BadAlloc; + update_totals(iter, pScrPriv); + } + + ErrorF("reporting %d %d %d %d\n", total_crtcs, total_outputs, total_modes, total_name_len); + + pScrPriv = rrGetScrPriv(pScreen); + rep.pad = 0; + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.timestamp = pScrPriv->lastSetTime.milliseconds; + rep.configTimestamp = pScrPriv->lastConfigTime.milliseconds; + rep.nCrtcs = total_crtcs; + rep.nOutputs = total_outputs; + rep.nModes = total_modes; + rep.nbytesNames = total_name_len; + + rep.length = (total_crtcs + total_outputs + total_modes * bytes_to_int32(SIZEOF(xRRModeInfo)) + + bytes_to_int32(rep.nbytesNames)); + + extraLen = rep.length << 2; + if (extraLen) { + extra = malloc(extraLen); + if (!extra) { + return BadAlloc; + } + } + else + extra = NULL; + + crtcs = (RRCrtc *)extra; + outputs = (RROutput *)(crtcs + total_crtcs); + modeinfos = (xRRModeInfo *)(outputs + total_outputs); + names = (CARD8 *)(modeinfos + total_modes); + + /* TODO primary */ + crtc_count = 0; + output_count = 0; + mode_count = 0; + + pScrPriv = rrGetScrPriv(pScreen); + update_arrays(pScreen, pScrPriv); + + xorg_list_for_each_entry(iter, &pScreen->output_slave_list, output_head) { + pScrPriv = rrGetScrPriv(iter); + + update_arrays(iter, pScrPriv); + } + + assert(bytes_to_int32((char *) names - (char *) extra) == rep.length); + if (client->swapped) { + swaps(&rep.sequenceNumber); + swapl(&rep.length); + swapl(&rep.timestamp); + swapl(&rep.configTimestamp); + swaps(&rep.nCrtcs); + swaps(&rep.nOutputs); + swaps(&rep.nModes); + swaps(&rep.nbytesNames); + } + WriteToClient(client, sizeof(xRRGetScreenResourcesReply), &rep); + if (extraLen) { + WriteToClient(client, extraLen, extra); + free(extra); + } + return Success; +} + static int rrGetScreenResources(ClientPtr client, Bool query) { @@ -321,7 +486,11 @@ rrGetScreenResources(ClientPtr client, Bool query) if (!RRGetInfo(pScreen, query)) return BadAlloc; + if (!xorg_list_is_empty(&pScreen->output_slave_list)) + return rrGetMultiScreenResources(client, query, pScreen); + if (!pScrPriv) { + rep.type = X_Reply; rep.sequenceNumber = client->sequence; rep.length = 0; @@ -331,6 +500,7 @@ rrGetScreenResources(ClientPtr client, Bool query) rep.nOutputs = 0; rep.nModes = 0; rep.nbytesNames = 0; + extra = NULL; extraLen = 0; } @@ -342,6 +512,7 @@ rrGetScreenResources(ClientPtr client, Bool query) if (!modes) return BadAlloc; + rep.type = X_Reply; rep.sequenceNumber = client->sequence; rep.length = 0; @@ -352,6 +523,7 @@ rrGetScreenResources(ClientPtr client, Bool query) rep.nModes = num_modes; rep.nbytesNames = 0; + for (i = 0; i < num_modes; i++) rep.nbytesNames += modes[i]->mode.nameLength; @@ -584,6 +756,7 @@ ProcRRGetScreenInfo(ClientPtr client) output = RRFirstOutput(pScreen); if (!pScrPriv || !output) { + rep.type = X_Reply; rep.setOfRotations = RR_Rotate_0; rep.sequenceNumber = client->sequence; @@ -596,6 +769,7 @@ ProcRRGetScreenInfo(ClientPtr client) rep.rotation = RR_Rotate_0; rep.rate = 0; rep.nrateEnts = 0; + extra = 0; extraLen = 0; } @@ -612,6 +786,7 @@ ProcRRGetScreenInfo(ClientPtr client) if (!pData) return BadAlloc; + rep.type = X_Reply; rep.setOfRotations = output->crtc->rotations; rep.sequenceNumber = client->sequence; @@ -685,15 +860,16 @@ ProcRRGetScreenInfo(ClientPtr client) swaps(&rep.sequenceNumber); swapl(&rep.length); swapl(&rep.timestamp); + swapl(&rep.configTimestamp); swaps(&rep.rotation); swaps(&rep.nSizes); swaps(&rep.sizeID); swaps(&rep.rate); swaps(&rep.nrateEnts); } - WriteToClient(client, sizeof(xRRGetScreenInfoReply), (char *) &rep); + WriteToClient(client, sizeof(xRRGetScreenInfoReply), &rep); if (extraLen) { - WriteToClient(client, extraLen, (char *) extra); + WriteToClient(client, extraLen, extra); free(extra); } return Success; @@ -713,6 +889,7 @@ ProcRRSetScreenConfig(ClientPtr client) Rotation rotation; int rate; Bool has_rate; + CARD8 status; RROutputPtr output; RRCrtcPtr crtc; RRModePtr mode; @@ -743,7 +920,7 @@ ProcRRSetScreenConfig(ClientPtr client) if (!pScrPriv) { time = currentTime; - rep.status = RRSetConfigFailed; + status = RRSetConfigFailed; goto sendReply; } if (!RRGetInfo(pScreen, FALSE)) @@ -752,7 +929,7 @@ ProcRRSetScreenConfig(ClientPtr client) output = RRFirstOutput(pScreen); if (!output) { time = currentTime; - rep.status = RRSetConfigFailed; + status = RRSetConfigFailed; goto sendReply; } @@ -768,7 +945,7 @@ ProcRRSetScreenConfig(ClientPtr client) * stop working after several hours have passed (freedesktop bug #6502). */ if (stuff->configTimestamp != pScrPriv->lastConfigTime.milliseconds) { - rep.status = RRSetConfigInvalidConfigTime; + status = RRSetConfigInvalidConfigTime; goto sendReply; } @@ -847,7 +1024,7 @@ ProcRRSetScreenConfig(ClientPtr client) * the last set-time */ if (CompareTimeStamps(time, pScrPriv->lastSetTime) < 0) { - rep.status = RRSetConfigInvalidTime; + status = RRSetConfigInvalidTime; goto sendReply; } @@ -879,24 +1056,24 @@ ProcRRSetScreenConfig(ClientPtr client) for (c = 0; c < pScrPriv->numCrtcs; c++) { if (!RRCrtcSet(pScrPriv->crtcs[c], NULL, 0, 0, RR_Rotate_0, 0, NULL)) { - rep.status = RRSetConfigFailed; + status = RRSetConfigFailed; /* XXX recover from failure */ goto sendReply; } } if (!RRScreenSizeSet(pScreen, width, height, pScreen->mmWidth, pScreen->mmHeight)) { - rep.status = RRSetConfigFailed; + status = RRSetConfigFailed; /* XXX recover from failure */ goto sendReply; } } if (!RRCrtcSet(crtc, mode, 0, 0, stuff->rotation, 1, &output)) - rep.status = RRSetConfigFailed; + status = RRSetConfigFailed; else { pScrPriv->lastSetTime = time; - rep.status = RRSetConfigSuccess; + status = RRSetConfigSuccess; } /* @@ -907,8 +1084,9 @@ ProcRRSetScreenConfig(ClientPtr client) free(pData); + rep.type = X_Reply; - /* rep.status has already been filled in */ + rep.status = status; rep.length = 0; rep.sequenceNumber = client->sequence; @@ -916,6 +1094,7 @@ ProcRRSetScreenConfig(ClientPtr client) rep.newConfigTimestamp = pScrPriv->lastConfigTime.milliseconds; rep.root = pDraw->pScreen->root->drawable.id; + if (client->swapped) { swaps(&rep.sequenceNumber); swapl(&rep.length); @@ -923,7 +1102,7 @@ ProcRRSetScreenConfig(ClientPtr client) swapl(&rep.newConfigTimestamp); swapl(&rep.root); } - WriteToClient(client, sizeof(xRRSetScreenConfigReply), (char *) &rep); + WriteToClient(client, sizeof(xRRSetScreenConfigReply), &rep); return Success; } |