[PATCH 5/6] randr: Add per-crtc pixmaps

Keith Packard keithp at keithp.com
Sun Dec 5 14:22:51 PST 2010


This adds new driver hooks to allocate scanout pixmaps and
changes the mode setting APIs to pass the new scanout pixmaps
along from DIX. DIX is responsible for reference counting the pixmaps
by tracking them through RRCrtcNotify.

Signed-off-by: Keith Packard <keithp at keithp.com>
---
 hw/xfree86/modes/xf86Crtc.c    |   20 +++++
 hw/xfree86/modes/xf86Crtc.h    |   32 ++++++++
 hw/xfree86/modes/xf86RandR12.c |   61 +++++++++++++++-
 randr/Makefile.am              |    1 +
 randr/mirrcrtc.c               |    3 +-
 randr/randr.c                  |   15 ++++
 randr/randrstr.h               |   48 ++++++++++++-
 randr/rrcrtc.c                 |   31 ++++++--
 randr/rrinfo.c                 |    2 +-
 randr/rrpixmap.c               |  154 ++++++++++++++++++++++++++++++++++++++++
 randr/rrscreen.c               |    8 ++-
 11 files changed, 355 insertions(+), 20 deletions(-)
 create mode 100644 randr/rrpixmap.c

diff --git a/hw/xfree86/modes/xf86Crtc.c b/hw/xfree86/modes/xf86Crtc.c
index 87a5608..f98af66 100644
--- a/hw/xfree86/modes/xf86Crtc.c
+++ b/hw/xfree86/modes/xf86Crtc.c
@@ -82,6 +82,17 @@ xf86CrtcSetSizeRange (ScrnInfoPtr scrn,
     config->maxHeight = maxHeight;
 }
 
+void
+xf86CrtcSetScanoutFormats(ScrnInfoPtr		scrn,
+			  int			num_formats,
+			  xf86CrtcScanoutFormat	*formats)
+{
+    xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(scrn);
+
+    config->num_scanout_formats = num_formats;
+    config->scanout_formats = formats;
+}
+
 /*
  * Crtc functions
  */
@@ -265,6 +276,7 @@ xf86CrtcSet(xf86CrtcPtr crtc, xf86CrtcSetRec *set)
     Rotation		saved_rotation;
     RRTransformRec	saved_transform;
     Bool		saved_transform_present;
+    PixmapPtr		saved_scanout_pixmap;
 
     crtc->enabled = xf86CrtcInUse (crtc);
 
@@ -284,6 +296,7 @@ xf86CrtcSet(xf86CrtcPtr crtc, xf86CrtcSetRec *set)
     saved_x = crtc->x;
     saved_y = crtc->y;
     saved_rotation = crtc->rotation;
+    saved_scanout_pixmap = crtc->scanoutPixmap;
     if (crtc->transformPresent) {
 	RRTransformInit (&saved_transform);
 	RRTransformCopy (&saved_transform, &crtc->transform);
@@ -301,6 +314,8 @@ xf86CrtcSet(xf86CrtcPtr crtc, xf86CrtcSetRec *set)
     }
     if (set->flags & XF86CrtcSetRotation)
 	crtc->rotation = set->rotation;
