diff options
Diffstat (limited to 'xorg-server/randr')
-rw-r--r-- | xorg-server/randr/Makefile.am | 2 | ||||
-rw-r--r-- | xorg-server/randr/makefile | 2 | ||||
-rw-r--r-- | xorg-server/randr/randr.c | 86 | ||||
-rw-r--r-- | xorg-server/randr/randrstr.h | 135 | ||||
-rw-r--r-- | xorg-server/randr/rrcrtc.c | 363 | ||||
-rw-r--r-- | xorg-server/randr/rrdispatch.c | 21 | ||||
-rw-r--r-- | xorg-server/randr/rrmode.c | 6 | ||||
-rw-r--r-- | xorg-server/randr/rroutput.c | 23 | ||||
-rw-r--r-- | xorg-server/randr/rrproperty.c | 30 | ||||
-rw-r--r-- | xorg-server/randr/rrprovider.c | 411 | ||||
-rw-r--r-- | xorg-server/randr/rrproviderproperty.c | 716 | ||||
-rw-r--r-- | xorg-server/randr/rrscreen.c | 217 | ||||
-rw-r--r-- | xorg-server/randr/rrxinerama.c | 44 |
13 files changed, 1933 insertions, 123 deletions
diff --git a/xorg-server/randr/Makefile.am b/xorg-server/randr/Makefile.am index de338b972..ccaff3f02 100644 --- a/xorg-server/randr/Makefile.am +++ b/xorg-server/randr/Makefile.am @@ -18,6 +18,8 @@ librandr_la_SOURCES = \ rroutput.c \ rrpointer.c \ rrproperty.c \ + rrprovider.c \ + rrproviderproperty.c \ rrscreen.c \ rrsdispatch.c \ rrtransform.h \ diff --git a/xorg-server/randr/makefile b/xorg-server/randr/makefile index 8dac78b7f..9f32cf77d 100644 --- a/xorg-server/randr/makefile +++ b/xorg-server/randr/makefile @@ -13,6 +13,8 @@ librandr_la_SOURCES = \ rroutput.c \
rrpointer.c \
rrproperty.c \
+ rrprovider.c \
+ rrproviderproperty.c \
rrscreen.c \
rrsdispatch.c \
rrtransform.h \
diff --git a/xorg-server/randr/randr.c b/xorg-server/randr/randr.c index 103da48d7..da48c3f06 100644 --- a/xorg-server/randr/randr.c +++ b/xorg-server/randr/randr.c @@ -30,6 +30,7 @@ #endif #include "randrstr.h" +#include "extinit.h" /* From render.h */ #ifndef SubPixelUnknown @@ -94,6 +95,9 @@ RRCloseScreen(ScreenPtr pScreen) for (j = pScrPriv->numOutputs - 1; j >= 0; j--) RROutputDestroy(pScrPriv->outputs[j]); + if (pScrPriv->provider) + RRProviderDestroy(pScrPriv->provider); + free(pScrPriv->crtcs); free(pScrPriv->outputs); free(pScrPriv); @@ -176,6 +180,47 @@ SRROutputPropertyNotifyEvent(xRROutputPropertyNotifyEvent * from, } static void +SRRProviderChangeNotifyEvent(xRRProviderChangeNotifyEvent * from, + xRRProviderChangeNotifyEvent * to) +{ + to->type = from->type; + to->subCode = from->subCode; + cpswaps(from->sequenceNumber, to->sequenceNumber); + cpswapl(from->timestamp, to->timestamp); + cpswapl(from->window, to->window); + cpswapl(from->provider, to->provider); +} + +static void +SRRProviderPropertyNotifyEvent(xRRProviderPropertyNotifyEvent * from, + xRRProviderPropertyNotifyEvent * to) +{ + to->type = from->type; + to->subCode = from->subCode; + cpswaps(from->sequenceNumber, to->sequenceNumber); + cpswapl(from->window, to->window); + cpswapl(from->provider, to->provider); + cpswapl(from->atom, to->atom); + cpswapl(from->timestamp, to->timestamp); + to->state = from->state; + /* pad1 */ + /* pad2 */ + /* pad3 */ + /* pad4 */ +} + +static void +SRRResourceChangeNotifyEvent(xRRResourceChangeNotifyEvent * from, + xRRResourceChangeNotifyEvent * to) +{ + to->type = from->type; + to->subCode = from->subCode; + cpswaps(from->sequenceNumber, to->sequenceNumber); + cpswapl(from->timestamp, to->timestamp); + cpswapl(from->window, to->window); +} + +static void SRRNotifyEvent(xEvent *from, xEvent *to) { switch (from->u.u.detail) { @@ -191,6 +236,17 @@ SRRNotifyEvent(xEvent *from, xEvent *to) SRROutputPropertyNotifyEvent((xRROutputPropertyNotifyEvent *) from, (xRROutputPropertyNotifyEvent *) to); break; + case RRNotify_ProviderChange: + SRRProviderChangeNotifyEvent((xRRProviderChangeNotifyEvent *) from, + (xRRProviderChangeNotifyEvent *) to); + break; + case RRNotify_ProviderProperty: + SRRProviderPropertyNotifyEvent((xRRProviderPropertyNotifyEvent *) from, + (xRRProviderPropertyNotifyEvent *) to); + break; + case RRNotify_ResourceChange: + SRRResourceChangeNotifyEvent((xRRResourceChangeNotifyEvent *) from, + (xRRResourceChangeNotifyEvent *) to); default: break; } @@ -269,7 +325,7 @@ RRScreenInit(ScreenPtr pScreen) wrap(pScrPriv, pScreen, CloseScreen, RRCloseScreen); pScreen->ConstrainCursorHarder = RRConstrainCursorHarder; - + pScreen->ReplaceScanoutPixmap = RRReplaceScanoutPixmap; pScrPriv->numOutputs = 0; pScrPriv->outputs = NULL; pScrPriv->numCrtcs = 0; @@ -356,7 +412,7 @@ RRExtensionInit(void) RRModeInitErrorValue(); RRCrtcInitErrorValue(); RROutputInitErrorValue(); - + RRProviderInitErrorValue(); #ifdef PANORAMIX RRXineramaExtensionInit(); #endif @@ -412,25 +468,37 @@ TellChanged(WindowPtr pWin, pointer value) void RRTellChanged(ScreenPtr pScreen) { + ScreenPtr master; rrScrPriv(pScreen); + rrScrPrivPtr mastersp; int i; + if (pScreen->isGPU) { + master = pScreen->current_master; + mastersp = rrGetScrPriv(master); + } + else { + master = pScreen; + mastersp = pScrPriv; + } + if (pScrPriv->changed) { UpdateCurrentTimeIf(); - if (pScrPriv->configChanged) { - pScrPriv->lastConfigTime = currentTime; - pScrPriv->configChanged = FALSE; + if (mastersp->configChanged) { + mastersp->lastConfigTime = currentTime; + mastersp->configChanged = FALSE; } pScrPriv->changed = FALSE; - WalkTree(pScreen, TellChanged, (pointer) pScreen); + mastersp->changed = FALSE; + WalkTree(master, TellChanged, (pointer) master); for (i = 0; i < pScrPriv->numOutputs; i++) pScrPriv->outputs[i]->changed = FALSE; for (i = 0; i < pScrPriv->numCrtcs; i++) pScrPriv->crtcs[i]->changed = FALSE; - if (pScrPriv->layoutChanged) { + if (mastersp->layoutChanged) { pScrPriv->layoutChanged = FALSE; - RRPointerScreenConfigured(pScreen); - RRSendConfigNotify(pScreen); + RRPointerScreenConfigured(master); + RRSendConfigNotify(master); } } } diff --git a/xorg-server/randr/randrstr.h b/xorg-server/randr/randrstr.h index 38fb10751..212b0a9be 100644 --- a/xorg-server/randr/randrstr.h +++ b/xorg-server/randr/randrstr.h @@ -62,6 +62,7 @@ typedef XID RRMode; typedef XID RROutput; typedef XID RRCrtc; +typedef XID RRProvider; extern _X_EXPORT int RREventBase, RRErrorBase; @@ -78,6 +79,7 @@ typedef struct _rrPropertyValue RRPropertyValueRec, *RRPropertyValuePtr; typedef struct _rrProperty RRPropertyRec, *RRPropertyPtr; typedef struct _rrCrtc RRCrtcRec, *RRCrtcPtr; typedef struct _rrOutput RROutputRec, *RROutputPtr; +typedef struct _rrProvider RRProviderRec, *RRProviderPtr; struct _rrMode { int refcnt; @@ -125,6 +127,8 @@ struct _rrCrtc { PictTransform transform; struct pict_f_transform f_transform; struct pict_f_transform f_inverse; + + PixmapPtr scanout_pixmap; }; struct _rrOutput { @@ -152,6 +156,18 @@ struct _rrOutput { void *devPrivate; }; +struct _rrProvider { + RRProvider id; + ScreenPtr pScreen; + uint32_t capabilities; + char *name; + int nameLength; + RRPropertyPtr properties; + Bool pendingProperties; + struct _rrProvider *offload_sink; + struct _rrProvider *output_source; +}; + #if RANDR_12_INTERFACE typedef Bool (*RRScreenSetSizeProcPtr) (ScreenPtr pScreen, CARD16 width, @@ -197,9 +213,25 @@ typedef Bool (*RRSetPanningProcPtr) (ScreenPtr pScrn, #endif /* RANDR_13_INTERFACE */ +typedef Bool (*RRProviderGetPropertyProcPtr) (ScreenPtr pScreen, + RRProviderPtr provider, Atom property); +typedef Bool (*RRProviderSetPropertyProcPtr) (ScreenPtr pScreen, + RRProviderPtr provider, + Atom property, + RRPropertyValuePtr value); + typedef Bool (*RRGetInfoProcPtr) (ScreenPtr pScreen, Rotation * rotations); typedef Bool (*RRCloseScreenProcPtr) (ScreenPtr pscreen); +typedef Bool (*RRProviderSetOutputSourceProcPtr)(ScreenPtr pScreen, + RRProviderPtr provider, + RRProviderPtr output_source); + +typedef Bool (*RRProviderSetOffloadSinkProcPtr)(ScreenPtr pScreen, + RRProviderPtr provider, + RRProviderPtr offload_sink); + + /* These are for 1.0 compatibility */ typedef struct _rrRefresh { @@ -223,6 +255,8 @@ typedef Bool (*RRSetConfigProcPtr) (ScreenPtr pScreen, #endif +typedef Bool (*RRCrtcSetScanoutPixmapProcPtr)(RRCrtcPtr crtc, PixmapPtr pixmap); + typedef struct _rrScrPriv { /* * 'public' part of the structure; DDXen fill this in @@ -246,7 +280,13 @@ typedef struct _rrScrPriv { RRGetPanningProcPtr rrGetPanning; RRSetPanningProcPtr rrSetPanning; #endif + /* TODO #if RANDR_15_INTERFACE */ + RRCrtcSetScanoutPixmapProcPtr rrCrtcSetScanoutPixmap; + RRProviderSetOutputSourceProcPtr rrProviderSetOutputSource; + RRProviderSetOffloadSinkProcPtr rrProviderSetOffloadSink; + RRProviderGetPropertyProcPtr rrProviderGetProperty; + RRProviderSetPropertyProcPtr rrProviderSetProperty; /* * Private part of the structure; not considered part of the ABI */ @@ -288,6 +328,8 @@ typedef struct _rrScrPriv { int size; #endif Bool discontiguous; + + RRProviderPtr provider; } rrScrPrivRec, *rrScrPrivPtr; extern _X_EXPORT DevPrivateKeyRec rrPrivKeyRec; @@ -331,7 +373,7 @@ extern _X_EXPORT RESTYPE RRClientType, RREventType; /* resource types for ev extern _X_EXPORT DevPrivateKeyRec RRClientPrivateKeyRec; #define RRClientPrivateKey (&RRClientPrivateKeyRec) -extern _X_EXPORT RESTYPE RRCrtcType, RRModeType, RROutputType; +extern _X_EXPORT RESTYPE RRCrtcType, RRModeType, RROutputType, RRProviderType; #define VERIFY_RR_OUTPUT(id, ptr, a)\ {\ @@ -363,13 +405,19 @@ extern _X_EXPORT RESTYPE RRCrtcType, RRModeType, RROutputType; }\ } +#define VERIFY_RR_PROVIDER(id, ptr, a)\ + {\ + int rc = dixLookupResourceByType((pointer *)&(ptr), id,\ + RRProviderType, client, a);\ + if (rc != Success) {\ + client->errorValue = id;\ + return rc;\ + }\ + } + #define GetRRClient(pClient) ((RRClientPtr)dixLookupPrivate(&(pClient)->devPrivates, RRClientPrivateKey)) #define rrClientPriv(pClient) RRClientPtr pRRClient = GetRRClient(pClient) -/* Initialize the extension */ -extern _X_EXPORT void - RRExtensionInit(void); - #ifdef RANDR_12_INTERFACE /* * Set the range of sizes for the screen @@ -616,6 +664,15 @@ extern _X_EXPORT void RRCrtcInitErrorValue(void); /* + * Detach and free a scanout pixmap + */ +extern _X_EXPORT void + RRCrtcDetachScanoutPixmap(RRCrtcPtr crtc); + +extern _X_EXPORT Bool + RRReplaceScanoutPixmap(DrawablePtr pDrawable, PixmapPtr pPixmap, Bool enable); + +/* * Crtc dispatch */ @@ -824,6 +881,74 @@ extern _X_EXPORT int extern _X_EXPORT int ProcRRDeleteOutputProperty(ClientPtr client); +/* rrprovider.c */ +extern _X_EXPORT void +RRProviderInitErrorValue(void); + +extern _X_EXPORT int +ProcRRGetProviders(ClientPtr client); + +extern _X_EXPORT int +ProcRRGetProviderInfo(ClientPtr client); + +extern _X_EXPORT int +ProcRRSetProviderOutputSource(ClientPtr client); + +extern _X_EXPORT int +ProcRRSetProviderOffloadSink(ClientPtr client); + +extern _X_EXPORT Bool +RRProviderInit(void); + +extern _X_EXPORT RRProviderPtr +RRProviderCreate(ScreenPtr pScreen, const char *name, + int nameLength); + +extern _X_EXPORT void +RRProviderDestroy (RRProviderPtr provider); + +extern _X_EXPORT void +RRProviderSetCapabilities(RRProviderPtr provider, uint32_t capabilities); + +extern _X_EXPORT Bool +RRProviderLookup(XID id, RRProviderPtr *provider_p); + +/* rrproviderproperty.c */ + +extern _X_EXPORT void + RRDeleteAllProviderProperties(RRProviderPtr provider); + +extern _X_EXPORT RRPropertyValuePtr + RRGetProviderProperty(RRProviderPtr provider, Atom property, Bool pending); + +extern _X_EXPORT RRPropertyPtr + RRQueryProviderProperty(RRProviderPtr provider, Atom property); + +extern _X_EXPORT void + RRDeleteProviderProperty(RRProviderPtr provider, Atom property); + +extern _X_EXPORT int +RRChangeProviderProperty(RRProviderPtr provider, Atom property, Atom type, + int format, int mode, unsigned long len, + pointer value, Bool sendevent, Bool pending); + +extern _X_EXPORT int + ProcRRGetProviderProperty(ClientPtr client); + +extern _X_EXPORT int + ProcRRListProviderProperties(ClientPtr client); + +extern _X_EXPORT int + ProcRRQueryProviderProperty(ClientPtr client); + +extern _X_EXPORT int +ProcRRConfigureProviderProperty(ClientPtr client); + +extern _X_EXPORT int +ProcRRChangeProviderProperty(ClientPtr client); + +extern _X_EXPORT int + ProcRRDeleteProviderProperty(ClientPtr client); /* rrxinerama.c */ #ifdef XINERAMA extern _X_EXPORT void diff --git a/xorg-server/randr/rrcrtc.c b/xorg-server/randr/rrcrtc.c index 0c596dd4c..859d19efe 100644 --- a/xorg-server/randr/rrcrtc.c +++ b/xorg-server/randr/rrcrtc.c @@ -239,26 +239,19 @@ RRDeliverCrtcEvent(ClientPtr client, WindowPtr pWin, RRCrtcPtr crtc) xRRCrtcChangeNotifyEvent ce; RRModePtr mode = crtc->mode; + ce.type = RRNotify + RREventBase; ce.subCode = RRNotify_CrtcChange; ce.timestamp = pScrPriv->lastSetTime.milliseconds; ce.window = pWin->drawable.id; ce.crtc = crtc->id; + ce.mode = mode ? mode->mode.id : None; ce.rotation = crtc->rotation; - if (mode) { - ce.mode = mode->mode.id; - ce.x = crtc->x; - ce.y = crtc->y; - ce.width = mode->mode.width; - ce.height = mode->mode.height; - } - else { - ce.mode = None; - ce.x = 0; - ce.y = 0; - ce.width = 0; - ce.height = 0; - } + ce.x = mode ? crtc->x : 0; + ce.y = mode ? crtc->y : 0; + ce.width = mode ? mode->mode.width : 0; + ce.height = mode ? mode->mode.height : 0; + WriteEventsToClient(client, 1, (xEvent *) &ce); } @@ -367,6 +360,154 @@ RRComputeContiguity(ScreenPtr pScreen) pScrPriv->discontiguous = discontiguous; } +void +RRCrtcDetachScanoutPixmap(RRCrtcPtr crtc) +{ + ScreenPtr master = crtc->pScreen->current_master; + int ret; + PixmapPtr mscreenpix; + rrScrPriv(crtc->pScreen); + + mscreenpix = master->GetScreenPixmap(master); + + ret = pScrPriv->rrCrtcSetScanoutPixmap(crtc, NULL); + if (crtc->scanout_pixmap) { + master->StopPixmapTracking(mscreenpix, crtc->scanout_pixmap); + master->DestroyPixmap(crtc->scanout_pixmap->master_pixmap); + crtc->pScreen->DestroyPixmap(crtc->scanout_pixmap); + } + crtc->scanout_pixmap = NULL; + RRCrtcChanged(crtc, TRUE); +} + +static Bool +rrCreateSharedPixmap(RRCrtcPtr crtc, int width, int height, + int x, int y) +{ + PixmapPtr mpix, spix; + ScreenPtr master = crtc->pScreen->current_master; + Bool ret; + int depth; + PixmapPtr mscreenpix; + PixmapPtr protopix = crtc->pScreen->current_master->GetScreenPixmap(crtc->pScreen->current_master); + rrScrPriv(crtc->pScreen); + + /* create a pixmap on the master screen, + then get a shared handle for it + create a shared pixmap on the slave screen using the handle + set the master screen to do dirty updates to the shared pixmap + from the screen pixmap. + set slave screen to scanout shared linear pixmap + */ + + mscreenpix = master->GetScreenPixmap(master); + depth = protopix->drawable.depth; + + if (crtc->scanout_pixmap) + RRCrtcDetachScanoutPixmap(crtc); + + if (width == 0 && height == 0) { + return TRUE; + } + + mpix = master->CreatePixmap(master, width, height, depth, + CREATE_PIXMAP_USAGE_SHARED); + if (!mpix) + return FALSE; + + spix = PixmapShareToSlave(mpix, crtc->pScreen); + if (spix == NULL) { + master->DestroyPixmap(mpix); + return FALSE; + } + + ret = pScrPriv->rrCrtcSetScanoutPixmap(crtc, spix); + if (ret == FALSE) { + ErrorF("failed to set shadow slave pixmap\n"); + return FALSE; + } + + crtc->scanout_pixmap = spix; + + master->StartPixmapTracking(mscreenpix, spix, x, y); + return TRUE; +} + +static Bool +rrCheckPixmapBounding(ScreenPtr pScreen, + RRCrtcPtr rr_crtc, int x, int y, int w, int h) +{ + RegionRec root_pixmap_region, total_region, new_crtc_region; + int i, c; + BoxRec newbox; + BoxPtr newsize; + ScreenPtr slave; + int new_width, new_height; + PixmapPtr screen_pixmap = pScreen->GetScreenPixmap(pScreen); + rrScrPriv(pScreen); + + PixmapRegionInit(&root_pixmap_region, screen_pixmap); + RegionInit(&total_region, NULL, 0); + + /* have to iterate all the crtcs of the attached gpu masters + and all their output slaves */ + for (c = 0; c < pScrPriv->numCrtcs; c++) { + if (pScrPriv->crtcs[c] == rr_crtc) { + newbox.x1 = x; + newbox.x2 = x + w; + newbox.y1 = y; + newbox.y2 = y + h; + } else { + if (!pScrPriv->crtcs[c]->mode) + continue; + newbox.x1 = pScrPriv->crtcs[c]->x; + newbox.x2 = pScrPriv->crtcs[c]->x + pScrPriv->crtcs[c]->mode->mode.width; + newbox.y1 = pScrPriv->crtcs[c]->y; + newbox.y2 = pScrPriv->crtcs[c]->y + pScrPriv->crtcs[c]->mode->mode.height; + } + RegionInit(&new_crtc_region, &newbox, 1); + RegionUnion(&total_region, &total_region, &new_crtc_region); + } + + xorg_list_for_each_entry(slave, &pScreen->output_slave_list, output_head) { + rrScrPriv(slave); + for (c = 0; c < pScrPriv->numCrtcs; c++) + if (pScrPriv->crtcs[c] == rr_crtc) { + newbox.x1 = x; + newbox.x2 = x + w; + newbox.y1 = y; + newbox.y2 = y + h; + } + else { + if (!pScrPriv->crtcs[c]->mode) + continue; + newbox.x1 = pScrPriv->crtcs[c]->x; + newbox.x2 = pScrPriv->crtcs[c]->x + pScrPriv->crtcs[c]->mode->mode.width; + newbox.y1 = pScrPriv->crtcs[c]->y; + newbox.y2 = pScrPriv->crtcs[c]->y + pScrPriv->crtcs[c]->mode->mode.height; + } + RegionInit(&new_crtc_region, &newbox, 1); + RegionUnion(&total_region, &total_region, &new_crtc_region); + } + + newsize = RegionExtents(&total_region); + new_width = newsize->x2 - newsize->x1; + new_height = newsize->y2 - newsize->y1; + + if (new_width == screen_pixmap->drawable.width && + new_height == screen_pixmap->drawable.height) { + ErrorF("adjust shatters %d %d\n", newsize->x1, newsize->x2); + } else { + int ret; + rrScrPriv(pScreen); + ret = pScrPriv->rrScreenSetSize(pScreen, + new_width, new_height, 0, 0); + } + + /* set shatters TODO */ + return TRUE; +} + /* * Request that the Crtc be reconfigured */ @@ -394,6 +535,26 @@ RRCrtcSet(RRCrtcPtr crtc, ret = TRUE; } else { + if (pScreen->isGPU) { + ScreenPtr master = pScreen->current_master; + int width = 0, height = 0; + + if (mode) { + width = mode->mode.width; + height = mode->mode.height; + } + ErrorF("have a master to look out for\n"); + ret = rrCheckPixmapBounding(master, crtc, + x, y, width, height); + if (!ret) + return FALSE; + + if (pScreen->current_master) { + ret = rrCreateSharedPixmap(crtc, width, height, x, y); + ErrorF("need to create shared pixmap %d", ret); + + } + } #if RANDR_12_INTERFACE if (pScrPriv->rrCrtcSet) { ret = (*pScrPriv->rrCrtcSet) (pScreen, crtc, mode, x, y, @@ -508,6 +669,9 @@ RRCrtcDestroyResource(pointer value, XID pid) } } } + + if (crtc->scanout_pixmap) + RRCrtcDetachScanoutPixmap(crtc); free(crtc->gammaRed); if (crtc->mode) RRModeDestroy(crtc->mode); @@ -729,11 +893,13 @@ ProcRRGetCrtcInfo(ClientPtr client) mode = crtc->mode; + rep.type = X_Reply; rep.status = RRSetConfigSuccess; rep.sequenceNumber = client->sequence; rep.length = 0; rep.timestamp = pScrPriv->lastSetTime.milliseconds; + if (pScrPriv->rrGetPanning && pScrPriv->rrGetPanning(pScreen, crtc, &panned_area, NULL, NULL) && (panned_area.x2 > panned_area.x1) && (panned_area.y2 > panned_area.y1)) @@ -804,9 +970,9 @@ ProcRRGetCrtcInfo(ClientPtr client) swaps(&rep.nOutput); swaps(&rep.nPossibleOutput); } - WriteToClient(client, sizeof(xRRGetCrtcInfoReply), (char *) &rep); + WriteToClient(client, sizeof(xRRGetCrtcInfoReply), &rep); if (extraLen) { - WriteToClient(client, extraLen, (char *) extra); + WriteToClient(client, extraLen, extra); free(extra); } @@ -828,6 +994,7 @@ ProcRRSetCrtcConfig(ClientPtr client) TimeStamp time; Rotation rotation; int ret, i, j; + CARD8 status; REQUEST_AT_LEAST_SIZE(xRRSetCrtcConfigReq); numOutputs = (stuff->length - bytes_to_int32(SIZEOF(xRRSetCrtcConfigReq))); @@ -906,7 +1073,7 @@ ProcRRSetCrtcConfig(ClientPtr client) if (!pScrPriv) { time = currentTime; - rep.status = RRSetConfigFailed; + status = RRSetConfigFailed; goto sendReply; } @@ -954,6 +1121,16 @@ ProcRRSetCrtcConfig(ClientPtr client) int source_height; PictTransform transform; struct pixman_f_transform f_transform, f_inverse; + int width, height; + + if (pScreen->isGPU) { + width = pScreen->current_master->width; + height = pScreen->current_master->height; + } + else { + width = pScreen->width; + height = pScreen->height; + } RRTransformCompute(stuff->x, stuff->y, mode->mode.width, mode->mode.height, @@ -963,13 +1140,13 @@ ProcRRSetCrtcConfig(ClientPtr client) RRModeGetScanoutSize(mode, &transform, &source_width, &source_height); - if (stuff->x + source_width > pScreen->width) { + if (stuff->x + source_width > width) { client->errorValue = stuff->x; free(outputs); return BadValue; } - if (stuff->y + source_height > pScreen->height) { + if (stuff->y + source_height > height) { client->errorValue = stuff->y; free(outputs); return BadValue; @@ -980,19 +1157,20 @@ ProcRRSetCrtcConfig(ClientPtr client) if (!RRCrtcSet(crtc, mode, stuff->x, stuff->y, rotation, numOutputs, outputs)) { - rep.status = RRSetConfigFailed; + status = RRSetConfigFailed; goto sendReply; } - rep.status = RRSetConfigSuccess; + status = RRSetConfigSuccess; pScrPriv->lastSetTime = time; sendReply: free(outputs); + rep.type = X_Reply; - /* rep.status has already been filled in */ - rep.length = 0; + rep.status = status; rep.sequenceNumber = client->sequence; + rep.length = 0; rep.newTimestamp = pScrPriv->lastSetTime.milliseconds; if (client->swapped) { @@ -1000,7 +1178,7 @@ ProcRRSetCrtcConfig(ClientPtr client) swapl(&rep.length); swapl(&rep.newTimestamp); } - WriteToClient(client, sizeof(xRRSetCrtcConfigReply), (char *) &rep); + WriteToClient(client, sizeof(xRRSetCrtcConfigReply), &rep); return Success; } @@ -1069,7 +1247,7 @@ ProcRRGetPanning(ClientPtr client) swaps(&rep.border_right); swaps(&rep.border_bottom); } - WriteToClient(client, sizeof(xRRGetPanningReply), (char *) &rep); + WriteToClient(client, sizeof(xRRGetPanningReply), &rep); return Success; } @@ -1085,6 +1263,7 @@ ProcRRSetPanning(ClientPtr client) BoxRec total; BoxRec tracking; INT16 border[4]; + CARD8 status; REQUEST_SIZE_MATCH(xRRSetPanningReq); VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess); @@ -1097,7 +1276,7 @@ ProcRRSetPanning(ClientPtr client) if (!pScrPriv) { time = currentTime; - rep.status = RRSetConfigFailed; + status = RRSetConfigFailed; goto sendReply; } @@ -1124,10 +1303,12 @@ ProcRRSetPanning(ClientPtr client) pScrPriv->lastSetTime = time; - rep.status = RRSetConfigSuccess; + status = RRSetConfigSuccess; sendReply: + rep.type = X_Reply; + rep.status = status; rep.sequenceNumber = client->sequence; rep.length = 0; rep.newTimestamp = pScrPriv->lastSetTime.milliseconds; @@ -1137,7 +1318,7 @@ ProcRRSetPanning(ClientPtr client) swapl(&rep.length); swapl(&rep.newTimestamp); } - WriteToClient(client, sizeof(xRRSetPanningReply), (char *) &rep); + WriteToClient(client, sizeof(xRRSetPanningReply), &rep); return Success; } @@ -1155,16 +1336,18 @@ ProcRRGetCrtcGammaSize(ClientPtr client) if (!RRCrtcGammaGet(crtc)) return RRErrorBase + BadRRCrtc; + reply.type = X_Reply; reply.sequenceNumber = client->sequence; reply.length = 0; reply.size = crtc->gammaSize; + if (client->swapped) { swaps(&reply.sequenceNumber); swapl(&reply.length); swaps(&reply.size); } - WriteToClient(client, sizeof(xRRGetCrtcGammaSizeReply), (char *) &reply); + WriteToClient(client, sizeof(xRRGetCrtcGammaSizeReply), &reply); return Success; } @@ -1192,16 +1375,18 @@ ProcRRGetCrtcGamma(ClientPtr client) return BadAlloc; } + reply.type = X_Reply; reply.sequenceNumber = client->sequence; reply.length = bytes_to_int32(len); reply.size = crtc->gammaSize; + if (client->swapped) { swaps(&reply.sequenceNumber); swapl(&reply.length); swaps(&reply.size); } - WriteToClient(client, sizeof(xRRGetCrtcGammaReply), (char *) &reply); + WriteToClient(client, sizeof(xRRGetCrtcGammaReply), &reply); if (crtc->gammaSize) { memcpy(extra, crtc->gammaRed, len); client->pSwapReplyFunc = (ReplySwapPtr) CopySwap16Write; @@ -1342,7 +1527,7 @@ ProcRRGetCrtcTransform(ClientPtr client) nextra = (transform_filter_length(pending) + transform_filter_length(current)); - reply = malloc(sizeof(xRRGetCrtcTransformReply) + nextra); + reply = calloc(1, sizeof(xRRGetCrtcTransformReply) + nextra); if (!reply) return BadAlloc; @@ -1367,24 +1552,15 @@ ProcRRGetCrtcTransform(ClientPtr client) swaps(&reply->sequenceNumber); swapl(&reply->length); } - WriteToClient(client, sizeof(xRRGetCrtcTransformReply) + nextra, - (char *) reply); + WriteToClient(client, sizeof(xRRGetCrtcTransformReply) + nextra, reply); free(reply); return Success; } -void -RRConstrainCursorHarder(DeviceIntPtr pDev, ScreenPtr pScreen, int mode, int *x, - int *y) +static Bool check_all_screen_crtcs(ScreenPtr pScreen, int *x, int *y) { rrScrPriv(pScreen); int i; - - /* intentional dead space -> let it float */ - if (pScrPriv->discontiguous) - return; - - /* if we're moving inside a crtc, we're fine */ for (i = 0; i < pScrPriv->numCrtcs; i++) { RRCrtcPtr crtc = pScrPriv->crtcs[i]; @@ -1396,8 +1572,15 @@ RRConstrainCursorHarder(DeviceIntPtr pDev, ScreenPtr pScreen, int mode, int *x, crtc_bounds(crtc, &left, &right, &top, &bottom); if ((*x >= left) && (*x < right) && (*y >= top) && (*y < bottom)) - return; + return TRUE; } + return FALSE; +} + +static Bool constrain_all_screen_crtcs(DeviceIntPtr pDev, ScreenPtr pScreen, int *x, int *y) +{ + rrScrPriv(pScreen); + int i; /* if we're trying to escape, clamp to the CRTC we're coming from */ for (i = 0; i < pScrPriv->numCrtcs; i++) { @@ -1421,7 +1604,101 @@ RRConstrainCursorHarder(DeviceIntPtr pDev, ScreenPtr pScreen, int mode, int *x, if (*y >= bottom) *y = bottom - 1; + return TRUE; + } + } + return FALSE; +} + +void +RRConstrainCursorHarder(DeviceIntPtr pDev, ScreenPtr pScreen, int mode, int *x, + int *y) +{ + rrScrPriv(pScreen); + Bool ret; + ScreenPtr slave; + + /* intentional dead space -> let it float */ + if (pScrPriv->discontiguous) + return; + + /* if we're moving inside a crtc, we're fine */ + ret = check_all_screen_crtcs(pScreen, x, y); + if (ret == TRUE) + return; + + xorg_list_for_each_entry(slave, &pScreen->output_slave_list, output_head) { + ret = check_all_screen_crtcs(slave, x, y); + if (ret == TRUE) return; + } + + /* if we're trying to escape, clamp to the CRTC we're coming from */ + ret = constrain_all_screen_crtcs(pDev, pScreen, x, y); + if (ret == TRUE) + return; + + xorg_list_for_each_entry(slave, &pScreen->output_slave_list, output_head) { + ret = constrain_all_screen_crtcs(pDev, slave, x, y); + if (ret == TRUE) + return; + } +} + +Bool +RRReplaceScanoutPixmap(DrawablePtr pDrawable, PixmapPtr pPixmap, Bool enable) +{ + rrScrPriv(pDrawable->pScreen); + int i; + Bool size_fits = FALSE; + Bool changed = FALSE; + Bool ret = TRUE; + + for (i = 0; i < pScrPriv->numCrtcs; i++) { + RRCrtcPtr crtc = pScrPriv->crtcs[i]; + + if (!crtc->mode && enable) + continue; + + changed = FALSE; + if (crtc->mode && crtc->x == pDrawable->x && + crtc->y == pDrawable->y && + crtc->mode->mode.width == pDrawable->width && + crtc->mode->mode.height == pDrawable->height) + size_fits = TRUE; + + /* is the pixmap already set? */ + if (crtc->scanout_pixmap == pPixmap) { + /* if its a disable then don't care about size */ + if (enable == FALSE) { + /* set scanout to NULL */ + crtc->scanout_pixmap = NULL; + changed = TRUE; + } else { + /* if the size fits then we are already setup */ + if (size_fits) + return TRUE; + /* if the size no longer fits then drop off */ + crtc->scanout_pixmap = NULL; + changed = TRUE; + ret = FALSE; + } + } else { + if (!size_fits) + return FALSE; + if (enable) { + crtc->scanout_pixmap = pPixmap; + pScrPriv->rrCrtcSetScanoutPixmap(crtc, pPixmap); + changed = TRUE; + } + } + + if (changed && pScrPriv->rrCrtcSet) { + pScrPriv->rrCrtcSetScanoutPixmap(crtc, crtc->scanout_pixmap); + + (*pScrPriv->rrCrtcSet) (pDrawable->pScreen, crtc, crtc->mode, crtc->x, crtc->y, + crtc->rotation, crtc->numOutputs, crtc->outputs); } } + return ret; } diff --git a/xorg-server/randr/rrdispatch.c b/xorg-server/randr/rrdispatch.c index 85cf03738..f9b26c137 100644 --- a/xorg-server/randr/rrdispatch.c +++ b/xorg-server/randr/rrdispatch.c @@ -35,16 +35,17 @@ RRClientKnowsRates(ClientPtr pClient) static int ProcRRQueryVersion(ClientPtr client) { - xRRQueryVersionReply rep = { 0 }; + xRRQueryVersionReply rep; REQUEST(xRRQueryVersionReq); rrClientPriv(client); REQUEST_SIZE_MATCH(xRRQueryVersionReq); pRRClient->major_version = stuff->majorVersion; pRRClient->minor_version = stuff->minorVersion; + memset(&rep, 0, sizeof(rep)); rep.type = X_Reply; - rep.length = 0; rep.sequenceNumber = client->sequence; + rep.length = 0; if (version_compare(stuff->majorVersion, stuff->minorVersion, SERVER_RANDR_MAJOR_VERSION, @@ -63,7 +64,7 @@ ProcRRQueryVersion(ClientPtr client) swapl(&rep.majorVersion); swapl(&rep.minorVersion); } - WriteToClient(client, sizeof(xRRQueryVersionReply), (char *) &rep); + WriteToClient(client, sizeof(xRRQueryVersionReply), &rep); return Success; } @@ -90,7 +91,8 @@ ProcRRSelectInput(ClientPtr client) if (stuff->enable & (RRScreenChangeNotifyMask | RRCrtcChangeNotifyMask | RROutputChangeNotifyMask | - RROutputPropertyNotifyMask)) { + RROutputPropertyNotifyMask | + RRProviderPropertyNotifyMask)) { ScreenPtr pScreen = pWin->drawable.pScreen; rrScrPriv(pScreen); @@ -241,4 +243,15 @@ int (*ProcRandrVector[RRNumberRequests]) (ClientPtr) = { ProcRRSetPanning, /* 29 */ ProcRRSetOutputPrimary, /* 30 */ ProcRRGetOutputPrimary, /* 31 */ +/* V1.4 additions */ + ProcRRGetProviders, /* 32 */ + ProcRRGetProviderInfo, /* 33 */ + ProcRRSetProviderOffloadSink, /* 34 */ + ProcRRSetProviderOutputSource, /* 35 */ + ProcRRListProviderProperties, /* 36 */ + ProcRRQueryProviderProperty, /* 37 */ + ProcRRConfigureProviderProperty, /* 38 */ + ProcRRChangeProviderProperty, /* 39 */ + ProcRRDeleteProviderProperty, /* 40 */ + ProcRRGetProviderProperty, /* 41 */ }; diff --git a/xorg-server/randr/rrmode.c b/xorg-server/randr/rrmode.c index 49a45c7f6..ae1218e0e 100644 --- a/xorg-server/randr/rrmode.c +++ b/xorg-server/randr/rrmode.c @@ -282,7 +282,7 @@ int ProcRRCreateMode(ClientPtr client) { REQUEST(xRRCreateModeReq); - xRRCreateModeReply rep = { 0 }; + xRRCreateModeReply rep; WindowPtr pWin; ScreenPtr pScreen; xRRModeInfo *modeInfo; @@ -310,8 +310,8 @@ ProcRRCreateMode(ClientPtr client) if (!mode) return error; + memset(&rep, 0, sizeof(rep)); rep.type = X_Reply; - rep.pad0 = 0; rep.sequenceNumber = client->sequence; rep.length = 0; rep.mode = mode->mode.id; @@ -320,7 +320,7 @@ ProcRRCreateMode(ClientPtr client) swapl(&rep.length); swapl(&rep.mode); } - WriteToClient(client, sizeof(xRRCreateModeReply), (char *) &rep); + WriteToClient(client, sizeof(xRRCreateModeReply), &rep); /* Drop out reference to this mode */ RRModeDestroy(mode); return Success; diff --git a/xorg-server/randr/rroutput.c b/xorg-server/randr/rroutput.c index fbd0e32b3..1eb071b4e 100644 --- a/xorg-server/randr/rroutput.c +++ b/xorg-server/randr/rroutput.c @@ -307,7 +307,8 @@ RRDeliverOutputEvent(ClientPtr client, WindowPtr pWin, RROutputPtr output) rrScrPriv(pScreen); xRROutputChangeNotifyEvent oe; RRCrtcPtr crtc = output->crtc; - RRModePtr mode = crtc ? crtc->mode : 0; + RRModePtr mode = crtc ? crtc->mode : NULL; + oe.type = RRNotify + RREventBase; oe.subCode = RRNotify_OutputChange; @@ -315,18 +316,12 @@ RRDeliverOutputEvent(ClientPtr client, WindowPtr pWin, RROutputPtr output) oe.configTimestamp = pScrPriv->lastConfigTime.milliseconds; oe.window = pWin->drawable.id; oe.output = output->id; - if (crtc) { - oe.crtc = crtc->id; - oe.mode = mode ? mode->mode.id : None; - oe.rotation = crtc->rotation; - } - else { - oe.crtc = None; - oe.mode = None; - oe.rotation = RR_Rotate_0; - } + oe.crtc = crtc ? crtc->id : None; + oe.mode = mode ? mode->mode.id : None; + oe.rotation = crtc ? crtc->rotation : RR_Rotate_0; oe.connection = output->connection; oe.subpixelOrder = output->subpixelOrder; + WriteEventsToClient(client, 1, (xEvent *) &oe); } @@ -425,7 +420,9 @@ ProcRRGetOutputInfo(ClientPtr client) pScreen = output->pScreen; pScrPriv = rrGetScrPriv(pScreen); + rep.type = X_Reply; + rep.status = RRSetConfigSuccess; rep.sequenceNumber = client->sequence; rep.length = bytes_to_int32(OutputInfoExtra); rep.timestamp = pScrPriv->lastSetTime.milliseconds; @@ -489,9 +486,9 @@ ProcRRGetOutputInfo(ClientPtr client) swaps(&rep.nClones); swaps(&rep.nameLength); } - WriteToClient(client, sizeof(xRRGetOutputInfoReply), (char *) &rep); + WriteToClient(client, sizeof(xRRGetOutputInfoReply), &rep); if (extraLen) { - WriteToClient(client, extraLen, (char *) extra); + WriteToClient(client, extraLen, extra); free(extra); } diff --git a/xorg-server/randr/rrproperty.c b/xorg-server/randr/rrproperty.c index 75948fccb..dc4a9f7a3 100644 --- a/xorg-server/randr/rrproperty.c +++ b/xorg-server/randr/rrproperty.c @@ -66,7 +66,6 @@ static void RRDeleteProperty(RROutputRec * output, RRPropertyRec * prop) { xRROutputPropertyNotifyEvent event; - event.type = RREventBase + RRNotify; event.subCode = RRNotify_OutputProperty; event.output = output->id; @@ -138,7 +137,6 @@ RRChangeOutputProperty(RROutputPtr output, Atom property, Atom type, pointer value, Bool sendevent, Bool pending) { RRPropertyPtr prop; - xRROutputPropertyNotifyEvent event; rrScrPrivPtr pScrPriv = rrGetScrPriv(output->pScreen); int size_in_bytes; int total_size; @@ -237,6 +235,7 @@ RRChangeOutputProperty(RROutputPtr output, Atom property, Atom type, output->pendingProperties = TRUE; if (sendevent) { + xRROutputPropertyNotifyEvent event; event.type = RREventBase + RRNotify; event.subCode = RRNotify_OutputProperty; event.output = output->id; @@ -378,7 +377,7 @@ int ProcRRListOutputProperties(ClientPtr client) { REQUEST(xRRListOutputPropertiesReq); - Atom *pAtoms = NULL, *temppAtoms; + Atom *pAtoms = NULL; xRRListOutputPropertiesReply rep; int numProps = 0; RROutputPtr output; @@ -394,21 +393,25 @@ ProcRRListOutputProperties(ClientPtr client) if (!(pAtoms = (Atom *) malloc(numProps * sizeof(Atom)))) return BadAlloc; + rep.type = X_Reply; - rep.length = bytes_to_int32(numProps * sizeof(Atom)); rep.sequenceNumber = client->sequence; + rep.length = bytes_to_int32(numProps * sizeof(Atom)); rep.nAtoms = numProps; + if (client->swapped) { swaps(&rep.sequenceNumber); swapl(&rep.length); swaps(&rep.nAtoms); } - temppAtoms = pAtoms; - for (prop = output->properties; prop; prop = prop->next) - *temppAtoms++ = prop->propertyName; + WriteToClient(client, sizeof(xRRListOutputPropertiesReply), &rep); - WriteToClient(client, sizeof(xRRListOutputPropertiesReply), (char *) &rep); if (numProps) { + /* Copy property name atoms to reply buffer */ + Atom *temppAtoms = pAtoms; + for (prop = output->properties; prop; prop = prop->next) + *temppAtoms++ = prop->propertyName; + client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write; WriteSwappedDataToClient(client, numProps * sizeof(Atom), pAtoms); free(pAtoms); @@ -438,17 +441,20 @@ ProcRRQueryOutputProperty(ClientPtr client) if (!extra) return BadAlloc; } + + rep.type = X_Reply; - rep.length = prop->num_valid; rep.sequenceNumber = client->sequence; + rep.length = prop->num_valid; rep.pending = prop->is_pending; rep.range = prop->range; rep.immutable = prop->immutable; + if (client->swapped) { swaps(&rep.sequenceNumber); swapl(&rep.length); } - WriteToClient(client, sizeof(xRRQueryOutputPropertyReply), (char *) &rep); + WriteToClient(client, sizeof(xRRQueryOutputPropertyReply), &rep); if (prop->num_valid) { memcpy(extra, prop->valid_values, prop->num_valid * sizeof(INT32)); client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write; @@ -594,8 +600,10 @@ ProcRRGetOutputProperty(ClientPtr client) if (prop->propertyName == stuff->property) break; + reply.type = X_Reply; reply.sequenceNumber = client->sequence; + if (!prop) { reply.nItems = 0; reply.length = 0; @@ -673,13 +681,13 @@ ProcRRGetOutputProperty(ClientPtr client) if (stuff->delete && (reply.bytesAfter == 0)) { xRROutputPropertyNotifyEvent event; - event.type = RREventBase + RRNotify; event.subCode = RRNotify_OutputProperty; event.output = output->id; event.state = PropertyDelete; event.atom = prop->propertyName; event.timestamp = currentTime.milliseconds; + RRDeliverPropertyEvent(output->pScreen, (xEvent *) &event); } diff --git a/xorg-server/randr/rrprovider.c b/xorg-server/randr/rrprovider.c new file mode 100644 index 000000000..c4fe36980 --- /dev/null +++ b/xorg-server/randr/rrprovider.c @@ -0,0 +1,411 @@ +/* + * Copyright © 2012 Red Hat Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + * + * Authors: Dave Airlie + */ + +#include "randrstr.h" +#include "swaprep.h" + +RESTYPE RRProviderType; + +/* + * Initialize provider type error value + */ +void +RRProviderInitErrorValue(void) +{ + SetResourceTypeErrorValue(RRProviderType, RRErrorBase + BadRRProvider); +} + +#define ADD_PROVIDER(_pScreen) do { \ + pScrPriv = rrGetScrPriv((_pScreen)); \ + if (pScrPriv->provider) { \ + providers[count_providers] = pScrPriv->provider->id; \ + if (client->swapped) \ + swapl(&providers[count_providers]); \ + count_providers++; \ + } \ + } while(0) + +int +ProcRRGetProviders (ClientPtr client) +{ + REQUEST(xRRGetProvidersReq); + xRRGetProvidersReply rep; + WindowPtr pWin; + ScreenPtr pScreen; + rrScrPrivPtr pScrPriv; + int rc; + CARD8 *extra; + unsigned int extraLen; + RRProvider *providers; + int total_providers = 0, count_providers = 0; + ScreenPtr iter; + + REQUEST_SIZE_MATCH(xRRGetProvidersReq); + rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); + if (rc != Success) + return rc; + + pScreen = pWin->drawable.pScreen; + + pScrPriv = rrGetScrPriv(pScreen); + + if (pScrPriv->provider) + total_providers++; + xorg_list_for_each_entry(iter, &pScreen->output_slave_list, output_head) { + pScrPriv = rrGetScrPriv(iter); + total_providers += pScrPriv->provider ? 1 : 0; + } + xorg_list_for_each_entry(iter, &pScreen->offload_slave_list, offload_head) { + pScrPriv = rrGetScrPriv(iter); + total_providers += pScrPriv->provider ? 1 : 0; + } + xorg_list_for_each_entry(iter, &pScreen->unattached_list, unattached_head) { + pScrPriv = rrGetScrPriv(iter); + total_providers += pScrPriv->provider ? 1 : 0; + } + + pScrPriv = rrGetScrPriv(pScreen); + rep.pad = 0; + + if (!pScrPriv) + { + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.timestamp = currentTime.milliseconds; + rep.nProviders = 0; + extra = NULL; + extraLen = 0; + } else { + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.timestamp = pScrPriv->lastSetTime.milliseconds; + rep.nProviders = total_providers; + rep.length = total_providers; + extraLen = rep.length << 2; + if (extraLen) { + extra = malloc(extraLen); + if (!extra) + return BadAlloc; + } else + extra = NULL; + + providers = (RRProvider *)extra; + ADD_PROVIDER(pScreen); + xorg_list_for_each_entry(iter, &pScreen->output_slave_list, output_head) { + ADD_PROVIDER(iter); + } + xorg_list_for_each_entry(iter, &pScreen->offload_slave_list, offload_head) { + ADD_PROVIDER(iter); + } + xorg_list_for_each_entry(iter, &pScreen->unattached_list, unattached_head) { + ADD_PROVIDER(iter); + } + } + + if (client->swapped) { + swaps(&rep.sequenceNumber); + swapl(&rep.length); + swapl(&rep.timestamp); + swaps(&rep.nProviders); + } + WriteToClient(client, sizeof(xRRGetProvidersReply), (char *)&rep); + if (extraLen) + { + WriteToClient (client, extraLen, (char *) extra); + free(extra); + } + return Success; +} + +int +ProcRRGetProviderInfo (ClientPtr client) +{ + REQUEST(xRRGetProviderInfoReq); + xRRGetProviderInfoReply rep; + rrScrPrivPtr pScrPriv, pScrProvPriv; + RRProviderPtr provider; + ScreenPtr pScreen; + CARD8 *extra; + unsigned int extraLen = 0; + RRCrtc *crtcs; + RROutput *outputs; + int i; + char *name; + ScreenPtr provscreen; + RRProvider *providers; + uint32_t *prov_cap; + + REQUEST_SIZE_MATCH(xRRGetProviderInfoReq); + VERIFY_RR_PROVIDER(stuff->provider, provider, DixReadAccess); + + pScreen = provider->pScreen; + pScrPriv = rrGetScrPriv(pScreen); + + rep.type = X_Reply; + rep.status = RRSetConfigSuccess; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.capabilities = provider->capabilities; + rep.nameLength = provider->nameLength; + rep.timestamp = pScrPriv->lastSetTime.milliseconds; + rep.nCrtcs = pScrPriv->numCrtcs; + rep.nOutputs = pScrPriv->numOutputs; + + /* count associated providers */ + rep.nAssociatedProviders = 0; + if (provider->offload_sink) + rep.nAssociatedProviders++; + if (provider->output_source) + rep.nAssociatedProviders++; + xorg_list_for_each_entry(provscreen, &pScreen->output_slave_list, output_head) + rep.nAssociatedProviders++; + xorg_list_for_each_entry(provscreen, &pScreen->offload_slave_list, offload_head) + rep.nAssociatedProviders++; + + rep.length = (pScrPriv->numCrtcs + pScrPriv->numOutputs + + (rep.nAssociatedProviders * 2) + bytes_to_int32(rep.nameLength)); + + extraLen = rep.length << 2; + if (extraLen) { + extra = malloc(extraLen); + if (!extra) + return BadAlloc; + } + else + extra = NULL; + + crtcs = (RRCrtc *)extra; + outputs = (RROutput *)(crtcs + rep.nCrtcs); + providers = (RRProvider *)(outputs + rep.nOutputs); + prov_cap = (unsigned int *)(providers + rep.nAssociatedProviders); + name = (char *)(prov_cap + rep.nAssociatedProviders); + + for (i = 0; i < pScrPriv->numCrtcs; i++) { + crtcs[i] = pScrPriv->crtcs[i]->id; + if (client->swapped) + swapl(&crtcs[i]); + } + + for (i = 0; i < pScrPriv->numOutputs; i++) { + outputs[i] = pScrPriv->outputs[i]->id; + if (client->swapped) + swapl(&outputs[i]); + } + + i = 0; + if (provider->offload_sink) { + providers[i] = provider->offload_sink->id; + if (client->swapped) + swapl(&providers[i]); + prov_cap[i] = RR_Capability_SinkOffload; + if (client->swapped) + swapl(&prov_cap[i]); + i++; + } + if (provider->output_source) { + providers[i] = provider->output_source->id; + if (client->swapped) + swapl(&providers[i]); + prov_cap[i] = RR_Capability_SourceOutput; + swapl(&prov_cap[i]); + i++; + } + xorg_list_for_each_entry(provscreen, &pScreen->output_slave_list, output_head) { + pScrProvPriv = rrGetScrPriv(provscreen); + providers[i] = pScrProvPriv->provider->id; + if (client->swapped) + swapl(&providers[i]); + prov_cap[i] = RR_Capability_SinkOutput; + if (client->swapped) + swapl(&prov_cap[i]); + i++; + } + xorg_list_for_each_entry(provscreen, &pScreen->offload_slave_list, offload_head) { + pScrProvPriv = rrGetScrPriv(provscreen); + providers[i] = pScrProvPriv->provider->id; + if (client->swapped) + swapl(&providers[i]); + prov_cap[i] = RR_Capability_SourceOffload; + if (client->swapped) + swapl(&prov_cap[i]); + i++; + } + + + memcpy(name, provider->name, rep.nameLength); + if (client->swapped) { + swaps(&rep.sequenceNumber); + swapl(&rep.length); + swapl(&rep.capabilities); + swaps(&rep.nCrtcs); + swaps(&rep.nOutputs); + swaps(&rep.nameLength); + } + WriteToClient(client, sizeof(xRRGetProviderInfoReply), (char *)&rep); + if (extraLen) + { + WriteToClient (client, extraLen, (char *) extra); + free(extra); + } + return Success; +} + +int +ProcRRSetProviderOutputSource(ClientPtr client) +{ + REQUEST(xRRSetProviderOutputSourceReq); + rrScrPrivPtr pScrPriv; + RRProviderPtr provider, source_provider = NULL; + ScreenPtr pScreen; + + REQUEST_AT_LEAST_SIZE(xRRSetProviderOutputSourceReq); + + VERIFY_RR_PROVIDER(stuff->provider, provider, DixReadAccess); + + if (!(provider->capabilities & RR_Capability_SinkOutput)) + return BadValue; + + if (stuff->source_provider) { + VERIFY_RR_PROVIDER(stuff->source_provider, source_provider, DixReadAccess); + + if (!(source_provider->capabilities & RR_Capability_SourceOutput)) + return BadValue; + } + + pScreen = provider->pScreen; + pScrPriv = rrGetScrPriv(pScreen); + + pScrPriv->rrProviderSetOutputSource(pScreen, provider, source_provider); + + RRTellChanged (pScreen); + + return Success; +} + +int +ProcRRSetProviderOffloadSink(ClientPtr client) +{ + REQUEST(xRRSetProviderOffloadSinkReq); + rrScrPrivPtr pScrPriv; + RRProviderPtr provider, sink_provider = NULL; + ScreenPtr pScreen; + + REQUEST_AT_LEAST_SIZE(xRRSetProviderOffloadSinkReq); + + VERIFY_RR_PROVIDER(stuff->provider, provider, DixReadAccess); + if (!(provider->capabilities & RR_Capability_SourceOffload)) + return BadValue; + + if (stuff->sink_provider) { + VERIFY_RR_PROVIDER(stuff->sink_provider, sink_provider, DixReadAccess); + if (!(sink_provider->capabilities & RR_Capability_SinkOffload)) + return BadValue; + } + pScreen = provider->pScreen; + pScrPriv = rrGetScrPriv(pScreen); + + pScrPriv->rrProviderSetOffloadSink(pScreen, provider, sink_provider); + + RRTellChanged (pScreen); + + return Success; +} + +RRProviderPtr +RRProviderCreate(ScreenPtr pScreen, const char *name, + int nameLength) +{ + RRProviderPtr provider; + rrScrPrivPtr pScrPriv; + + pScrPriv = rrGetScrPriv(pScreen); + + provider = calloc(1, sizeof(RRProviderRec) + nameLength + 1); + if (!provider) + return NULL; + + provider->id = FakeClientID(0); + provider->pScreen = pScreen; + provider->name = (char *) (provider + 1); + provider->nameLength = nameLength; + memcpy(provider->name, name, nameLength); + provider->name[nameLength] = '\0'; + + if (!AddResource (provider->id, RRProviderType, (pointer) provider)) + return NULL; + pScrPriv->provider = provider; + return provider; +} + +/* + * Destroy a provider at shutdown + */ +void +RRProviderDestroy (RRProviderPtr provider) +{ + FreeResource (provider->id, 0); +} + +void +RRProviderSetCapabilities(RRProviderPtr provider, uint32_t capabilities) +{ + provider->capabilities = capabilities; +} + +static int +RRProviderDestroyResource (pointer value, XID pid) +{ + RRProviderPtr provider = (RRProviderPtr)value; + ScreenPtr pScreen = provider->pScreen; + + if (pScreen) + { + rrScrPriv(pScreen); + + pScrPriv->provider = NULL; + } + free(provider); + return 1; +} + +Bool +RRProviderInit(void) +{ + RRProviderType = CreateNewResourceType(RRProviderDestroyResource, "Provider"); + if (!RRProviderType) + return FALSE; + + return TRUE; +} + +extern _X_EXPORT Bool +RRProviderLookup(XID id, RRProviderPtr *provider_p) +{ + int rc = dixLookupResourceByType((void **)provider_p, id, + RRProviderType, NullClient, DixReadAccess); + if (rc == Success) + return TRUE; + return FALSE; +} diff --git a/xorg-server/randr/rrproviderproperty.c b/xorg-server/randr/rrproviderproperty.c new file mode 100644 index 000000000..5e04fab8f --- /dev/null +++ b/xorg-server/randr/rrproviderproperty.c @@ -0,0 +1,716 @@ +/* + * Copyright © 2006 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#include "randrstr.h" +#include "propertyst.h" +#include "swaprep.h" + +static int +DeliverPropertyEvent(WindowPtr pWin, void *value) +{ + xRRProviderPropertyNotifyEvent *event = value; + RREventPtr *pHead, pRREvent; + + dixLookupResourceByType((pointer *) &pHead, pWin->drawable.id, + RREventType, serverClient, DixReadAccess); + if (!pHead) + return WT_WALKCHILDREN; + + for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next) { + if (!(pRREvent->mask & RRProviderPropertyNotifyMask)) + continue; + + event->window = pRREvent->window->drawable.id; + WriteEventsToClient(pRREvent->client, 1, (xEvent *) event); + } + + return WT_WALKCHILDREN; +} + +static void +RRDeliverPropertyEvent(ScreenPtr pScreen, xEvent *event) +{ + if (!(dispatchException & (DE_RESET | DE_TERMINATE))) + WalkTree(pScreen, DeliverPropertyEvent, event); +} + +static void +RRDestroyProviderProperty(RRPropertyPtr prop) +{ + free(prop->valid_values); + free(prop->current.data); + free(prop->pending.data); + free(prop); +} + +static void +RRDeleteProperty(RRProviderRec * provider, RRPropertyRec * prop) +{ + xRRProviderPropertyNotifyEvent event; + + event.type = RREventBase + RRNotify; + event.subCode = RRNotify_ProviderProperty; + event.provider = provider->id; + event.state = PropertyDelete; + event.atom = prop->propertyName; + event.timestamp = currentTime.milliseconds; + + RRDeliverPropertyEvent(provider->pScreen, (xEvent *) &event); + + RRDestroyProviderProperty(prop); +} + +void +RRDeleteAllProviderProperties(RRProviderPtr provider) +{ + RRPropertyPtr prop, next; + + for (prop = provider->properties; prop; prop = next) { + next = prop->next; + RRDeleteProperty(provider, prop); + } +} + +static void +RRInitProviderPropertyValue(RRPropertyValuePtr property_value) +{ + property_value->type = None; + property_value->format = 0; + property_value->size = 0; + property_value->data = NULL; +} + +static RRPropertyPtr +RRCreateProviderProperty(Atom property) +{ + RRPropertyPtr prop; + + prop = (RRPropertyPtr) malloc(sizeof(RRPropertyRec)); + if (!prop) + return NULL; + prop->next = NULL; + prop->propertyName = property; + prop->is_pending = FALSE; + prop->range = FALSE; + prop->immutable = FALSE; + prop->num_valid = 0; + prop->valid_values = NULL; + RRInitProviderPropertyValue(&prop->current); + RRInitProviderPropertyValue(&prop->pending); + return prop; +} + +void +RRDeleteProviderProperty(RRProviderPtr provider, Atom property) +{ + RRPropertyRec *prop, **prev; + + for (prev = &provider->properties; (prop = *prev); prev = &(prop->next)) + if (prop->propertyName == property) { + *prev = prop->next; + RRDeleteProperty(provider, prop); + return; + } +} + +int +RRChangeProviderProperty(RRProviderPtr provider, Atom property, Atom type, + int format, int mode, unsigned long len, + pointer value, Bool sendevent, Bool pending) +{ + RRPropertyPtr prop; + xRRProviderPropertyNotifyEvent event; + rrScrPrivPtr pScrPriv = rrGetScrPriv(provider->pScreen); + int size_in_bytes; + int total_size; + unsigned long total_len; + RRPropertyValuePtr prop_value; + RRPropertyValueRec new_value; + Bool add = FALSE; + + size_in_bytes = format >> 3; + + /* first see if property already exists */ + prop = RRQueryProviderProperty(provider, property); + if (!prop) { /* just add to list */ + prop = RRCreateProviderProperty(property); + if (!prop) + return BadAlloc; + add = TRUE; + mode = PropModeReplace; + } + if (pending && prop->is_pending) + prop_value = &prop->pending; + else + prop_value = &prop->current; + + /* To append or prepend to a property the request format and type + must match those of the already defined property. The + existing format and type are irrelevant when using the mode + "PropModeReplace" since they will be written over. */ + + if ((format != prop_value->format) && (mode != PropModeReplace)) + return BadMatch; + if ((prop_value->type != type) && (mode != PropModeReplace)) + return BadMatch; + new_value = *prop_value; + if (mode == PropModeReplace) + total_len = len; + else + total_len = prop_value->size + len; + + if (mode == PropModeReplace || len > 0) { + pointer new_data = NULL, old_data = NULL; + + total_size = total_len * size_in_bytes; + new_value.data = (pointer) malloc(total_size); + if (!new_value.data && total_size) { + if (add) + RRDestroyProviderProperty(prop); + return BadAlloc; + } + new_value.size = len; + new_value.type = type; + new_value.format = format; + + switch (mode) { + case PropModeReplace: + new_data = new_value.data; + old_data = NULL; + break; + case PropModeAppend: + new_data = (pointer) (((char *) new_value.data) + + (prop_value->size * size_in_bytes)); + old_data = new_value.data; + break; + case PropModePrepend: + new_data = new_value.data; + old_data = (pointer) (((char *) new_value.data) + + (prop_value->size * size_in_bytes)); + break; + } + if (new_data) + memcpy((char *) new_data, (char *) value, len * size_in_bytes); + if (old_data) + memcpy((char *) old_data, (char *) prop_value->data, + prop_value->size * size_in_bytes); + + if (pending && pScrPriv->rrProviderSetProperty && + !pScrPriv->rrProviderSetProperty(provider->pScreen, provider, + prop->propertyName, &new_value)) { + free(new_value.data); + return BadValue; + } + free(prop_value->data); + *prop_value = new_value; + } + + else if (len == 0) { + /* do nothing */ + } + + if (add) { + prop->next = provider->properties; + provider->properties = prop; + } + + if (pending && prop->is_pending) + provider->pendingProperties = TRUE; + + if (sendevent) { + event.type = RREventBase + RRNotify; + event.subCode = RRNotify_ProviderProperty; + event.provider = provider->id; + event.state = PropertyNewValue; + event.atom = prop->propertyName; + event.timestamp = currentTime.milliseconds; + RRDeliverPropertyEvent(provider->pScreen, (xEvent *) &event); + } + return Success; +} + +Bool +RRPostProviderPendingProperties(RRProviderPtr provider) +{ + RRPropertyValuePtr pending_value; + RRPropertyValuePtr current_value; + RRPropertyPtr property; + Bool ret = TRUE; + + if (!provider->pendingProperties) + return TRUE; + + provider->pendingProperties = FALSE; + for (property = provider->properties; property; property = property->next) { + /* Skip non-pending properties */ + if (!property->is_pending) + continue; + + pending_value = &property->pending; + current_value = &property->current; + + /* + * If the pending and current values are equal, don't mark it + * as changed (which would deliver an event) + */ + if (pending_value->type == current_value->type && + pending_value->format == current_value->format && + pending_value->size == current_value->size && + !memcmp(pending_value->data, current_value->data, + pending_value->size * (pending_value->format / 8))) + continue; + + if (RRChangeProviderProperty(provider, property->propertyName, + pending_value->type, pending_value->format, + PropModeReplace, pending_value->size, + pending_value->data, TRUE, FALSE) != Success) + ret = FALSE; + } + return ret; +} + +RRPropertyPtr +RRQueryProviderProperty(RRProviderPtr provider, Atom property) +{ + RRPropertyPtr prop; + + for (prop = provider->properties; prop; prop = prop->next) + if (prop->propertyName == property) + return prop; + return NULL; +} + +RRPropertyValuePtr +RRGetProviderProperty(RRProviderPtr provider, Atom property, Bool pending) +{ + RRPropertyPtr prop = RRQueryProviderProperty(provider, property); + rrScrPrivPtr pScrPriv = rrGetScrPriv(provider->pScreen); + + if (!prop) + return NULL; + if (pending && prop->is_pending) + return &prop->pending; + else { +#if RANDR_13_INTERFACE + /* If we can, try to update the property value first */ + if (pScrPriv->rrProviderGetProperty) + pScrPriv->rrProviderGetProperty(provider->pScreen, provider, + prop->propertyName); +#endif + return &prop->current; + } +} + +int +RRConfigureProviderProperty(RRProviderPtr provider, Atom property, + Bool pending, Bool range, Bool immutable, + int num_values, INT32 *values) +{ + RRPropertyPtr prop = RRQueryProviderProperty(provider, property); + Bool add = FALSE; + INT32 *new_values; + + if (!prop) { + prop = RRCreateProviderProperty(property); + if (!prop) + return BadAlloc; + add = TRUE; + } + else if (prop->immutable && !immutable) + return BadAccess; + + /* + * ranges must have even number of values + */ + if (range && (num_values & 1)) + return BadMatch; + + new_values = malloc(num_values * sizeof(INT32)); + if (!new_values && num_values) + return BadAlloc; + if (num_values) + memcpy(new_values, values, num_values * sizeof(INT32)); + + /* + * Property moving from pending to non-pending + * loses any pending values + */ + if (prop->is_pending && !pending) { + free(prop->pending.data); + RRInitProviderPropertyValue(&prop->pending); + } + + prop->is_pending = pending; + prop->range = range; + prop->immutable = immutable; + prop->num_valid = num_values; + free(prop->valid_values); + prop->valid_values = new_values; + + if (add) { + prop->next = provider->properties; + provider->properties = prop; + } + + return Success; +} + +int +ProcRRListProviderProperties(ClientPtr client) +{ + REQUEST(xRRListProviderPropertiesReq); + Atom *pAtoms = NULL, *temppAtoms; + xRRListProviderPropertiesReply rep; + int numProps = 0; + RRProviderPtr provider; + RRPropertyPtr prop; + + REQUEST_SIZE_MATCH(xRRListProviderPropertiesReq); + + VERIFY_RR_PROVIDER(stuff->provider, provider, DixReadAccess); + + for (prop = provider->properties; prop; prop = prop->next) + numProps++; + if (numProps) + if (!(pAtoms = (Atom *) malloc(numProps * sizeof(Atom)))) + return BadAlloc; + + rep.type = X_Reply; + rep.length = bytes_to_int32(numProps * sizeof(Atom)); + rep.sequenceNumber = client->sequence; + rep.nAtoms = numProps; + if (client->swapped) { + swaps(&rep.sequenceNumber); + swapl(&rep.length); + swaps(&rep.nAtoms); + } + temppAtoms = pAtoms; + for (prop = provider->properties; prop; prop = prop->next) + *temppAtoms++ = prop->propertyName; + + WriteToClient(client, sizeof(xRRListProviderPropertiesReply), (char *) &rep); + if (numProps) { + client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write; + WriteSwappedDataToClient(client, numProps * sizeof(Atom), pAtoms); + free(pAtoms); + } + return Success; +} + +int +ProcRRQueryProviderProperty(ClientPtr client) +{ + REQUEST(xRRQueryProviderPropertyReq); + xRRQueryProviderPropertyReply rep; + RRProviderPtr provider; + RRPropertyPtr prop; + char *extra = NULL; + + REQUEST_SIZE_MATCH(xRRQueryProviderPropertyReq); + + VERIFY_RR_PROVIDER(stuff->provider, provider, DixReadAccess); + + prop = RRQueryProviderProperty(provider, stuff->property); + if (!prop) + return BadName; + + if (prop->num_valid) { + extra = malloc(prop->num_valid * sizeof(INT32)); + if (!extra) + return BadAlloc; + } + rep.type = X_Reply; + rep.length = prop->num_valid; + rep.sequenceNumber = client->sequence; + rep.pending = prop->is_pending; + rep.range = prop->range; + rep.immutable = prop->immutable; + if (client->swapped) { + swaps(&rep.sequenceNumber); + swapl(&rep.length); + } + WriteToClient(client, sizeof(xRRQueryProviderPropertyReply), (char *) &rep); + if (prop->num_valid) { + memcpy(extra, prop->valid_values, prop->num_valid * sizeof(INT32)); + client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write; + WriteSwappedDataToClient(client, prop->num_valid * sizeof(INT32), + extra); + free(extra); + } + return Success; +} + +int +ProcRRConfigureProviderProperty(ClientPtr client) +{ + REQUEST(xRRConfigureProviderPropertyReq); + RRProviderPtr provider; + int num_valid; + + REQUEST_AT_LEAST_SIZE(xRRConfigureProviderPropertyReq); + + VERIFY_RR_PROVIDER(stuff->provider, provider, DixReadAccess); + + num_valid = + stuff->length - bytes_to_int32(sizeof(xRRConfigureProviderPropertyReq)); + return RRConfigureProviderProperty(provider, stuff->property, stuff->pending, + stuff->range, FALSE, num_valid, + (INT32 *) (stuff + 1)); +} + +int +ProcRRChangeProviderProperty(ClientPtr client) +{ + REQUEST(xRRChangeProviderPropertyReq); + RRProviderPtr provider; + char format, mode; + unsigned long len; + int sizeInBytes; + int totalSize; + int err; + + REQUEST_AT_LEAST_SIZE(xRRChangeProviderPropertyReq); + UpdateCurrentTime(); + format = stuff->format; + mode = stuff->mode; + if ((mode != PropModeReplace) && (mode != PropModeAppend) && + (mode != PropModePrepend)) { + client->errorValue = mode; + return BadValue; + } + if ((format != 8) && (format != 16) && (format != 32)) { + client->errorValue = format; + return BadValue; + } + len = stuff->nUnits; + if (len > bytes_to_int32((0xffffffff - sizeof(xChangePropertyReq)))) + return BadLength; + sizeInBytes = format >> 3; + totalSize = len * sizeInBytes; + REQUEST_FIXED_SIZE(xRRChangeProviderPropertyReq, totalSize); + + VERIFY_RR_PROVIDER(stuff->provider, provider, DixReadAccess); + + if (!ValidAtom(stuff->property)) { + client->errorValue = stuff->property; + return BadAtom; + } + if (!ValidAtom(stuff->type)) { + client->errorValue = stuff->type; + return BadAtom; + } + + err = RRChangeProviderProperty(provider, stuff->property, + stuff->type, (int) format, + (int) mode, len, (pointer) &stuff[1], TRUE, + TRUE); + if (err != Success) + return err; + else + return Success; +} + +int +ProcRRDeleteProviderProperty(ClientPtr client) +{ + REQUEST(xRRDeleteProviderPropertyReq); + RRProviderPtr provider; + RRPropertyPtr prop; + + REQUEST_SIZE_MATCH(xRRDeleteProviderPropertyReq); + UpdateCurrentTime(); + VERIFY_RR_PROVIDER(stuff->provider, provider, DixReadAccess); + + if (!ValidAtom(stuff->property)) { + client->errorValue = stuff->property; + return BadAtom; + } + + prop = RRQueryProviderProperty(provider, stuff->property); + if (!prop) { + client->errorValue = stuff->property; + return BadName; + } + + if (prop->immutable) { + client->errorValue = stuff->property; + return BadAccess; + } + + RRDeleteProviderProperty(provider, stuff->property); + return Success; +} + +int +ProcRRGetProviderProperty(ClientPtr client) +{ + REQUEST(xRRGetProviderPropertyReq); + RRPropertyPtr prop, *prev; + RRPropertyValuePtr prop_value; + unsigned long n, len, ind; + RRProviderPtr provider; + xRRGetProviderPropertyReply reply; + char *extra = NULL; + + REQUEST_SIZE_MATCH(xRRGetProviderPropertyReq); + if (stuff->delete) + UpdateCurrentTime(); + VERIFY_RR_PROVIDER(stuff->provider, provider, + stuff->delete ? DixWriteAccess : DixReadAccess); + + if (!ValidAtom(stuff->property)) { + client->errorValue = stuff->property; + return BadAtom; + } + if ((stuff->delete != xTrue) && (stuff->delete != xFalse)) { + client->errorValue = stuff->delete; + return BadValue; + } + if ((stuff->type != AnyPropertyType) && !ValidAtom(stuff->type)) { + client->errorValue = stuff->type; + return BadAtom; + } + + for (prev = &provider->properties; (prop = *prev); prev = &prop->next) + if (prop->propertyName == stuff->property) + break; + + reply.type = X_Reply; + reply.sequenceNumber = client->sequence; + if (!prop) { + reply.nItems = 0; + reply.length = 0; + reply.bytesAfter = 0; + reply.propertyType = None; + reply.format = 0; + if (client->swapped) { + swaps(&reply.sequenceNumber); + swapl(&reply.length); + swapl(&reply.propertyType); + swapl(&reply.bytesAfter); + swapl(&reply.nItems); + } + WriteToClient(client, sizeof(xRRGetProviderPropertyReply), &reply); + return Success; + } + + if (prop->immutable && stuff->delete) + return BadAccess; + + prop_value = RRGetProviderProperty(provider, stuff->property, stuff->pending); + if (!prop_value) + return BadAtom; + + /* If the request type and actual type don't match. Return the + property information, but not the data. */ + + if (((stuff->type != prop_value->type) && (stuff->type != AnyPropertyType)) + ) { + reply.bytesAfter = prop_value->size; + reply.format = prop_value->format; + reply.length = 0; + reply.nItems = 0; + reply.propertyType = prop_value->type; + if (client->swapped) { + swaps(&reply.sequenceNumber); + swapl(&reply.length); + swapl(&reply.propertyType); + swapl(&reply.bytesAfter); + swapl(&reply.nItems); + } + WriteToClient(client, sizeof(xRRGetProviderPropertyReply), &reply); + return Success; + } + +/* + * Return type, format, value to client + */ + n = (prop_value->format / 8) * prop_value->size; /* size (bytes) of prop */ + ind = stuff->longOffset << 2; + + /* If longOffset is invalid such that it causes "len" to + be negative, it's a value error. */ + + if (n < ind) { + client->errorValue = stuff->longOffset; + return BadValue; + } + + len = min(n - ind, 4 * stuff->longLength); + + if (len) { + extra = malloc(len); + if (!extra) + return BadAlloc; + } + reply.bytesAfter = n - (ind + len); + reply.format = prop_value->format; + reply.length = bytes_to_int32(len); + if (prop_value->format) + reply.nItems = len / (prop_value->format / 8); + else + reply.nItems = 0; + reply.propertyType = prop_value->type; + + if (stuff->delete && (reply.bytesAfter == 0)) { + xRRProviderPropertyNotifyEvent event; + + event.type = RREventBase + RRNotify; + event.subCode = RRNotify_ProviderProperty; + event.provider = provider->id; + event.state = PropertyDelete; + event.atom = prop->propertyName; + event.timestamp = currentTime.milliseconds; + RRDeliverPropertyEvent(provider->pScreen, (xEvent *) &event); + } + + if (client->swapped) { + swaps(&reply.sequenceNumber); + swapl(&reply.length); + swapl(&reply.propertyType); + swapl(&reply.bytesAfter); + swapl(&reply.nItems); + } + WriteToClient(client, sizeof(xGenericReply), &reply); + if (len) { + memcpy(extra, (char *) prop_value->data + ind, len); + switch (reply.format) { + case 32: + client->pSwapReplyFunc = (ReplySwapPtr) CopySwap32Write; + break; + case 16: + client->pSwapReplyFunc = (ReplySwapPtr) CopySwap16Write; + break; + default: + client->pSwapReplyFunc = (ReplySwapPtr) WriteToClient; + break; + } + WriteSwappedDataToClient(client, len, extra); + free(extra); + } + + if (stuff->delete && (reply.bytesAfter == 0)) { /* delete the Property */ + *prev = prop->next; + RRDestroyProviderProperty(prop); + } + return Success; +} 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; } diff --git a/xorg-server/randr/rrxinerama.c b/xorg-server/randr/rrxinerama.c index aa8a61eee..63e2a318b 100644 --- a/xorg-server/randr/rrxinerama.c +++ b/xorg-server/randr/rrxinerama.c @@ -93,8 +93,8 @@ ProcRRXineramaQueryVersion(ClientPtr client) REQUEST_SIZE_MATCH(xPanoramiXQueryVersionReq); rep.type = X_Reply; - rep.length = 0; rep.sequenceNumber = client->sequence; + rep.length = 0; rep.majorVersion = SERVER_RRXINERAMA_MAJOR_VERSION; rep.minorVersion = SERVER_RRXINERAMA_MINOR_VERSION; if (client->swapped) { @@ -103,7 +103,7 @@ ProcRRXineramaQueryVersion(ClientPtr client) swaps(&rep.majorVersion); swaps(&rep.minorVersion); } - WriteToClient(client, sizeof(xPanoramiXQueryVersionReply), (char *) &rep); + WriteToClient(client, sizeof(xPanoramiXQueryVersionReply), &rep); return Success; } @@ -130,17 +130,19 @@ ProcRRXineramaGetState(ClientPtr client) active = TRUE; } + rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; rep.state = active; + rep.sequenceNumber = client->sequence; + rep.length = 0; rep.window = stuff->window; + if (client->swapped) { swaps(&rep.sequenceNumber); swapl(&rep.length); swapl(&rep.window); } - WriteToClient(client, sizeof(xPanoramiXGetStateReply), (char *) &rep); + WriteToClient(client, sizeof(xPanoramiXGetStateReply), &rep); return Success; } @@ -184,17 +186,19 @@ ProcRRXineramaGetScreenCount(ClientPtr client) if (rc != Success) return rc; + rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; rep.ScreenCount = RRXineramaScreenCount(pWin->drawable.pScreen); + rep.sequenceNumber = client->sequence; + rep.length = 0; rep.window = stuff->window; + if (client->swapped) { swaps(&rep.sequenceNumber); swapl(&rep.length); swapl(&rep.window); } - WriteToClient(client, sizeof(xPanoramiXGetScreenCountReply), (char *) &rep); + WriteToClient(client, sizeof(xPanoramiXGetScreenCountReply), &rep); return Success; } @@ -215,13 +219,15 @@ ProcRRXineramaGetScreenSize(ClientPtr client) pScreen = pWin->drawable.pScreen; pRoot = pScreen->root; + rep.type = X_Reply; - rep.length = 0; rep.sequenceNumber = client->sequence; + rep.length = 0; rep.width = pRoot->drawable.width; rep.height = pRoot->drawable.height; rep.window = stuff->window; rep.screen = stuff->screen; + if (client->swapped) { swaps(&rep.sequenceNumber); swapl(&rep.length); @@ -230,7 +236,7 @@ ProcRRXineramaGetScreenSize(ClientPtr client) swapl(&rep.window); swapl(&rep.screen); } - WriteToClient(client, sizeof(xPanoramiXGetScreenSizeReply), (char *) &rep); + WriteToClient(client, sizeof(xPanoramiXGetScreenSizeReply), &rep); return Success; } @@ -246,12 +252,13 @@ ProcRRXineramaIsActive(ClientPtr client) rep.length = 0; rep.sequenceNumber = client->sequence; rep.state = RRXineramaScreenActive(screenInfo.screens[RR_XINERAMA_SCREEN]); + if (client->swapped) { swaps(&rep.sequenceNumber); swapl(&rep.length); swapl(&rep.state); } - WriteToClient(client, sizeof(xXineramaIsActiveReply), (char *) &rep); + WriteToClient(client, sizeof(xXineramaIsActiveReply), &rep); return Success; } @@ -299,24 +306,29 @@ ProcRRXineramaQueryScreens(ClientPtr client) { xXineramaQueryScreensReply rep; ScreenPtr pScreen = screenInfo.screens[RR_XINERAMA_SCREEN]; + int n = 0; REQUEST_SIZE_MATCH(xXineramaQueryScreensReq); - if (RRXineramaScreenActive(pScreen)) + if (RRXineramaScreenActive(pScreen)) { RRGetInfo(pScreen, FALSE); + n = RRXineramaScreenCount(pScreen); + } + rep.type = X_Reply; rep.sequenceNumber = client->sequence; - rep.number = RRXineramaScreenCount(pScreen); - rep.length = bytes_to_int32(rep.number * sz_XineramaScreenInfo); + rep.length = bytes_to_int32(n * sz_XineramaScreenInfo); + rep.number = n; + if (client->swapped) { swaps(&rep.sequenceNumber); swapl(&rep.length); swapl(&rep.number); } - WriteToClient(client, sizeof(xXineramaQueryScreensReply), (char *) &rep); + WriteToClient(client, sizeof(xXineramaQueryScreensReply), &rep); - if (rep.number) { + if (n) { rrScrPriv(pScreen); int i; int has_primary = 0; |