diff options
Diffstat (limited to 'nx-X11/programs/Xserver/randr/rrcrtc.c')
-rw-r--r-- | nx-X11/programs/Xserver/randr/rrcrtc.c | 2195 |
1 files changed, 1566 insertions, 629 deletions
diff --git a/nx-X11/programs/Xserver/randr/rrcrtc.c b/nx-X11/programs/Xserver/randr/rrcrtc.c index fdf063901..d69b5ec08 100644 --- a/nx-X11/programs/Xserver/randr/rrcrtc.c +++ b/nx-X11/programs/Xserver/randr/rrcrtc.c @@ -1,5 +1,6 @@ /* * Copyright © 2006 Keith Packard + * Copyright 2010 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 @@ -39,29 +40,28 @@ #include "randrstr.h" #include "swaprep.h" -#include "registry.h" +#include "mipointer.h" -RESTYPE RRCrtcType; +RESTYPE RRCrtcType; /* * Notify the CRTC of some change */ void -RRCrtcChanged (RRCrtcPtr crtc, Bool layoutChanged) +RRCrtcChanged(RRCrtcPtr crtc, Bool layoutChanged) { - ScreenPtr pScreen = crtc->pScreen; + ScreenPtr pScreen = crtc->pScreen; crtc->changed = TRUE; - if (pScreen) - { - rrScrPriv(pScreen); - - pScrPriv->changed = TRUE; - /* - * Send ConfigureNotify on any layout change - */ - if (layoutChanged) - pScrPriv->layoutChanged = TRUE; + if (pScreen) { + rrScrPriv(pScreen); + + RRSetChanged(pScreen); + /* + * Send ConfigureNotify on any layout change + */ + if (layoutChanged) + pScrPriv->layoutChanged = TRUE; } } @@ -69,31 +69,36 @@ RRCrtcChanged (RRCrtcPtr crtc, Bool layoutChanged) * Create a CRTC */ RRCrtcPtr -RRCrtcCreate (ScreenPtr pScreen, void *devPrivate) +RRCrtcCreate(ScreenPtr pScreen, void *devPrivate) { - RRCrtcPtr crtc; - RRCrtcPtr *crtcs; - rrScrPrivPtr pScrPriv; + RRCrtcPtr crtc; + RRCrtcPtr *crtcs; + rrScrPrivPtr pScrPriv; if (!RRInit()) - return NULL; - + return NULL; + pScrPriv = rrGetScrPriv(pScreen); /* make space for the crtc pointer */ if (pScrPriv->numCrtcs) - crtcs = xrealloc (pScrPriv->crtcs, - (pScrPriv->numCrtcs + 1) * sizeof (RRCrtcPtr)); +#ifndef NXAGENT_SERVER + crtcs = reallocarray(pScrPriv->crtcs, + pScrPriv->numCrtcs + 1, sizeof(RRCrtcPtr)); +#else /* !defined(NXAGENT_SERVER) */ + crtcs = xrealloc(pScrPriv->crtcs, + (pScrPriv->numCrtcs + 1) * sizeof(RRCrtcPtr)); +#endif /* !defined(NXAGENT_SERVER) */ else - crtcs = xalloc (sizeof (RRCrtcPtr)); + crtcs = xalloc(sizeof(RRCrtcPtr)); if (!crtcs) - return FALSE; + return FALSE; pScrPriv->crtcs = crtcs; - - crtc = xcalloc (1, sizeof (RRCrtcRec)); + + crtc = xcalloc(1, sizeof(RRCrtcRec)); if (!crtc) - return NULL; - crtc->id = FakeClientID (0); + return NULL; + crtc->id = FakeClientID(0); crtc->pScreen = pScreen; crtc->mode = NULL; crtc->x = 0; @@ -106,14 +111,21 @@ RRCrtcCreate (ScreenPtr pScreen, void *devPrivate) crtc->gammaRed = crtc->gammaBlue = crtc->gammaGreen = NULL; crtc->changed = FALSE; crtc->devPrivate = devPrivate; + RRTransformInit(&crtc->client_pending_transform); + RRTransformInit(&crtc->client_current_transform); + pixman_transform_init_identity(&crtc->transform); + pixman_f_transform_init_identity(&crtc->f_transform); + pixman_f_transform_init_identity(&crtc->f_inverse); - if (!AddResource (crtc->id, RRCrtcType, (void *) crtc)) - return NULL; + if (!AddResource(crtc->id, RRCrtcType, (void *) crtc)) + return NULL; /* attach the screen and crtc together */ crtc->pScreen = pScreen; pScrPriv->crtcs[pScrPriv->numCrtcs++] = crtc; - + + RRResourcesChanged(pScreen); + return crtc; } @@ -121,296 +133,655 @@ RRCrtcCreate (ScreenPtr pScreen, void *devPrivate) * Set the allowed rotations on a CRTC */ void -RRCrtcSetRotations (RRCrtcPtr crtc, Rotation rotations) +RRCrtcSetRotations(RRCrtcPtr crtc, Rotation rotations) { crtc->rotations = rotations; } /* + * Set whether transforms are allowed on a CRTC + */ +void +RRCrtcSetTransformSupport(RRCrtcPtr crtc, Bool transforms) +{ + crtc->transforms = transforms; +} + +/* * Notify the extension that the Crtc has been reconfigured, * the driver calls this whenever it has updated the mode */ Bool -RRCrtcNotify (RRCrtcPtr crtc, - RRModePtr mode, - int x, - int y, - Rotation rotation, - int numOutputs, - RROutputPtr *outputs) -{ - int i, j; - +RRCrtcNotify(RRCrtcPtr crtc, + RRModePtr mode, + int x, + int y, + Rotation rotation, + RRTransformPtr transform, int numOutputs, RROutputPtr * outputs) +{ + int i, j; + /* * Check to see if any of the new outputs were * not in the old list and mark them as changed */ - for (i = 0; i < numOutputs; i++) - { - for (j = 0; j < crtc->numOutputs; j++) - if (outputs[i] == crtc->outputs[j]) - break; - if (j == crtc->numOutputs) - { - outputs[i]->crtc = crtc; - RROutputChanged (outputs[i], FALSE); - RRCrtcChanged (crtc, FALSE); - } + for (i = 0; i < numOutputs; i++) { + for (j = 0; j < crtc->numOutputs; j++) + if (outputs[i] == crtc->outputs[j]) + break; + if (j == crtc->numOutputs) { + outputs[i]->crtc = crtc; + RROutputChanged(outputs[i], FALSE); + RRCrtcChanged(crtc, FALSE); + } } /* * Check to see if any of the old outputs are * not in the new list and mark them as changed */ - for (j = 0; j < crtc->numOutputs; j++) - { - for (i = 0; i < numOutputs; i++) - if (outputs[i] == crtc->outputs[j]) - break; - if (i == numOutputs) - { - if (crtc->outputs[j]->crtc == crtc) - crtc->outputs[j]->crtc = NULL; - RROutputChanged (crtc->outputs[j], FALSE); - RRCrtcChanged (crtc, FALSE); - } + for (j = 0; j < crtc->numOutputs; j++) { + for (i = 0; i < numOutputs; i++) + if (outputs[i] == crtc->outputs[j]) + break; + if (i == numOutputs) { + if (crtc->outputs[j]->crtc == crtc) + crtc->outputs[j]->crtc = NULL; + RROutputChanged(crtc->outputs[j], FALSE); + RRCrtcChanged(crtc, FALSE); + } } /* * Reallocate the crtc output array if necessary */ - if (numOutputs != crtc->numOutputs) - { - RROutputPtr *newoutputs; - - if (numOutputs) - { - if (crtc->numOutputs) - newoutputs = xrealloc (crtc->outputs, - numOutputs * sizeof (RROutputPtr)); - else - newoutputs = xalloc (numOutputs * sizeof (RROutputPtr)); - if (!newoutputs) - return FALSE; - } - else - { - if (crtc->outputs) - xfree (crtc->outputs); - newoutputs = NULL; - } - crtc->outputs = newoutputs; - crtc->numOutputs = numOutputs; + if (numOutputs != crtc->numOutputs) { + RROutputPtr *newoutputs; + + if (numOutputs) { + if (crtc->numOutputs) +#ifndef NXAGENT_SERVER + newoutputs = reallocarray(crtc->outputs, + numOutputs, sizeof(RROutputPtr)); +#else /* !defined(NXAGENT_SERVER) */ + newoutputs = xrealloc(crtc->outputs, + numOutputs * sizeof(RROutputPtr)); +#endif /* !defined(NXAGENT_SERVER) */ + else +#ifndef NXAGENT_SERVER + newoutputs = xallocarray(numOutputs, sizeof(RROutputPtr)); +#else /* !defined(NXAGENT_SERVER) */ + newoutputs = xalloc(numOutputs * sizeof(RROutputPtr)); +#endif /* !defined(NXAGENT_SERVER) */ + if (!newoutputs) + return FALSE; + } + else { + xfree(crtc->outputs); + newoutputs = NULL; + } + crtc->outputs = newoutputs; + crtc->numOutputs = numOutputs; } /* * Copy the new list of outputs into the crtc */ - memcpy (crtc->outputs, outputs, numOutputs * sizeof (RROutputPtr)); + memcpy(crtc->outputs, outputs, numOutputs * sizeof(RROutputPtr)); /* * Update remaining crtc fields */ - if (mode != crtc->mode) - { - if (crtc->mode) - RRModeDestroy (crtc->mode); - crtc->mode = mode; - if (mode != NULL) - mode->refcnt++; - RRCrtcChanged (crtc, TRUE); - } - if (x != crtc->x) - { - crtc->x = x; - RRCrtcChanged (crtc, TRUE); - } - if (y != crtc->y) - { - crtc->y = y; - RRCrtcChanged (crtc, TRUE); - } - if (rotation != crtc->rotation) - { - crtc->rotation = rotation; - RRCrtcChanged (crtc, TRUE); + if (mode != crtc->mode) { + if (crtc->mode) + RRModeDestroy(crtc->mode); + crtc->mode = mode; + if (mode != NULL) + mode->refcnt++; + RRCrtcChanged(crtc, TRUE); + } + if (x != crtc->x) { + crtc->x = x; + RRCrtcChanged(crtc, TRUE); + } + if (y != crtc->y) { + crtc->y = y; + RRCrtcChanged(crtc, TRUE); + } + if (rotation != crtc->rotation) { + crtc->rotation = rotation; + RRCrtcChanged(crtc, TRUE); + } + if (!RRTransformEqual(transform, &crtc->client_current_transform)) { + RRTransformCopy(&crtc->client_current_transform, transform); + RRCrtcChanged(crtc, TRUE); + } + if (crtc->changed && mode) { + RRTransformCompute(x, y, + mode->mode.width, mode->mode.height, + rotation, + &crtc->client_current_transform, + &crtc->transform, &crtc->f_transform, + &crtc->f_inverse); } return TRUE; } void -RRDeliverCrtcEvent (ClientPtr client, WindowPtr pWin, RRCrtcPtr crtc) +RRDeliverCrtcEvent(ClientPtr client, WindowPtr pWin, RRCrtcPtr crtc) { ScreenPtr pScreen = pWin->drawable.pScreen; - rrScrPriv (pScreen); - xRRCrtcChangeNotifyEvent ce; - RRModePtr mode = crtc->mode; - - ce.type = RRNotify + RREventBase; - ce.subCode = RRNotify_CrtcChange; - ce.sequenceNumber = client->sequence; - ce.timestamp = pScrPriv->lastSetTime.milliseconds; - ce.window = pWin->drawable.id; - ce.crtc = crtc->id; - 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; + + rrScrPriv(pScreen); + RRModePtr mode = crtc->mode; + + xRRCrtcChangeNotifyEvent ce = { + .type = RRNotify + RREventBase, + .subCode = RRNotify_CrtcChange, +#ifdef NXAGENT_SERVER + .sequenceNumber = client->sequence, +#endif + .timestamp = pScrPriv->lastSetTime.milliseconds, + .window = pWin->drawable.id, + .crtc = crtc->id, + .mode = mode ? mode->mode.id : None, + .rotation = crtc->rotation, + .x = mode ? crtc->x : 0, + .y = mode ? crtc->y : 0, + .width = mode ? mode->mode.width : 0, + .height = mode ? mode->mode.height : 0 + }; + WriteEventsToClient(client, 1, (xEvent *) &ce); +} + +static Bool +RRCrtcPendingProperties(RRCrtcPtr crtc) +{ + ScreenPtr pScreen = crtc->pScreen; + + rrScrPriv(pScreen); + int o; + + for (o = 0; o < pScrPriv->numOutputs; o++) { + RROutputPtr output = pScrPriv->outputs[o]; + + if (output->crtc == crtc && output->pendingProperties) + return TRUE; } - else - { - ce.mode = None; - ce.x = 0; - ce.y = 0; - ce.width = 0; - ce.height = 0; + return FALSE; +} + +static void +crtc_bounds(RRCrtcPtr crtc, int *left, int *right, int *top, int *bottom) +{ + *left = crtc->x; + *top = crtc->y; + + switch (crtc->rotation) { + case RR_Rotate_0: + case RR_Rotate_180: + default: + *right = crtc->x + crtc->mode->mode.width; + *bottom = crtc->y + crtc->mode->mode.height; + return; + case RR_Rotate_90: + case RR_Rotate_270: + *right = crtc->x + crtc->mode->mode.height; + *bottom = crtc->y + crtc->mode->mode.width; + return; } - WriteEventsToClient (client, 1, (xEvent *) &ce); } +/* overlapping counts as adjacent */ static Bool -RRCrtcPendingProperties (RRCrtcPtr crtc) +crtcs_adjacent(const RRCrtcPtr a, const RRCrtcPtr b) +{ + /* left, right, top, bottom... */ + int al, ar, at, ab; + int bl, br, bt, bb; + int cl, cr, ct, cb; /* the overlap, if any */ + + crtc_bounds(a, &al, &ar, &at, &ab); + crtc_bounds(b, &bl, &br, &bt, &bb); + + cl = max(al, bl); + cr = min(ar, br); + ct = max(at, bt); + cb = min(ab, bb); + + return (cl <= cr) && (ct <= cb); +} + +/* Depth-first search and mark all CRTCs reachable from cur */ +static void +mark_crtcs(rrScrPrivPtr pScrPriv, int *reachable, int cur) +{ + int i; + + reachable[cur] = TRUE; + for (i = 0; i < pScrPriv->numCrtcs; ++i) { + if (reachable[i] || !pScrPriv->crtcs[i]->mode) + continue; + if (crtcs_adjacent(pScrPriv->crtcs[cur], pScrPriv->crtcs[i])) + mark_crtcs(pScrPriv, reachable, i); + } +} + +static void +RRComputeContiguity(ScreenPtr pScreen) { - ScreenPtr pScreen = crtc->pScreen; rrScrPriv(pScreen); - int o; + Bool discontiguous = TRUE; + int i, n = pScrPriv->numCrtcs; + + int *reachable = xcalloc(n, sizeof(int)); - for (o = 0; o < pScrPriv->numOutputs; o++) - { - RROutputPtr output = pScrPriv->outputs[o]; - if (output->crtc == crtc && output->pendingProperties) - return TRUE; + if (!reachable) + goto out; + + /* Find first enabled CRTC and start search for reachable CRTCs from it */ + for (i = 0; i < n; ++i) { + if (pScrPriv->crtcs[i]->mode) { + mark_crtcs(pScrPriv, reachable, i); + break; + } + } + + /* Check that all enabled CRTCs were marked as reachable */ + for (i = 0; i < n; ++i) + if (pScrPriv->crtcs[i]->mode && !reachable[i]) + goto out; + + discontiguous = FALSE; + + out: + xfree(reachable); + pScrPriv->discontiguous = discontiguous; +} + +static void +rrDestroySharedPixmap(RRCrtcPtr crtc, PixmapPtr pPixmap) { +#ifndef NXAGENT_SERVER + ScreenPtr master = crtc->pScreen->current_master; + + if (master && pPixmap->master_pixmap) { + PixmapPtr mscreenpix = master->GetScreenPixmap(master); + + master->StopPixmapTracking(mscreenpix, pPixmap); + /* + * Unref the pixmap twice: once for the original reference, and once + * for the reference implicitly added by PixmapShareToSlave. + */ + master->DestroyPixmap(pPixmap->master_pixmap); + master->DestroyPixmap(pPixmap->master_pixmap); + } +#endif + + crtc->pScreen->DestroyPixmap(pPixmap); +} + +void +RRCrtcDetachScanoutPixmap(RRCrtcPtr crtc) +{ + rrScrPriv(crtc->pScreen); + + pScrPriv->rrCrtcSetScanoutPixmap(crtc, NULL); + if (crtc->scanout_pixmap) { + rrDestroySharedPixmap(crtc, crtc->scanout_pixmap); + } + crtc->scanout_pixmap = NULL; + RRCrtcChanged(crtc, TRUE); +} + +#ifndef NXAGENT_SERVER +static PixmapPtr +rrCreateSharedPixmap(RRCrtcPtr crtc, ScreenPtr master, + int width, int height, int depth, + int x, int y, Rotation rotation) +{ + Bool ret; + PixmapPtr mpix, spix; + rrScrPriv(crtc->pScreen); + + mpix = master->CreatePixmap(master, width, height, depth, + CREATE_PIXMAP_USAGE_SHARED); + if (!mpix) + return NULL; + + spix = PixmapShareToSlave(mpix, crtc->pScreen); + if (spix == NULL) { + master->DestroyPixmap(mpix); + return NULL; + } + + ret = pScrPriv->rrCrtcSetScanoutPixmap(crtc, spix); + if (ret == FALSE) { + rrDestroySharedPixmap(crtc, spix); + ErrorF("randr: failed to set shadow slave pixmap\n"); + return NULL; + } + + return spix; +} + +static Bool +rrSetupPixmapSharing(RRCrtcPtr crtc, int width, int height, + int x, int y, Rotation rotation) +{ + ScreenPtr master = crtc->pScreen->current_master; + int depth; + PixmapPtr mscreenpix; + PixmapPtr spix; + + /* 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 = mscreenpix->drawable.depth; + + if (crtc->scanout_pixmap) + RRCrtcDetachScanoutPixmap(crtc); + + if (width == 0 && height == 0) { + return TRUE; + } + + spix = rrCreateSharedPixmap(crtc, master, + width, height, depth, + x, y, rotation); + if (spix == NULL) { + return FALSE; + } + + crtc->scanout_pixmap = spix; + + master->StartPixmapTracking(mscreenpix, spix, x, y, 0, 0, rotation); + return TRUE; +} + +static void crtc_to_box(BoxPtr box, RRCrtcPtr crtc) +{ + box->x1 = crtc->x; + box->y1 = crtc->y; + switch (crtc->rotation) { + case RR_Rotate_0: + case RR_Rotate_180: + default: + box->x2 = crtc->x + crtc->mode->mode.width; + box->y2 = crtc->y + crtc->mode->mode.height; + break; + case RR_Rotate_90: + case RR_Rotate_270: + box->x2 = crtc->x + crtc->mode->mode.height; + box->y2 = crtc->y + crtc->mode->mode.width; + break; } - return FALSE; } +static Bool +rrCheckPixmapBounding(ScreenPtr pScreen, + RRCrtcPtr rr_crtc, Rotation rotation, + int x, int y, int w, int h) +{ + RegionRec root_pixmap_region, total_region, new_crtc_region; + int 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++) { + RRCrtcPtr crtc = pScrPriv->crtcs[c]; + + if (crtc == rr_crtc) { + newbox.x1 = x; + newbox.y1 = y; + if (rotation == RR_Rotate_90 || + rotation == RR_Rotate_270) { + newbox.x2 = x + h; + newbox.y2 = y + w; + } else { + newbox.x2 = x + w; + newbox.y2 = y + h; + } + } else { + if (!crtc->mode) + continue; + crtc_to_box(&newbox, crtc); + } + 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) { + rrScrPrivPtr slave_priv = rrGetScrPriv(slave); + for (c = 0; c < slave_priv->numCrtcs; c++) { + RRCrtcPtr slave_crtc = slave_priv->crtcs[c]; + + if (slave_crtc == rr_crtc) { + newbox.x1 = x; + newbox.y1 = y; + if (rotation == RR_Rotate_90 || + rotation == RR_Rotate_270) { + newbox.x2 = x + h; + newbox.y2 = y + w; + } else { + newbox.x2 = x + w; + newbox.y2 = y + h; + } + } + else { + if (!slave_crtc->mode) + continue; + crtc_to_box(&newbox, slave_crtc); + } + 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) { + } else { + pScrPriv->rrScreenSetSize(pScreen, new_width, new_height, 0, 0); + } + + /* set shatters TODO */ + return TRUE; +} +#endif /* !defined(NXAGENT_SERVER) */ + /* * Request that the Crtc be reconfigured */ Bool -RRCrtcSet (RRCrtcPtr crtc, - RRModePtr mode, - int x, - int y, - Rotation rotation, - int numOutputs, - RROutputPtr *outputs) -{ - ScreenPtr pScreen = crtc->pScreen; - Bool ret = FALSE; +RRCrtcSet(RRCrtcPtr crtc, + RRModePtr mode, + int x, + int y, Rotation rotation, int numOutputs, RROutputPtr * outputs) +{ + ScreenPtr pScreen = crtc->pScreen; + Bool ret = FALSE; + Bool recompute = TRUE; + Bool crtcChanged; + int o; + rrScrPriv(pScreen); + crtcChanged = FALSE; + for (o = 0; o < numOutputs; o++) { + if (outputs[o] && outputs[o]->crtc != crtc) { + crtcChanged = TRUE; + break; + } + } + /* See if nothing changed */ if (crtc->mode == mode && - crtc->x == x && - crtc->y == y && - crtc->rotation == rotation && - crtc->numOutputs == numOutputs && - !memcmp (crtc->outputs, outputs, numOutputs * sizeof (RROutputPtr)) && - !RRCrtcPendingProperties (crtc)) - { - ret = TRUE; + crtc->x == x && + crtc->y == y && + crtc->rotation == rotation && + crtc->numOutputs == numOutputs && + !memcmp(crtc->outputs, outputs, numOutputs * sizeof(RROutputPtr)) && + !RRCrtcPendingProperties(crtc) && !RRCrtcPendingTransform(crtc) && + !crtcChanged) { + recompute = FALSE; + ret = TRUE; } - else - { + else { +#ifndef NXAGENT_SERVER + if (pScreen->isGPU) { + ScreenPtr master = pScreen->current_master; + int width = 0, height = 0; + + if (mode) { + width = mode->mode.width; + height = mode->mode.height; + } + ret = rrCheckPixmapBounding(master, crtc, + rotation, x, y, width, height); + if (!ret) + return FALSE; + + if (pScreen->current_master) { + ret = rrSetupPixmapSharing(crtc, width, height, x, y, rotation); + } + } +#endif #if RANDR_12_INTERFACE - if (pScrPriv->rrCrtcSet) - { - ret = (*pScrPriv->rrCrtcSet) (pScreen, crtc, mode, x, y, - rotation, numOutputs, outputs); - } - else + if (pScrPriv->rrCrtcSet) { + ret = (*pScrPriv->rrCrtcSet) (pScreen, crtc, mode, x, y, + rotation, numOutputs, outputs); + } + else #endif - { + { #if RANDR_10_INTERFACE - if (pScrPriv->rrSetConfig) - { - RRScreenSize size; - RRScreenRate rate; - - if (!mode) - { - RRCrtcNotify (crtc, NULL, x, y, rotation, 0, NULL); - ret = TRUE; - } - else - { - size.width = mode->mode.width; - size.height = mode->mode.height; - if (outputs[0]->mmWidth && outputs[0]->mmHeight) - { - size.mmWidth = outputs[0]->mmWidth; - size.mmHeight = outputs[0]->mmHeight; - } - else - { - size.mmWidth = pScreen->mmWidth; - size.mmHeight = pScreen->mmHeight; - } - size.nRates = 1; - rate.rate = RRVerticalRefresh (&mode->mode); - size.pRates = &rate; - ret = (*pScrPriv->rrSetConfig) (pScreen, rotation, rate.rate, &size); - /* - * Old 1.0 interface tied screen size to mode size - */ - if (ret) - { - RRCrtcNotify (crtc, mode, x, y, rotation, 1, outputs); - RRScreenSizeNotify (pScreen); - } - } - } + if (pScrPriv->rrSetConfig) { + RRScreenSize size; + RRScreenRate rate; + + if (!mode) { + RRCrtcNotify(crtc, NULL, x, y, rotation, NULL, 0, NULL); + ret = TRUE; + } + else { + size.width = mode->mode.width; + size.height = mode->mode.height; + if (outputs[0]->mmWidth && outputs[0]->mmHeight) { + size.mmWidth = outputs[0]->mmWidth; + size.mmHeight = outputs[0]->mmHeight; + } + else { + size.mmWidth = pScreen->mmWidth; + size.mmHeight = pScreen->mmHeight; + } + size.nRates = 1; + rate.rate = RRVerticalRefresh(&mode->mode); + size.pRates = &rate; + ret = + (*pScrPriv->rrSetConfig) (pScreen, rotation, rate.rate, + &size); + /* + * Old 1.0 interface tied screen size to mode size + */ + if (ret) { + RRCrtcNotify(crtc, mode, x, y, rotation, NULL, 1, + outputs); + RRScreenSizeNotify(pScreen); + } + } + } #endif - } - if (ret) - { - int o; - RRTellChanged (pScreen); + } + if (ret) { + + RRTellChanged(pScreen); - for (o = 0; o < numOutputs; o++) - RRPostPendingProperties (outputs[o]); - } + for (o = 0; o < numOutputs; o++) + RRPostPendingProperties(outputs[o]); + } } + + if (recompute) + RRComputeContiguity(pScreen); + return ret; } /* + * Return crtc transform + */ +RRTransformPtr +RRCrtcGetTransform(RRCrtcPtr crtc) +{ + RRTransformPtr transform = &crtc->client_pending_transform; + + if (pixman_transform_is_identity(&transform->transform)) + return NULL; + return transform; +} + +/* + * Check whether the pending and current transforms are the same + */ +Bool +RRCrtcPendingTransform(RRCrtcPtr crtc) +{ + return memcmp(&crtc->client_current_transform.transform, + &crtc->client_pending_transform.transform, + sizeof(PictTransform)) != 0; +} + +/* * Destroy a Crtc at shutdown */ void -RRCrtcDestroy (RRCrtcPtr crtc) +RRCrtcDestroy(RRCrtcPtr crtc) { - FreeResource (crtc->id, 0); + FreeResource(crtc->id, 0); } static int -RRCrtcDestroyResource (void * value, XID pid) -{ - RRCrtcPtr crtc = (RRCrtcPtr) value; - ScreenPtr pScreen = crtc->pScreen; - - if (pScreen) - { - rrScrPriv(pScreen); - int i; - - for (i = 0; i < pScrPriv->numCrtcs; i++) - { - if (pScrPriv->crtcs[i] == crtc) - { - memmove (pScrPriv->crtcs + i, pScrPriv->crtcs + i + 1, - (pScrPriv->numCrtcs - (i + 1)) * sizeof (RRCrtcPtr)); - --pScrPriv->numCrtcs; - break; - } - } - } - if (crtc->gammaRed) - xfree (crtc->gammaRed); +RRCrtcDestroyResource(void *value, XID pid) +{ + RRCrtcPtr crtc = (RRCrtcPtr) value; + ScreenPtr pScreen = crtc->pScreen; + + if (pScreen) { + rrScrPriv(pScreen); + int i; + + for (i = 0; i < pScrPriv->numCrtcs; i++) { + if (pScrPriv->crtcs[i] == crtc) { + memmove(pScrPriv->crtcs + i, pScrPriv->crtcs + i + 1, + (pScrPriv->numCrtcs - (i + 1)) * sizeof(RRCrtcPtr)); + --pScrPriv->numCrtcs; + break; + } + } + + RRResourcesChanged(pScreen); + } + + if (crtc->scanout_pixmap) + RRCrtcDetachScanoutPixmap(crtc); + xfree(crtc->gammaRed); if (crtc->mode) - RRModeDestroy (crtc->mode); - xfree (crtc); + RRModeDestroy(crtc->mode); + xfree(crtc); return 1; } @@ -419,25 +790,45 @@ RRCrtcDestroyResource (void * value, XID pid) */ Bool -RRCrtcGammaSet (RRCrtcPtr crtc, - CARD16 *red, - CARD16 *green, - CARD16 *blue) +RRCrtcGammaSet(RRCrtcPtr crtc, CARD16 *red, CARD16 *green, CARD16 *blue) { - Bool ret = TRUE; + Bool ret = TRUE; + #if RANDR_12_INTERFACE - ScreenPtr pScreen = crtc->pScreen; + ScreenPtr pScreen = crtc->pScreen; #endif - - memcpy (crtc->gammaRed, red, crtc->gammaSize * sizeof (CARD16)); - memcpy (crtc->gammaGreen, green, crtc->gammaSize * sizeof (CARD16)); - memcpy (crtc->gammaBlue, blue, crtc->gammaSize * sizeof (CARD16)); + + memcpy(crtc->gammaRed, red, crtc->gammaSize * sizeof(CARD16)); + memcpy(crtc->gammaGreen, green, crtc->gammaSize * sizeof(CARD16)); + memcpy(crtc->gammaBlue, blue, crtc->gammaSize * sizeof(CARD16)); #if RANDR_12_INTERFACE - if (pScreen) - { - rrScrPriv(pScreen); - if (pScrPriv->rrCrtcSetGamma) - ret = (*pScrPriv->rrCrtcSetGamma) (pScreen, crtc); + if (pScreen) { + rrScrPriv(pScreen); + if (pScrPriv->rrCrtcSetGamma) + ret = (*pScrPriv->rrCrtcSetGamma) (pScreen, crtc); + } +#endif + return ret; +} + +/* + * Request current gamma back from the DDX (if possible). + * This includes gamma size. + */ +Bool +RRCrtcGammaGet(RRCrtcPtr crtc) +{ + Bool ret = TRUE; + +#if RANDR_12_INTERFACE + ScreenPtr pScreen = crtc->pScreen; +#endif + +#if RANDR_12_INTERFACE + if (pScreen) { + rrScrPriv(pScreen); + if (pScrPriv->rrCrtcGetGamma) + ret = (*pScrPriv->rrCrtcGetGamma) (pScreen, crtc); } #endif return ret; @@ -450,9 +841,31 @@ RRCrtcGammaSet (RRCrtcPtr crtc, */ Bool -RRCrtcGammaNotify (RRCrtcPtr crtc) +RRCrtcGammaNotify(RRCrtcPtr crtc) +{ + return TRUE; /* not much going on here */ +} + +static void +RRModeGetScanoutSize(RRModePtr mode, PictTransformPtr transform, + int *width, int *height) { - return TRUE; /* not much going on here */ + BoxRec box; + + if (mode == NULL) { + *width = 0; + *height = 0; + return; + } + + box.x1 = 0; + box.y1 = 0; + box.x2 = mode->mode.width; + box.y2 = mode->mode.height; + + pixman_transform_bounds(transform, &box); + *width = box.x2 - box.x1; + *height = box.y2 - box.y1; } /** @@ -461,24 +874,7 @@ RRCrtcGammaNotify (RRCrtcPtr crtc) void RRCrtcGetScanoutSize(RRCrtcPtr crtc, int *width, int *height) { - if (crtc->mode == NULL) { - *width = 0; - *height = 0; - return; - } - - switch (crtc->rotation & 0xf) { - case RR_Rotate_0: - case RR_Rotate_180: - *width = crtc->mode->mode.width; - *height = crtc->mode->mode.height; - break; - case RR_Rotate_90: - case RR_Rotate_270: - *width = crtc->mode->mode.height; - *height = crtc->mode->mode.width; - break; - } + RRModeGetScanoutSize(crtc->mode, &crtc->transform, width, height); } /* @@ -486,64 +882,125 @@ RRCrtcGetScanoutSize(RRCrtcPtr crtc, int *width, int *height) */ Bool -RRCrtcGammaSetSize (RRCrtcPtr crtc, - int size) +RRCrtcGammaSetSize(RRCrtcPtr crtc, int size) { - CARD16 *gamma; + CARD16 *gamma; if (size == crtc->gammaSize) - return TRUE; - if (size) - { - gamma = xalloc (size * 3 * sizeof (CARD16)); - if (!gamma) - return FALSE; + return TRUE; + if (size) { +#ifndef NXAGENT_SERVER + gamma = xallocarray(size, 3 * sizeof(CARD16)); +#else /* !defined(NXAGENT_SERVER) */ + gamma = xalloc(size * 3 * sizeof(CARD16)); +#endif /* !defined(NXAGENT_SERVER) */ + if (!gamma) + return FALSE; } else - gamma = NULL; - if (crtc->gammaRed) - xfree (crtc->gammaRed); + gamma = NULL; + xfree(crtc->gammaRed); crtc->gammaRed = gamma; crtc->gammaGreen = gamma + size; - crtc->gammaBlue = gamma + size*2; + crtc->gammaBlue = gamma + size * 2; crtc->gammaSize = size; return TRUE; } /* + * Set the pending CRTC transformation + */ + +int +RRCrtcTransformSet(RRCrtcPtr crtc, + PictTransformPtr transform, + struct pixman_f_transform *f_transform, + struct pixman_f_transform *f_inverse, + char *filter_name, + int filter_len, xFixed * params, int nparams) +{ + PictFilterPtr filter = NULL; + int width = 0, height = 0; + + if (!crtc->transforms) + return BadValue; + + if (filter_len) { + filter = PictureFindFilter(crtc->pScreen, filter_name, filter_len); + if (!filter) + return BadName; + if (filter->ValidateParams) { + if (!filter->ValidateParams(crtc->pScreen, filter->id, + params, nparams, &width, &height)) + return BadMatch; + } + else { + width = filter->width; + height = filter->height; + } + } + else { + if (nparams) + return BadMatch; + } + if (!RRTransformSetFilter(&crtc->client_pending_transform, + filter, params, nparams, width, height)) + return BadAlloc; + + crtc->client_pending_transform.transform = *transform; + crtc->client_pending_transform.f_transform = *f_transform; + crtc->client_pending_transform.f_inverse = *f_inverse; + return Success; +} + +/* * Initialize crtc type */ Bool -RRCrtcInit (void) +RRCrtcInit(void) { - RRCrtcType = CreateNewResourceType (RRCrtcDestroyResource); + RRCrtcType = CreateNewResourceType(RRCrtcDestroyResource +#ifndef NXAGENT_SERVER + , "CRTC" +#endif + ); if (!RRCrtcType) - return FALSE; - RegisterResourceName (RRCrtcType, "CRTC"); + return FALSE; + return TRUE; } +/* + * Initialize crtc type error value + */ +void +RRCrtcInitErrorValue(void) +{ +#ifndef NXAGENT_SERVER + SetResourceTypeErrorValue(RRCrtcType, RRErrorBase + BadRRCrtc); +#endif +} + int -ProcRRGetCrtcInfo (ClientPtr client) +ProcRRGetCrtcInfo(ClientPtr client) { REQUEST(xRRGetCrtcInfoReq); - xRRGetCrtcInfoReply rep; - RRCrtcPtr crtc; - CARD8 *extra; - unsigned long extraLen; - ScreenPtr pScreen; - rrScrPrivPtr pScrPriv; - RRModePtr mode; - RROutput *outputs; - RROutput *possible; - int i, j, k, n; - int width, height; - - REQUEST_SIZE_MATCH(xRRGetCrtcInfoReq); - crtc = LookupCrtc(client, stuff->crtc, DixReadAccess); + xRRGetCrtcInfoReply rep; + RRCrtcPtr crtc; + CARD8 *extra; + unsigned long extraLen; + ScreenPtr pScreen; + rrScrPrivPtr pScrPriv; + RRModePtr mode; + RROutput *outputs; + RROutput *possible; + int i, j, k; + int width, height; + BoxRec panned_area; + int n; - if (!crtc) - return RRErrorBase + BadRRCrtc; + REQUEST_SIZE_MATCH(xRRGetCrtcInfoReq); + VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess); /* All crtcs must be associated with screens before client * requests are processed @@ -552,206 +1009,210 @@ ProcRRGetCrtcInfo (ClientPtr client) pScrPriv = rrGetScrPriv(pScreen); mode = crtc->mode; - - rep.type = X_Reply; - rep.status = RRSetConfigSuccess; - rep.sequenceNumber = client->sequence; - rep.length = 0; - rep.timestamp = pScrPriv->lastSetTime.milliseconds; - rep.x = crtc->x; - rep.y = crtc->y; - RRCrtcGetScanoutSize (crtc, &width, &height); - rep.width = width; - rep.height = height; + + rep = (xRRGetCrtcInfoReply) { + .type = X_Reply, + .status = RRSetConfigSuccess, + .sequenceNumber = client->sequence, + .length = 0, + .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)) { + rep.x = panned_area.x1; + rep.y = panned_area.y1; + rep.width = panned_area.x2 - panned_area.x1; + rep.height = panned_area.y2 - panned_area.y1; + } + else { + RRCrtcGetScanoutSize(crtc, &width, &height); + rep.x = crtc->x; + rep.y = crtc->y; + rep.width = width; + rep.height = height; + } rep.mode = mode ? mode->mode.id : 0; rep.rotation = crtc->rotation; rep.rotations = crtc->rotations; rep.nOutput = crtc->numOutputs; k = 0; for (i = 0; i < pScrPriv->numOutputs; i++) - for (j = 0; j < pScrPriv->outputs[i]->numCrtcs; j++) - if (pScrPriv->outputs[i]->crtcs[j] == crtc) - k++; + for (j = 0; j < pScrPriv->outputs[i]->numCrtcs; j++) + if (pScrPriv->outputs[i]->crtcs[j] == crtc) + k++; rep.nPossibleOutput = k; - + rep.length = rep.nOutput + rep.nPossibleOutput; extraLen = rep.length << 2; - if (extraLen) - { - extra = xalloc (extraLen); - if (!extra) - return BadAlloc; + if (extraLen) { + extra = xalloc(extraLen); + if (!extra) + return BadAlloc; } else - extra = NULL; + extra = NULL; outputs = (RROutput *) extra; possible = (RROutput *) (outputs + rep.nOutput); - - for (i = 0; i < crtc->numOutputs; i++) - { - outputs[i] = crtc->outputs[i]->id; - if (client->swapped) - swapl (&outputs[i], n); + + for (i = 0; i < crtc->numOutputs; i++) { + outputs[i] = crtc->outputs[i]->id; + if (client->swapped) + swapl(&outputs[i], n); } k = 0; for (i = 0; i < pScrPriv->numOutputs; i++) - for (j = 0; j < pScrPriv->outputs[i]->numCrtcs; j++) - if (pScrPriv->outputs[i]->crtcs[j] == crtc) - { - possible[k] = pScrPriv->outputs[i]->id; - if (client->swapped) - swapl (&possible[k], n); - k++; - } - + for (j = 0; j < pScrPriv->outputs[i]->numCrtcs; j++) + if (pScrPriv->outputs[i]->crtcs[j] == crtc) { + possible[k] = pScrPriv->outputs[i]->id; + if (client->swapped) + swapl(&possible[k], n); + k++; + } + if (client->swapped) { - swaps(&rep.sequenceNumber, n); - swapl(&rep.length, n); - swapl(&rep.timestamp, n); - swaps(&rep.x, n); - swaps(&rep.y, n); - swaps(&rep.width, n); - swaps(&rep.height, n); - swapl(&rep.mode, n); - swaps(&rep.rotation, n); - swaps(&rep.rotations, n); - swaps(&rep.nOutput, n); - swaps(&rep.nPossibleOutput, n); - } - WriteToClient(client, sizeof(xRRGetCrtcInfoReply), (char *)&rep); - if (extraLen) - { - WriteToClient (client, extraLen, (char *) extra); - xfree (extra); - } - - return client->noClientException; + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.timestamp, n); + swaps(&rep.x, n); + swaps(&rep.y, n); + swaps(&rep.width, n); + swaps(&rep.height, n); + swapl(&rep.mode, n); + swaps(&rep.rotation, n); + swaps(&rep.rotations, n); + swaps(&rep.nOutput, n); + swaps(&rep.nPossibleOutput, n); + } + WriteToClient(client, sizeof(xRRGetCrtcInfoReply), (char *) &rep); + if (extraLen) { + WriteToClient(client, extraLen, (char *) extra); + xfree(extra); + } + + return Success; } int -ProcRRSetCrtcConfig (ClientPtr client) +ProcRRSetCrtcConfig(ClientPtr client) { REQUEST(xRRSetCrtcConfigReq); - xRRSetCrtcConfigReply rep; - ScreenPtr pScreen; - rrScrPrivPtr pScrPriv; - RRCrtcPtr crtc; - RRModePtr mode; - int numOutputs; - RROutputPtr *outputs = NULL; - RROutput *outputIds; - TimeStamp time; - Rotation rotation; - int i, j; - + xRRSetCrtcConfigReply rep; + ScreenPtr pScreen; + rrScrPrivPtr pScrPriv; + RRCrtcPtr crtc; + RRModePtr mode; + int numOutputs; + RROutputPtr *outputs = NULL; + RROutput *outputIds; + TimeStamp time; + Rotation rotation; + int +#ifndef NXAGENT_SERVER + ret, +#endif + i, j; + CARD8 status; + int n; + REQUEST_AT_LEAST_SIZE(xRRSetCrtcConfigReq); - numOutputs = (stuff->length - (SIZEOF (xRRSetCrtcConfigReq) >> 2)); - - crtc = LookupIDByType (stuff->crtc, RRCrtcType); - if (!crtc) - { - client->errorValue = stuff->crtc; - return RRErrorBase + BadRRCrtc; + numOutputs = (stuff->length - bytes_to_int32(SIZEOF(xRRSetCrtcConfigReq))); + + VERIFY_RR_CRTC(stuff->crtc, crtc, DixSetAttrAccess); + + if (stuff->mode == None) { + mode = NULL; + if (numOutputs > 0) + return BadMatch; } - if (stuff->mode == None) - { - mode = NULL; - if (numOutputs > 0) - return BadMatch; + else { + VERIFY_RR_MODE(stuff->mode, mode, DixSetAttrAccess); + if (numOutputs == 0) + return BadMatch; } - else - { - mode = LookupIDByType (stuff->mode, RRModeType); - if (!mode) - { - client->errorValue = stuff->mode; - return RRErrorBase + BadRRMode; - } - if (numOutputs == 0) - return BadMatch; - } - if (numOutputs) - { - outputs = xalloc (numOutputs * sizeof (RROutputPtr)); - if (!outputs) - return BadAlloc; + if (numOutputs) { +#ifndef NXAGENT_SERVER + outputs = xallocarray(numOutputs, sizeof(RROutputPtr)); +#else /* !defined(NXAGENT_SERVER) */ + outputs = xalloc(numOutputs * sizeof(RROutputPtr)); +#endif /* !defined(NXAGENT_SERVER) */ + if (!outputs) + return BadAlloc; } else - outputs = NULL; - + outputs = NULL; + outputIds = (RROutput *) (stuff + 1); - for (i = 0; i < numOutputs; i++) - { - outputs[i] = (RROutputPtr) LookupIDByType (outputIds[i], RROutputType); - if (!outputs[i]) - { - client->errorValue = outputIds[i]; - if (outputs) - xfree (outputs); - return RRErrorBase + BadRROutput; - } - /* validate crtc for this output */ - for (j = 0; j < outputs[i]->numCrtcs; j++) - if (outputs[i]->crtcs[j] == crtc) - break; - if (j == outputs[i]->numCrtcs) - { - if (outputs) - xfree (outputs); - return BadMatch; - } - /* validate mode for this output */ - for (j = 0; j < outputs[i]->numModes + outputs[i]->numUserModes; j++) - { - RRModePtr m = (j < outputs[i]->numModes ? - outputs[i]->modes[j] : - outputs[i]->userModes[j - outputs[i]->numModes]); - if (m == mode) - break; - } - if (j == outputs[i]->numModes + outputs[i]->numUserModes) - { - if (outputs) - xfree (outputs); - return BadMatch; - } + for (i = 0; i < numOutputs; i++) { +#ifndef NXAGENT_SERVER + ret = dixLookupResourceByType((void **) (outputs + i), outputIds[i], + RROutputType, client, DixSetAttrAccess); + + if (ret != Success) { + xfree(outputs); + return ret; + } +#else /* !defined(NXAGENT_SERVER) */ + outputs[i] = (RROutputPtr) LookupIDByType(outputIds[i], RROutputType); + if (!outputs[i]) { + client->errorValue = outputIds[i]; + if (outputs) + xfree(outputs); + return RRErrorBase + BadRROutput; + } +#endif /* !defined(NXAGENT_SERVER) */ + /* validate crtc for this output */ + for (j = 0; j < outputs[i]->numCrtcs; j++) + if (outputs[i]->crtcs[j] == crtc) + break; + if (j == outputs[i]->numCrtcs) { + xfree(outputs); + return BadMatch; + } + /* validate mode for this output */ + for (j = 0; j < outputs[i]->numModes + outputs[i]->numUserModes; j++) { + RRModePtr m = (j < outputs[i]->numModes ? + outputs[i]->modes[j] : + outputs[i]->userModes[j - outputs[i]->numModes]); + if (m == mode) + break; + } + if (j == outputs[i]->numModes + outputs[i]->numUserModes) { + xfree(outputs); + return BadMatch; + } } /* validate clones */ - for (i = 0; i < numOutputs; i++) - { - for (j = 0; j < numOutputs; j++) - { - int k; - if (i == j) - continue; - for (k = 0; k < outputs[i]->numClones; k++) - { - if (outputs[i]->clones[k] == outputs[j]) - break; - } - if (k == outputs[i]->numClones) - { - if (outputs) - xfree (outputs); - return BadMatch; - } - } + for (i = 0; i < numOutputs; i++) { + for (j = 0; j < numOutputs; j++) { + int k; + + if (i == j) + continue; + for (k = 0; k < outputs[i]->numClones; k++) { + if (outputs[i]->clones[k] == outputs[j]) + break; + } + if (k == outputs[i]->numClones) { + xfree(outputs); + return BadMatch; + } + } } pScreen = crtc->pScreen; pScrPriv = rrGetScrPriv(pScreen); - + time = ClientTimeToServerTime(stuff->timestamp); - - if (!pScrPriv) - { - time = currentTime; - rep.status = RRSetConfigFailed; - goto sendReply; + + if (!pScrPriv) { + time = currentTime; + status = RRSetConfigFailed; + goto sendReply; } - + /* * Validate requested rotation */ @@ -763,201 +1224,677 @@ ProcRRSetCrtcConfig (ClientPtr client) case RR_Rotate_90: case RR_Rotate_180: case RR_Rotate_270: - break; + break; default: - /* - * Invalid rotation - */ - client->errorValue = stuff->rotation; - if (outputs) - xfree (outputs); - return BadValue; - } - - if (mode) - { - if ((~crtc->rotations) & rotation) - { - /* - * requested rotation or reflection not supported by screen - */ - client->errorValue = stuff->rotation; - if (outputs) - xfree (outputs); - return BadMatch; - } - + /* + * Invalid rotation + */ + client->errorValue = stuff->rotation; + xfree(outputs); + return BadValue; + } + + if (mode) { + if ((~crtc->rotations) & rotation) { + /* + * requested rotation or reflection not supported by screen + */ + client->errorValue = stuff->rotation; + xfree(outputs); + return BadMatch; + } + #ifdef RANDR_12_INTERFACE - /* - * Check screen size bounds if the DDX provides a 1.2 interface - * for setting screen size. Else, assume the CrtcSet sets - * the size along with the mode - */ - if (pScrPriv->rrScreenSetSize) - { - int source_width = mode->mode.width; - int source_height = mode->mode.height; - - if ((rotation & 0xf) == RR_Rotate_90 || (rotation & 0xf) == RR_Rotate_270) - { - source_width = mode->mode.height; - source_height = mode->mode.width; - } - if (stuff->x + source_width > pScreen->width) - { - client->errorValue = stuff->x; - if (outputs) - xfree (outputs); - return BadValue; - } - - if (stuff->y + source_height > pScreen->height) - { - client->errorValue = stuff->y; - if (outputs) - xfree (outputs); - return BadValue; - } - } + /* + * Check screen size bounds if the DDX provides a 1.2 interface + * for setting screen size. Else, assume the CrtcSet sets + * the size along with the mode. If the driver supports transforms, + * then it must allow crtcs to display a subset of the screen, so + * only do this check for drivers without transform support. + */ + if (pScrPriv->rrScreenSetSize && !crtc->transforms) { + int source_width; + int source_height; + PictTransform transform; + struct pixman_f_transform f_transform, f_inverse; + int width, height; + +#ifndef NXAGENT_SERVER + if (pScreen->isGPU) { + width = pScreen->current_master->width; + height = pScreen->current_master->height; + } + else +#else /* !defined(NXAGENT_SERVER) */ + { + width = pScreen->width; + height = pScreen->height; + } +#endif /* !defined(NXAGENT_SERVER) */ + + RRTransformCompute(stuff->x, stuff->y, + mode->mode.width, mode->mode.height, + rotation, + &crtc->client_pending_transform, + &transform, &f_transform, &f_inverse); + + RRModeGetScanoutSize(mode, &transform, &source_width, + &source_height); + if (stuff->x + source_width > width) { + client->errorValue = stuff->x; + xfree(outputs); + return BadValue; + } + + if (stuff->y + source_height > height) { + client->errorValue = stuff->y; + xfree(outputs); + return BadValue; + } + } #endif } - - /* - * Make sure the requested set-time is not older than - * the last set-time + + if (!RRCrtcSet(crtc, mode, stuff->x, stuff->y, + rotation, numOutputs, outputs)) { + status = RRSetConfigFailed; + goto sendReply; + } + status = RRSetConfigSuccess; + pScrPriv->lastSetTime = time; + + sendReply: + xfree(outputs); + + rep = (xRRSetCrtcConfigReply) { + .type = X_Reply, + .status = status, + .sequenceNumber = client->sequence, + .length = 0, + .newTimestamp = pScrPriv->lastSetTime.milliseconds + }; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.newTimestamp, n); + } + WriteToClient(client, sizeof(xRRSetCrtcConfigReply), (char *) &rep); + + return Success; +} + +int +ProcRRGetPanning(ClientPtr client) +{ + REQUEST(xRRGetPanningReq); + xRRGetPanningReply rep; + RRCrtcPtr crtc; + ScreenPtr pScreen; + rrScrPrivPtr pScrPriv; + BoxRec total; + BoxRec tracking; + INT16 border[4]; + int n; + + REQUEST_SIZE_MATCH(xRRGetPanningReq); + VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess); + + /* All crtcs must be associated with screens before client + * requests are processed */ - if (CompareTimeStamps (time, pScrPriv->lastSetTime) < 0) - { - rep.status = RRSetConfigInvalidTime; - goto sendReply; + pScreen = crtc->pScreen; + pScrPriv = rrGetScrPriv(pScreen); + + if (!pScrPriv) + return RRErrorBase + BadRRCrtc; + + rep = (xRRGetPanningReply) { + .type = X_Reply, + .status = RRSetConfigSuccess, + .sequenceNumber = client->sequence, + .length = 1, + .timestamp = pScrPriv->lastSetTime.milliseconds + }; + if (pScrPriv->rrGetPanning && + pScrPriv->rrGetPanning(pScreen, crtc, &total, &tracking, border)) { + rep.left = total.x1; + rep.top = total.y1; + rep.width = total.x2 - total.x1; + rep.height = total.y2 - total.y1; + rep.track_left = tracking.x1; + rep.track_top = tracking.y1; + rep.track_width = tracking.x2 - tracking.x1; + rep.track_height = tracking.y2 - tracking.y1; + rep.border_left = border[0]; + rep.border_top = border[1]; + rep.border_right = border[2]; + rep.border_bottom = border[3]; + } + + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.timestamp, n); + swaps(&rep.left, n); + swaps(&rep.top, n); + swaps(&rep.width, n); + swaps(&rep.height, n); + swaps(&rep.track_left, n); + swaps(&rep.track_top, n); + swaps(&rep.track_width, n); + swaps(&rep.track_height, n); + swaps(&rep.border_left, n); + swaps(&rep.border_top, n); + swaps(&rep.border_right, n); + swaps(&rep.border_bottom, n); } + WriteToClient(client, sizeof(xRRGetPanningReply), (char *) &rep); + return Success; +} + +int +ProcRRSetPanning(ClientPtr client) +{ + REQUEST(xRRSetPanningReq); + xRRSetPanningReply rep; + RRCrtcPtr crtc; + ScreenPtr pScreen; + rrScrPrivPtr pScrPriv; + TimeStamp time; + BoxRec total; + BoxRec tracking; + INT16 border[4]; + CARD8 status; + int n; + + REQUEST_SIZE_MATCH(xRRSetPanningReq); + VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess); + + /* All crtcs must be associated with screens before client + * requests are processed + */ + pScreen = crtc->pScreen; + pScrPriv = rrGetScrPriv(pScreen); - if (!RRCrtcSet (crtc, mode, stuff->x, stuff->y, - rotation, numOutputs, outputs)) - { - rep.status = RRSetConfigFailed; - goto sendReply; + if (!pScrPriv) { + time = currentTime; + status = RRSetConfigFailed; + goto sendReply; } - rep.status = RRSetConfigSuccess; + + time = ClientTimeToServerTime(stuff->timestamp); + + if (!pScrPriv->rrGetPanning) + return RRErrorBase + BadRRCrtc; + + total.x1 = stuff->left; + total.y1 = stuff->top; + total.x2 = total.x1 + stuff->width; + total.y2 = total.y1 + stuff->height; + tracking.x1 = stuff->track_left; + tracking.y1 = stuff->track_top; + tracking.x2 = tracking.x1 + stuff->track_width; + tracking.y2 = tracking.y1 + stuff->track_height; + border[0] = stuff->border_left; + border[1] = stuff->border_top; + border[2] = stuff->border_right; + border[3] = stuff->border_bottom; + + if (!pScrPriv->rrSetPanning(pScreen, crtc, &total, &tracking, border)) + return BadMatch; + pScrPriv->lastSetTime = time; - -sendReply: - if (outputs) - xfree (outputs); - - rep.type = X_Reply; - /* rep.status has already been filled in */ - rep.length = 0; - rep.sequenceNumber = client->sequence; - rep.newTimestamp = pScrPriv->lastSetTime.milliseconds; - - if (client->swapped) - { - int n; - swaps(&rep.sequenceNumber, n); - swapl(&rep.length, n); - swapl(&rep.newTimestamp, n); - } - WriteToClient(client, sizeof(xRRSetCrtcConfigReply), (char *)&rep); - - return client->noClientException; + + status = RRSetConfigSuccess; + + sendReply: + rep = (xRRSetPanningReply) { + .type = X_Reply, + .status = status, + .sequenceNumber = client->sequence, + .length = 0, + .newTimestamp = pScrPriv->lastSetTime.milliseconds + }; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.newTimestamp, n); + } + WriteToClient(client, sizeof(xRRSetPanningReply), (char *) &rep); + return Success; } int -ProcRRGetCrtcGammaSize (ClientPtr client) +ProcRRGetCrtcGammaSize(ClientPtr client) { REQUEST(xRRGetCrtcGammaSizeReq); - xRRGetCrtcGammaSizeReply reply; - RRCrtcPtr crtc; - int n; + xRRGetCrtcGammaSizeReply reply; + RRCrtcPtr crtc; + int n; REQUEST_SIZE_MATCH(xRRGetCrtcGammaSizeReq); - crtc = LookupCrtc (client, stuff->crtc, DixReadAccess); - if (!crtc) - return RRErrorBase + BadRRCrtc; - - reply.type = X_Reply; - reply.sequenceNumber = client->sequence; - reply.length = 0; - reply.size = crtc->gammaSize; + VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess); + + /* Gamma retrieval failed, any better error? */ + if (!RRCrtcGammaGet(crtc)) + return RRErrorBase + BadRRCrtc; + + reply = (xRRGetCrtcGammaSizeReply) { + .type = X_Reply, + .sequenceNumber = client->sequence, + .length = 0, + .size = crtc->gammaSize + }; if (client->swapped) { - swaps (&reply.sequenceNumber, n); - swapl (&reply.length, n); - swaps (&reply.size, n); + swaps(&reply.sequenceNumber, n); + swapl(&reply.length, n); + swaps(&reply.size, n); } - WriteToClient (client, sizeof (xRRGetCrtcGammaSizeReply), (char *) &reply); - return client->noClientException; + WriteToClient(client, sizeof(xRRGetCrtcGammaSizeReply), (char *) &reply); + return Success; } int -ProcRRGetCrtcGamma (ClientPtr client) +ProcRRGetCrtcGamma(ClientPtr client) { REQUEST(xRRGetCrtcGammaReq); - xRRGetCrtcGammaReply reply; - RRCrtcPtr crtc; - int n; - unsigned long len; - char *extra; - + xRRGetCrtcGammaReply reply; + RRCrtcPtr crtc; + unsigned long len; + char *extra = NULL; + int n; + REQUEST_SIZE_MATCH(xRRGetCrtcGammaReq); - crtc = LookupCrtc (client, stuff->crtc, DixReadAccess); - if (!crtc) - return RRErrorBase + BadRRCrtc; - + VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess); + + /* Gamma retrieval failed, any better error? */ + if (!RRCrtcGammaGet(crtc)) + return RRErrorBase + BadRRCrtc; + len = crtc->gammaSize * 3 * 2; - + if (crtc->gammaSize) { - extra = xalloc(len); - if (!extra) - return BadAlloc; + extra = xalloc(len); + if (!extra) + return BadAlloc; } - reply.type = X_Reply; - reply.sequenceNumber = client->sequence; - reply.length = (len + 3) >> 2; - reply.size = crtc->gammaSize; + reply = (xRRGetCrtcGammaReply) { + .type = X_Reply, + .sequenceNumber = client->sequence, + .length = bytes_to_int32(len), + .size = crtc->gammaSize + }; if (client->swapped) { - swaps (&reply.sequenceNumber, n); - swapl (&reply.length, n); - swaps (&reply.size, n); + swaps(&reply.sequenceNumber, n); + swapl(&reply.length, n); + swaps(&reply.size, n); } - WriteToClient (client, sizeof (xRRGetCrtcGammaReply), (char *) &reply); - if (crtc->gammaSize) - { - memcpy(extra, crtc->gammaRed, len); - client->pSwapReplyFunc = (ReplySwapPtr)CopySwap16Write; - WriteSwappedDataToClient (client, len, extra); - xfree(extra); + WriteToClient(client, sizeof(xRRGetCrtcGammaReply), (char *) &reply); + if (crtc->gammaSize) { + memcpy(extra, crtc->gammaRed, len); + client->pSwapReplyFunc = (ReplySwapPtr) CopySwap16Write; + WriteSwappedDataToClient(client, len, extra); + xfree(extra); } - return client->noClientException; + return Success; } int -ProcRRSetCrtcGamma (ClientPtr client) +ProcRRSetCrtcGamma(ClientPtr client) { REQUEST(xRRSetCrtcGammaReq); - RRCrtcPtr crtc; - unsigned long len; - CARD16 *red, *green, *blue; - + RRCrtcPtr crtc; + unsigned long len; + CARD16 *red, *green, *blue; + REQUEST_AT_LEAST_SIZE(xRRSetCrtcGammaReq); - crtc = LookupCrtc (client, stuff->crtc, DixWriteAccess); - if (!crtc) - return RRErrorBase + BadRRCrtc; - - len = client->req_len - (sizeof (xRRSetCrtcGammaReq) >> 2); + VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess); + + len = client->req_len - bytes_to_int32(sizeof(xRRSetCrtcGammaReq)); if (len < (stuff->size * 3 + 1) >> 1) - return BadLength; + return BadLength; if (stuff->size != crtc->gammaSize) - return BadMatch; - + return BadMatch; + red = (CARD16 *) (stuff + 1); green = red + crtc->gammaSize; blue = green + crtc->gammaSize; - - RRCrtcGammaSet (crtc, red, green, blue); + RRCrtcGammaSet(crtc, red, green, blue); + + return Success; +} + +/* Version 1.3 additions */ + +int +ProcRRSetCrtcTransform(ClientPtr client) +{ + REQUEST(xRRSetCrtcTransformReq); + RRCrtcPtr crtc; + PictTransform transform; + struct pixman_f_transform f_transform, f_inverse; + char *filter; + int nbytes; + xFixed *params; + int nparams; + + REQUEST_AT_LEAST_SIZE(xRRSetCrtcTransformReq); + VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess); + + PictTransform_from_xRenderTransform(&transform, &stuff->transform); + pixman_f_transform_from_pixman_transform(&f_transform, &transform); + if (!pixman_f_transform_invert(&f_inverse, &f_transform)) + return BadMatch; + + filter = (char *) (stuff + 1); + nbytes = stuff->nbytesFilter; + params = (xFixed *) (filter + pad_to_int32(nbytes)); + nparams = ((xFixed *) stuff + client->req_len) - params; + if (nparams < 0) + return BadLength; + + return RRCrtcTransformSet(crtc, &transform, &f_transform, &f_inverse, + filter, nbytes, params, nparams); +} + +#define CrtcTransformExtra (SIZEOF(xRRGetCrtcTransformReply) - 32) + +static int +transform_filter_length(RRTransformPtr transform) +{ + int nbytes, nparams; + + if (transform->filter == NULL) + return 0; + nbytes = strlen(transform->filter->name); + nparams = transform->nparams; + return pad_to_int32(nbytes) + (nparams * sizeof(xFixed)); +} + +static int +transform_filter_encode(ClientPtr client, char *output, + CARD16 *nbytesFilter, + CARD16 *nparamsFilter, RRTransformPtr transform) +{ + int nbytes, nparams; + int n; + + if (transform->filter == NULL) { + *nbytesFilter = 0; + *nparamsFilter = 0; + return 0; + } + nbytes = strlen(transform->filter->name); + nparams = transform->nparams; + *nbytesFilter = nbytes; + *nparamsFilter = nparams; + memcpy(output, transform->filter->name, nbytes); + while ((nbytes & 3) != 0) + output[nbytes++] = 0; + memcpy(output + nbytes, transform->params, nparams * sizeof(xFixed)); + if (client->swapped) { + swaps(nbytesFilter, n); + swaps(nparamsFilter, n); + SwapLongs((CARD32 *) (output + nbytes), nparams); + } + nbytes += nparams * sizeof(xFixed); + return nbytes; +} + +static void +transform_encode(ClientPtr client, xRenderTransform * wire, + PictTransform * pict) +{ + xRenderTransform_from_PictTransform(wire, pict); + if (client->swapped) + SwapLongs((CARD32 *) wire, bytes_to_int32(sizeof(xRenderTransform))); +} + +int +ProcRRGetCrtcTransform(ClientPtr client) +{ + REQUEST(xRRGetCrtcTransformReq); + xRRGetCrtcTransformReply *reply; + RRCrtcPtr crtc; + int nextra; + RRTransformPtr current, pending; + char *extra; + int n; + + REQUEST_SIZE_MATCH(xRRGetCrtcTransformReq); + VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess); + + pending = &crtc->client_pending_transform; + current = &crtc->client_current_transform; + + nextra = (transform_filter_length(pending) + + transform_filter_length(current)); + + reply = xcalloc(1, sizeof(xRRGetCrtcTransformReply) + nextra); + if (!reply) + return BadAlloc; + + extra = (char *) (reply + 1); + reply->type = X_Reply; + reply->sequenceNumber = client->sequence; + reply->length = bytes_to_int32(CrtcTransformExtra + nextra); + + reply->hasTransforms = crtc->transforms; + + transform_encode(client, &reply->pendingTransform, &pending->transform); + extra += transform_filter_encode(client, extra, + &reply->pendingNbytesFilter, + &reply->pendingNparamsFilter, pending); + + transform_encode(client, &reply->currentTransform, ¤t->transform); + extra += transform_filter_encode(client, extra, + &reply->currentNbytesFilter, + &reply->currentNparamsFilter, current); + + if (client->swapped) { + swaps(&reply->sequenceNumber, n); + swapl(&reply->length, n); + } + WriteToClient(client, sizeof(xRRGetCrtcTransformReply) + nextra, + (char *) reply); + xfree(reply); return Success; } +static Bool +check_all_screen_crtcs(ScreenPtr pScreen, int *x, int *y) +{ + rrScrPriv(pScreen); + int i; + for (i = 0; i < pScrPriv->numCrtcs; i++) { + RRCrtcPtr crtc = pScrPriv->crtcs[i]; + + int left, right, top, bottom; + + if (!crtc->mode) + continue; + + crtc_bounds(crtc, &left, &right, &top, &bottom); + + if ((*x >= left) && (*x < right) && (*y >= top) && (*y < bottom)) + return TRUE; + } + return FALSE; +} + +static Bool +constrain_all_screen_crtcs( +#ifndef NXAGENT_SERVER + DeviceIntPtr pDev, +#endif /* !defined(NXAGENT_SERVER) */ + 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++) { + RRCrtcPtr crtc = pScrPriv->crtcs[i]; + int nx, ny; + int left, right, top, bottom; + + if (!crtc->mode) + continue; + + crtc_bounds(crtc, &left, &right, &top, &bottom); +#ifndef NXAGENT_SERVER + miPointerGetPosition(pDev, &nx, &ny); +#else /* !defined(NXAGENT_SERVER) */ + + miPointerPosition(&nx, &ny); +#endif /* !defined(NXAGENT_SERVER) */ + + if ((nx >= left) && (nx < right) && (ny >= top) && (ny < bottom)) { + if (*x < left) + *x = left; + if (*x >= right) + *x = right - 1; + if (*y < top) + *y = top; + if (*y >= bottom) + *y = bottom - 1; + + return TRUE; + } + } + return FALSE; +} + +void +RRConstrainCursorHarder( +#ifndef NXAGENT_SERVER + DeviceIntPtr pDev, +#endif /* !defined(NXAGENT_SERVER) */ + ScreenPtr pScreen, int mode, int *x, + int *y) +{ + rrScrPriv(pScreen); + Bool ret; +#ifndef NXAGENT_SERVER + ScreenPtr slave; +#endif + + /* 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; + +#ifndef NXAGENT_SERVER + xorg_list_for_each_entry(slave, &pScreen->output_slave_list, output_head) { + ret = check_all_screen_crtcs(slave, x, y); + if (ret == TRUE) + return; + } +#endif /* !defined(NXAGENT_SERVER) */ + + /* if we're trying to escape, clamp to the CRTC we're coming from */ + ret = constrain_all_screen_crtcs( +#ifndef NXAGENT_SERVER + pDev, +#endif /* !defined(NXAGENT_SERVER) */ + pScreen, x, y); + if (ret == TRUE) + return; + +#ifndef NXAGENT_SERVER + 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; + } +#endif /* !defined(NXAGENT_SERVER) */ +} + +Bool +RRReplaceScanoutPixmap(DrawablePtr pDrawable, PixmapPtr pPixmap, Bool enable) +{ + rrScrPriv(pDrawable->pScreen); + Bool ret = TRUE; + PixmapPtr *saved_scanout_pixmap; + int i; + + saved_scanout_pixmap = xalloc(sizeof(PixmapPtr) * pScrPriv->numCrtcs); + if (saved_scanout_pixmap == NULL) + return FALSE; + + for (i = 0; i < pScrPriv->numCrtcs; i++) { + RRCrtcPtr crtc = pScrPriv->crtcs[i]; + Bool size_fits; + + saved_scanout_pixmap[i] = crtc->scanout_pixmap; + + if (!crtc->mode && enable) + continue; + if (!crtc->scanout_pixmap && !enable) + continue; + + size_fits = (crtc->mode && + crtc->x == pDrawable->x && + crtc->y == pDrawable->y && + crtc->mode->mode.width == pDrawable->width && + crtc->mode->mode.height == pDrawable->height); + + /* 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; + } + else if (!size_fits) { + /* if the size no longer fits then drop off */ + crtc->scanout_pixmap = NULL; + pScrPriv->rrCrtcSetScanoutPixmap(crtc, crtc->scanout_pixmap); + + (*pScrPriv->rrCrtcSet) (pDrawable->pScreen, crtc, crtc->mode, crtc->x, crtc->y, + crtc->rotation, crtc->numOutputs, crtc->outputs); + saved_scanout_pixmap[i] = crtc->scanout_pixmap; + ret = FALSE; + } + else { + /* if the size fits then we are already setup */ + } + } + else { + if (!size_fits) + ret = FALSE; + else if (enable) + crtc->scanout_pixmap = pPixmap; + else + /* reject an attempt to disable someone else's scanout_pixmap */ + ret = FALSE; + } + } + + for (i = 0; i < pScrPriv->numCrtcs; i++) { + RRCrtcPtr crtc = pScrPriv->crtcs[i]; + + if (crtc->scanout_pixmap == saved_scanout_pixmap[i]) + continue; + + if (ret) { + pScrPriv->rrCrtcSetScanoutPixmap(crtc, crtc->scanout_pixmap); + + (*pScrPriv->rrCrtcSet) (pDrawable->pScreen, crtc, crtc->mode, + crtc->x, crtc->y, crtc->rotation, + crtc->numOutputs, crtc->outputs); + } + else + crtc->scanout_pixmap = saved_scanout_pixmap[i]; + } + xfree(saved_scanout_pixmap); + + return ret; +} |