diff options
Diffstat (limited to 'randr')
-rw-r--r-- | randr/Makefile.am | 1 | ||||
-rw-r--r-- | randr/mirrcrtc.c | 3 | ||||
-rw-r--r-- | randr/randr.c | 15 | ||||
-rw-r--r-- | randr/randrstr.h | 48 | ||||
-rw-r--r-- | randr/rrcrtc.c | 31 | ||||
-rw-r--r-- | randr/rrinfo.c | 2 | ||||
-rw-r--r-- | randr/rrpixmap.c | 154 | ||||
-rw-r--r-- | randr/rrscreen.c | 8 |
8 files changed, 246 insertions, 16 deletions
diff --git a/randr/Makefile.am b/randr/Makefile.am index a1c88dcb8..b7664c686 100644 --- a/randr/Makefile.am +++ b/randr/Makefile.am @@ -16,6 +16,7 @@ librandr_la_SOURCES = \ rrinfo.c \ rrmode.c \ rroutput.c \ + rrpixmap.c \ rrpointer.c \ rrproperty.c \ rrscreen.c \ diff --git a/randr/mirrcrtc.c b/randr/mirrcrtc.c index b1e2c9f34..cc76797d6 100644 --- a/randr/mirrcrtc.c +++ b/randr/mirrcrtc.c @@ -66,7 +66,8 @@ miRRSetCrtcConfig(RRCrtcConfigPtr crtc_config) y, crtc_config->rotation, crtc_config->numOutputs, - crtc_config->outputs); + crtc_config->outputs, + crtc_config->pixmap); } Bool diff --git a/randr/randr.c b/randr/randr.c index 607770520..c22657ee2 100644 --- a/randr/randr.c +++ b/randr/randr.c @@ -98,6 +98,7 @@ RRCloseScreen (int i, ScreenPtr pScreen) free(pScrPriv->crtcs); free(pScrPriv->outputs); + free(pScrPriv->scanout_info); free(pScrPriv); RRNScreens -= 1; /* ok, one fewer screen with RandR running */ return (*pScreen->CloseScreen) (i, pScreen); @@ -248,6 +249,8 @@ Bool RRScreenInit(ScreenPtr pScreen) pScrPriv->rrCrtcSet = NULL; pScrPriv->rrCrtcSetGamma = NULL; #endif + pScrPriv->scanout_info = NULL; + pScrPriv->n_scanout_info = 0; #if RANDR_10_INTERFACE pScrPriv->rrSetConfig = 0; pScrPriv->rotations = RR_Rotate_0; @@ -482,6 +485,18 @@ RRVerticalRefresh (xRRModeInfo *mode) return (CARD16) refresh; } +RRScanoutPixmapInfo * +RRQueryScanoutPixmapInfo(ScreenPtr screen, int *n_info) +{ + rrScrPriv(screen); + + if (!pScrPriv->scanout_info && pScrPriv->rrQueryScanoutPixmaps) + pScrPriv->scanout_info = pScrPriv->rrQueryScanoutPixmaps(screen, + &pScrPriv->n_scanout_info); + *n_info = pScrPriv->n_scanout_info; + return pScrPriv->scanout_info; +} + static int ProcRRDispatch (ClientPtr client) { diff --git a/randr/randrstr.h b/randr/randrstr.h index 2fe960234..c23197219 100644 --- a/randr/randrstr.h +++ b/randr/randrstr.h @@ -123,6 +123,7 @@ struct _rrCrtc { CARD16 *gammaGreen; void *devPrivate; Bool transforms; + PixmapPtr scanoutPixmap; RRTransformRec client_pending_transform; RRTransformRec client_current_transform; PictTransform client_sprite_position_transform; @@ -198,7 +199,8 @@ typedef Bool (*RRCrtcSetProcPtr) (ScreenPtr pScreen, int y, Rotation rotation, int numOutputs, - RROutputPtr *outputs); + RROutputPtr *outputs, + PixmapPtr scanout_pixmap); typedef Bool (*RRCrtcSetGammaProcPtr) (ScreenPtr pScreen, RRCrtcPtr crtc); @@ -264,6 +266,20 @@ typedef Bool (*RRSetConfigProcPtr) (ScreenPtr pScreen, #endif +typedef struct { + PictFormatPtr format; + int maxWidth, maxHeight; + int depth; + Rotation rotations; +} RRScanoutPixmapInfo; + +typedef RRScanoutPixmapInfo *(*RRQueryScanoutPixmapsPtr) (ScreenPtr pScreen, + int *num_info); + +typedef PixmapPtr (*RRCreateScanoutPixmapPtr) (ScreenPtr pScreen, + int width, int height, int depth, + Rotation rotations, + PictFormatPtr format); typedef void (*RRSetCrtcSpriteTransformPtr) (ScreenPtr pScreen, RRCrtcPtr randr_crtc, @@ -303,6 +319,8 @@ typedef struct _rrScrPriv { RRGetPanningProcPtr rrGetPanning; RRSetPanningProcPtr rrSetPanning; #endif + RRQueryScanoutPixmapsPtr rrQueryScanoutPixmaps; + RRCreateScanoutPixmapPtr rrCreateScanoutPixmap; RRSetCrtcSpriteTransformPtr rrSetCrtcSpriteTransform; RRGetCrtcSpriteTransformPtr rrGetCrtcSpriteTransform; RRSetCrtcConfigsPtr rrSetCrtcConfigs; @@ -333,6 +351,8 @@ typedef struct _rrScrPriv { /* Last known pointer position */ RRCrtcPtr pointerCrtc; + RRScanoutPixmapInfo *scanout_info; + int n_scanout_info; #ifdef RANDR_10_INTERFACE /* * Configuration information @@ -347,6 +367,7 @@ typedef struct _rrScrPriv { int rate; int size; #endif + } rrScrPrivRec, *rrScrPrivPtr; extern _X_EXPORT DevPrivateKeyRec rrPrivKeyRec; @@ -521,6 +542,9 @@ RRGetRotation (ScreenPtr pScreen); extern _X_EXPORT CARD16 RRVerticalRefresh (xRRModeInfo *mode); +extern _X_EXPORT RRScanoutPixmapInfo * +RRQueryScanoutPixmapInfo(ScreenPtr screen, int *n_info); + #ifdef RANDR_10_INTERFACE /* * This is the old interface, deprecated but left @@ -599,7 +623,8 @@ RRCrtcNotify (RRCrtcPtr crtc, Rotation rotation, RRTransformPtr transform, int numOutputs, - RROutputPtr *outputs); + RROutputPtr *outputs, + PixmapPtr scanoutPixmap); extern _X_EXPORT void RRDeliverCrtcEvent (ClientPtr client, WindowPtr pWin, RRCrtcPtr crtc); @@ -614,7 +639,8 @@ RRCrtcSet (RRCrtcPtr crtc, int y, Rotation rotation, int numOutput, - RROutputPtr *outputs); + RROutputPtr *outputs, + PixmapPtr scanout_pixmap); /* * Request that the Crtc gamma be changed @@ -643,6 +669,10 @@ RRCrtcGammaGet(RRCrtcPtr crtc); extern _X_EXPORT Bool RRCrtcGammaNotify (RRCrtcPtr crtc); +void +RRModeGetScanoutSize (RRModePtr mode, struct pixman_f_transform *transform, + int *width, int *height); + /* * Set the size of the gamma table at server startup time */ @@ -778,11 +808,23 @@ RRCrtcSpriteTransformSet(RRCrtcPtr crtc, struct pict_f_transform *f_image_transform); int +ProcRRQueryScanoutPixmaps (ClientPtr client); + +int +ProcRRCreateScanoutPixmap (ClientPtr client); + +int +ProcRRSetCrtcPixmapConfig (ClientPtr client); + +int ProcRRSetCrtcSpriteTransform (ClientPtr client); int ProcRRGetCrtcSpriteTransform (ClientPtr client); +int +ProcRRSetCrtcConfigs (ClientPtr client); + /* rrdispatch.c */ extern _X_EXPORT Bool RRClientKnowsRates (ClientPtr pClient); diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c index 1f8f2e662..12982a896 100644 --- a/randr/rrcrtc.c +++ b/randr/rrcrtc.c @@ -138,7 +138,8 @@ RRCrtcNotify (RRCrtcPtr crtc, Rotation rotation, RRTransformPtr transform, int numOutputs, - RROutputPtr *outputs) + RROutputPtr *outputs, + PixmapPtr scanoutPixmap) { int i, j; @@ -236,6 +237,15 @@ RRCrtcNotify (RRCrtcPtr crtc, RRCrtcChanged (crtc, TRUE); } + if (scanoutPixmap != crtc->scanoutPixmap) + { + if (scanoutPixmap) + ++scanoutPixmap->refcnt; + if (crtc->scanoutPixmap) + (*crtc->scanoutPixmap->drawable.pScreen->DestroyPixmap) (crtc->scanoutPixmap); + crtc->scanoutPixmap = scanoutPixmap; + } + if (crtc->changed && mode) { RRTransformCompute (x, y, @@ -312,7 +322,8 @@ RRCrtcSet (RRCrtcPtr crtc, int y, Rotation rotation, int numOutputs, - RROutputPtr *outputs) + RROutputPtr *outputs, + PixmapPtr scanout_pixmap) { ScreenPtr pScreen = crtc->pScreen; Bool ret = FALSE; @@ -326,7 +337,8 @@ RRCrtcSet (RRCrtcPtr crtc, crtc->numOutputs == numOutputs && !memcmp (crtc->outputs, outputs, numOutputs * sizeof (RROutputPtr)) && !RRCrtcPendingProperties (crtc) && - !RRCrtcPendingTransform (crtc)) + !RRCrtcPendingTransform (crtc) && + crtc->scanoutPixmap == scanout_pixmap) { ret = TRUE; } @@ -336,7 +348,7 @@ RRCrtcSet (RRCrtcPtr crtc, if (pScrPriv->rrCrtcSet) { ret = (*pScrPriv->rrCrtcSet) (pScreen, crtc, mode, x, y, - rotation, numOutputs, outputs); + rotation, numOutputs, outputs, scanout_pixmap); } else #endif @@ -349,7 +361,7 @@ RRCrtcSet (RRCrtcPtr crtc, if (!mode) { - RRCrtcNotify (crtc, NULL, x, y, rotation, NULL, 0, NULL); + RRCrtcNotify (crtc, NULL, x, y, rotation, NULL, 0, NULL, scanout_pixmap); ret = TRUE; } else @@ -375,7 +387,7 @@ RRCrtcSet (RRCrtcPtr crtc, */ if (ret) { - RRCrtcNotify (crtc, mode, x, y, rotation, NULL, 1, outputs); + RRCrtcNotify (crtc, mode, x, y, rotation, NULL, 1, outputs, scanout_pixmap); RRScreenSizeNotify (pScreen); } } @@ -573,7 +585,10 @@ RRCrtcGammaNotify (RRCrtcPtr crtc) return TRUE; /* not much going on here */ } -static void +/* + * Compute overall scanout buffer requirements for the specified mode + */ +void RRModeGetScanoutSize (RRModePtr mode, struct pixman_f_transform *transform, int *width, int *height) { @@ -1049,7 +1064,7 @@ ProcRRSetCrtcConfig (ClientPtr client) } if (!RRCrtcSet (crtc, mode, stuff->x, stuff->y, - rotation, numOutputs, outputs)) + rotation, numOutputs, outputs, NULL)) { rep.status = RRSetConfigFailed; goto sendReply; diff --git a/randr/rrinfo.c b/randr/rrinfo.c index fdf372607..549ebcc8d 100644 --- a/randr/rrinfo.c +++ b/randr/rrinfo.c @@ -168,7 +168,7 @@ RRScanOldConfig (ScreenPtr pScreen, Rotation rotations) /* notice current mode */ if (newMode) RRCrtcNotify (crtc, newMode, 0, 0, pScrPriv->rotation, - NULL, 1, &output); + NULL, 1, &output, NULL); } #endif diff --git a/randr/rrpixmap.c b/randr/rrpixmap.c new file mode 100644 index 000000000..7d4543c22 --- /dev/null +++ b/randr/rrpixmap.c @@ -0,0 +1,154 @@ +/* + * Copyright © 2010 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 "xace.h" + +int +ProcRRQueryScanoutPixmaps (ClientPtr client) +{ + REQUEST(xRRQueryScanoutPixmapsReq); + xRRQueryScanoutPixmapsReply rep; + RRScanoutPixmapInfo *info; + xRRScanoutPixmapInfo *x_info; + int n_info; + int rc; + DrawablePtr drawable; + ScreenPtr screen; + rrScrPrivPtr screen_priv; + int n, s; + + REQUEST_SIZE_MATCH(xRRQueryScanoutPixmapsReq); + rc = dixLookupDrawable(&drawable, stuff->drawable, client, 0, DixGetAttrAccess); + if (rc != Success) { + client->errorValue = stuff->drawable; + return rc; + } + + screen = drawable->pScreen; + screen_priv = rrGetScrPriv(screen); + + rep.type = X_Reply; + /* rep.status has already been filled in */ + rep.length = 0; + rep.sequenceNumber = client->sequence; + + info = RRQueryScanoutPixmapInfo(screen, &n_info); + x_info = calloc(n_info, sizeof (xRRScanoutPixmapInfo)); + if (n_info && !x_info) + return BadAlloc; + rep.length += (n_info * sizeof (xRRScanoutPixmapInfo)) >> 2; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + } + + for (s = 0; s < n_info; s++) { + x_info[s].format = info[s].format->id; + x_info[s].maxWidth = info[s].maxWidth; + x_info[s].maxHeight = info[s].maxHeight; + x_info[s].rotations = info[s].rotations; + if (client->swapped) { + swapl(&x_info[s].format, n); + swaps(&x_info[s].maxWidth, n); + swaps(&x_info[s].maxHeight, n); + swaps(&x_info[s].rotations, n); + } + } + + WriteToClient(client, sizeof(rep), (char *)&rep); + if (n_info) + WriteToClient(client, n_info * sizeof (xRRScanoutPixmapInfo), + (char *) x_info); + return Success; +} + +int +ProcRRCreateScanoutPixmap (ClientPtr client) +{ + REQUEST(xRRCreateScanoutPixmapReq); + int rc; + DrawablePtr drawable; + ScreenPtr screen; + rrScrPrivPtr screen_priv; + PixmapPtr pixmap; + int n_info; + RRScanoutPixmapInfo *info; + int s; + + REQUEST_SIZE_MATCH(xRRCreateScanoutPixmapReq); + client->errorValue = stuff->pid; + LEGAL_NEW_RESOURCE(stuff->pid, client); + + rc = dixLookupDrawable(&drawable, stuff->drawable, client, 0, DixGetAttrAccess); + if (rc != Success) { + client->errorValue = stuff->drawable; + return rc; + } + screen = drawable->pScreen; + screen_priv = rrGetScrPriv(screen); + if (!screen_priv) + return BadValue; + + info = RRQueryScanoutPixmapInfo(screen, &n_info); + for (s = 0; s < n_info; s++) { + if (info[s].format->id == stuff->format) + break; + } + if (s == n_info || !screen_priv->rrCreateScanoutPixmap) { + client->errorValue = stuff->format; + return BadValue; + } + info = &info[s]; + if (!stuff->width || stuff->width > info->maxWidth) { + client->errorValue = stuff->width; + return BadValue; + } + if (!stuff->height || stuff->height > info->maxHeight) { + client->errorValue = stuff->height; + return BadValue; + } + if ((stuff->rotations & info->rotations) != stuff->rotations) { + client->errorValue = stuff->rotations; + return BadValue; + } + + pixmap = screen_priv->rrCreateScanoutPixmap (screen, + stuff->width, stuff->height, + info->depth, + stuff->rotations, + info->format); + if (!pixmap) + return BadAlloc; + + pixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER; + pixmap->drawable.id = stuff->pid; + rc = XaceHook(XACE_RESOURCE_ACCESS, client, stuff->pid, RT_PIXMAP, + pixmap, RT_NONE, NULL, DixCreateAccess); + if (rc != Success) { + screen->DestroyPixmap(pixmap); + return rc; + } + if (!AddResource(stuff->pid, RT_PIXMAP, pixmap)) + return BadAlloc; + return Success; +} diff --git a/randr/rrscreen.c b/randr/rrscreen.c index 62ea2b62f..0c52347cf 100644 --- a/randr/rrscreen.c +++ b/randr/rrscreen.c @@ -794,8 +794,10 @@ ProcRRSetScreenConfig (ClientPtr client) } rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0, DixWriteAccess); - if (rc != Success) + if (rc != Success) { + client->errorValue = stuff->drawable; return rc; + } pScreen = pDraw->pScreen; @@ -940,7 +942,7 @@ ProcRRSetScreenConfig (ClientPtr client) for (c = 0; c < pScrPriv->numCrtcs; c++) { if (!RRCrtcSet (pScrPriv->crtcs[c], NULL, 0, 0, RR_Rotate_0, - 0, NULL)) + 0, NULL, NULL)) { rep.status = RRSetConfigFailed; /* XXX recover from failure */ @@ -956,7 +958,7 @@ ProcRRSetScreenConfig (ClientPtr client) } } - if (!RRCrtcSet (crtc, mode, 0, 0, stuff->rotation, 1, &output)) + if (!RRCrtcSet (crtc, mode, 0, 0, stuff->rotation, 1, &output, NULL)) rep.status = RRSetConfigFailed; else { pScrPriv->lastSetTime = time; |