summaryrefslogtreecommitdiff
path: root/randr
diff options
context:
space:
mode:
Diffstat (limited to 'randr')
-rw-r--r--randr/Makefile.am1
-rw-r--r--randr/mirrcrtc.c3
-rw-r--r--randr/randr.c15
-rw-r--r--randr/randrstr.h48
-rw-r--r--randr/rrcrtc.c31
-rw-r--r--randr/rrinfo.c2
-rw-r--r--randr/rrpixmap.c154
-rw-r--r--randr/rrscreen.c8
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;