+    if (set->flags & XF86CrtcSetScanoutPixmap)
+	crtc->scanoutPixmap = set->scanout_pixmap;
 
     if (set->flags & XF86CrtcSetTransform) {
 	if (set->transform) {
@@ -399,6 +414,10 @@ done:
 	crtc->active = TRUE;
 	if (scrn->pScreen)
 	    xf86CrtcSetScreenSubpixelOrder (scrn->pScreen);
+	if (crtc->scanoutPixmap)
+	    ++crtc->scanoutPixmap->refcnt;
+	if (saved_scanout_pixmap)
+	    (*scrn->pScreen->DestroyPixmap)(saved_scanout_pixmap);
 	if (scrn->ModeSet)
 	    scrn->ModeSet(scrn);
     } else {
@@ -409,6 +428,7 @@ done:
 	if (saved_transform_present)
 	    RRTransformCopy (&crtc->transform, &saved_transform);
 	crtc->transformPresent = saved_transform_present;
+	crtc->scanoutPixmap = saved_scanout_pixmap;
     }
 
     if (adjusted_mode) {
diff --git a/hw/xfree86/modes/xf86Crtc.h b/hw/xfree86/modes/xf86Crtc.h
index c2e8131..9a520fc 100644
--- a/hw/xfree86/modes/xf86Crtc.h
+++ b/hw/xfree86/modes/xf86Crtc.h
@@ -79,6 +79,7 @@ typedef enum _xf86CrtcSetFlags {
     XF86CrtcSetTransform = 8,		/* transform */
     XF86CrtcSetRotation = 16,		/* rotation */
     XF86CrtcSetProperty = 32,		/* output property */
+    XF86CrtcSetScanoutPixmap = 64,	/* scanout pixmap */
 } xf86CrtcSetFlags;
 
 typedef struct _xf86CrtcSet {
@@ -87,6 +88,7 @@ typedef struct _xf86CrtcSet {
     Rotation		rotation;
     RRTransformPtr	transform;
     int			x, y;
+    PixmapPtr		scanout_pixmap;
 } xf86CrtcSetRec;
 
 typedef struct _xf86CrtcFuncs {
@@ -277,6 +279,7 @@ struct _xf86Crtc {
     Rotation	    rotation;
     PixmapPtr	    rotatedPixmap;
     void	    *rotatedData;
+    PixmapPtr	    scanoutPixmap;
     
     /**
      * Position on screen
@@ -670,6 +673,14 @@ typedef struct _xf86CrtcSetConfig {
     int				pixmap_x, pixmap_y;
 } xf86CrtcSetConfigRec, *xf86CrtcSetConfigPtr;
 
+typedef struct _xf86CrtcScanoutFormat {
+    int		    depth;
+    int		    bitsPerPixel;
+    int		    maxWidth, maxHeight;
+    Rotation	    rotations;
+    PictFormatShort format;
+} xf86CrtcScanoutFormat;
+
 typedef struct _xf86CrtcConfigFuncs {
     /**
      * Requests that the driver resize the screen.
@@ -693,6 +704,17 @@ typedef struct _xf86CrtcConfigFuncs {
 		   RRScreenConfigPtr	screen_config,
 		   xf86CrtcSetConfigPtr	crtc_configs,
 		   int			num_configs);
+
+    /**
+     * Create a scanout pixmap
+     */
+    PixmapPtr
+    (*create_scanout_pixmap)(ScrnInfoPtr		scrn,
+			     int			width,
+			     int			height,
+			     Rotation			rotations,
+			     xf86CrtcScanoutFormat	*format);
+
 } xf86CrtcConfigFuncsRec, *xf86CrtcConfigFuncsPtr;
 
 typedef void (*xf86_crtc_notify_proc_ptr) (ScreenPtr pScreen);
@@ -752,6 +774,11 @@ typedef struct _xf86CrtcConfig {
     /* callback when crtc configuration changes */
     xf86_crtc_notify_proc_ptr  xf86_crtc_notify;
 
+    /*
+     * Supported scanout pixmap formats
+     */
+    int			num_scanout_formats;
+    xf86CrtcScanoutFormat	*scanout_formats;
 } xf86CrtcConfigRec, *xf86CrtcConfigPtr;
 
 extern _X_EXPORT int xf86CrtcConfigPrivateIndex;
@@ -797,6 +824,11 @@ xf86CrtcSetSizeRange (ScrnInfoPtr scrn,
 		      int minWidth, int minHeight,
 		      int maxWidth, int maxHeight);
 
+extern _X_EXPORT void
+xf86CrtcSetScanoutFormats (ScrnInfoPtr			scrn,
+			   int				num_formats,
+			   xf86CrtcScanoutFormat	*formats);
+
 /*
  * Crtc functions
  */
diff --git a/hw/xfree86/modes/xf86RandR12.c b/hw/xfree86/modes/xf86RandR12.c
index e3330f4..b0eabdd 100644
--- a/hw/xfree86/modes/xf86RandR12.c
+++ b/hw/xfree86/modes/xf86RandR12.c
@@ -1083,7 +1083,7 @@ xf86RandR12CrtcNotify (RRCrtcPtr	randr_crtc)
     ret = RRCrtcNotify (randr_crtc, randr_mode, x, y,
 			rotation,
 			crtc->transformPresent ? &crtc->transform : NULL,
-			numOutputs, randr_outputs);
+			numOutputs, randr_outputs, crtc->scanoutPixmap);
     free(randr_outputs);
     return ret;
 }
@@ -1126,7 +1126,8 @@ xf86RandR12CrtcSet (ScreenPtr	    pScreen,
 		    int		    y,
 		    Rotation	    rotation,
 		    int		    num_randr_outputs,
-		    RROutputPtr	    *randr_outputs)
+		    RROutputPtr	    *randr_outputs,
+		    PixmapPtr	    scanout_pixmap)
 {
     XF86RandRInfoPtr	randrp = XF86RANDRINFO(pScreen);
     ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
@@ -1157,6 +1158,9 @@ xf86RandR12CrtcSet (ScreenPtr	    pScreen,
 				  sizeof (transform->transform)) != 0)
 	flags |= XF86CrtcSetTransform;
 
+    if (scanout_pixmap != crtc->scanoutPixmap)
+	flags |= XF86CrtcSetScanoutPixmap;
+
     if (x != crtc->x || y != crtc->y)
 	flags |= XF86CrtcSetOrigin;
     for (o = 0; o < config->num_output; o++)
@@ -1203,6 +1207,7 @@ xf86RandR12CrtcSet (ScreenPtr	    pScreen,
 	    set.transform = transform;
 	    set.x = x;
 	    set.y = y;
+	    set.scanout_pixmap = scanout_pixmap;
 	    set.flags = flags;
 	    if (!xf86CrtcSet(crtc, &set))
 	    {
@@ -1732,6 +1737,54 @@ xf86RandR12ChangeGamma(int scrnIndex, Gamma gamma)
     return Success;
 }
 
+static RRScanoutPixmapInfo *
+xf86RRQueryScanoutPixmaps(ScreenPtr screen, int *n_info)
+{
+    ScrnInfoPtr		scrn = xf86Screens[screen->myNum];
+    xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(scrn);
+    RRScanoutPixmapInfo	*info;
+    int			f;
+
+    info = calloc(config->num_scanout_formats, sizeof (RRScanoutPixmapInfo));
+    if (config->num_scanout_formats && !info) {
+	*n_info = 0;
+	return NULL;
+    }
+    for (f = 0; f < config->num_scanout_formats; f++) {
+	info[f].maxWidth = config->scanout_formats[f].maxWidth;
+	info[f].maxHeight = config->scanout_formats[f].maxHeight;
+	info[f].depth = config->scanout_formats[f].depth;
+	info[f].rotations = config->scanout_formats[f].rotations;
+	info[f].format = PictureMatchFormat (screen, info[f].depth,
+					     config->scanout_formats[f].format);
+    }
+    *n_info = config->num_scanout_formats;
+    return info;
+}
+
+static PixmapPtr
+xf86RRCreateScanoutPixmap(ScreenPtr screen,
+			  int width, int height, int depth,
+			  Rotation rotations,
+			  PictFormatPtr format)
+{
+    ScrnInfoPtr		scrn = xf86Screens[screen->myNum];
+    xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(scrn);
+    int			f;
+
+    if (!config->funcs->create_scanout_pixmap)
+	return NullPixmap;
+
+    for (f = 0; f < config->num_scanout_formats; f++)
+	if (config->scanout_formats[f].depth == depth &&
+	    (config->scanout_formats[f].format & 0xffffff) == format->format) {
+	    return (*config->funcs->create_scanout_pixmap) (scrn, width, height,
+							    rotations,
+							    &config->scanout_formats[f]);
+	}
+    return NullPixmap;
+}
+
 static void
 xf86RandR14SetCrtcSpriteTransform(ScreenPtr		pScreen,
 				  RRCrtcPtr		randr_crtc,
@@ -1893,17 +1946,17 @@ xf86RandR12Init12 (ScreenPtr pScreen)
     rp->rrCrtcGetGamma = xf86RandR12CrtcGetGamma;
     rp->rrOutputSetProperty = xf86RandR12OutputSetProperty;
     rp->rrOutputValidateMode = xf86RandR12OutputValidateMode;
-#if RANDR_13_INTERFACE
     rp->rrOutputGetProperty = xf86RandR13OutputGetProperty;
     rp->rrGetPanning = xf86RandR13GetPanning;
     rp->rrSetPanning = xf86RandR13SetPanning;
-#endif
     rp->rrModeDestroy = xf86RandR12ModeDestroy;
     rp->rrSetConfig = NULL;
     pScrn->PointerMoved = xf86RandR12PointerMoved;
     pScrn->ChangeGamma = xf86RandR12ChangeGamma;
     rp->rrSetCrtcSpriteTransform = xf86RandR14SetCrtcSpriteTransform;
     rp->rrSetCrtcConfigs = xf86RRSetCrtcConfigs;
+    rp->rrQueryScanoutPixmaps = xf86RRQueryScanoutPixmaps;
+    rp->rrCreateScanoutPixmap = xf86RRCreateScanoutPixmap;
 
     randrp->orig_EnterVT = pScrn->EnterVT;
     pScrn->EnterVT = xf86RandR12EnterVT;
diff --git a/randr/Makefile.am b/randr/Makefile.am
index a1c88dc..b7664c6 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 b1e2c9f..cc76797 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 6077705..c22657e 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 2fe9602..c231972 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 1f8f2e6..12982a8 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 fdf3726..549ebcc 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 0000000..7d4543c
--- /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 62ea2b6..0c52347 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;
-- 
1.7.2.3



More information about the xorg-devel mailing list