[PATCH] [RANDR] Support filters in CRTC transforms.

Keith Packard keithp at keithp.com
Fri Nov 14 14:12:33 PST 2008


Create new RRTransform datatype to hold all of the transform related
information, use that in lots of places to pass filters around.
---
 hw/xfree86/modes/xf86Crtc.h   |    3 +
 hw/xfree86/modes/xf86Rotate.c |   31 +++++-
 randr/randrstr.h              |   27 +++--
 randr/rrcrtc.c                |  239 ++++++++++++++++++++++++++++++++++-------
 4 files changed, 247 insertions(+), 53 deletions(-)

diff --git a/hw/xfree86/modes/xf86Crtc.h b/hw/xfree86/modes/xf86Crtc.h
index ef8589e..a5bb11b 100644
--- a/hw/xfree86/modes/xf86Crtc.h
+++ b/hw/xfree86/modes/xf86Crtc.h
@@ -306,6 +306,9 @@ struct _xf86Crtc {
      */
     PictTransform   crtc_to_framebuffer;
     PictTransform   framebuffer_to_crtc;
+    PictFilterPtr   filter;
+    xFixed	    *params;
+    int		    nparams;
     Bool	    transform_in_use;
     /**
      * Bounding box in screen space
diff --git a/hw/xfree86/modes/xf86Rotate.c b/hw/xfree86/modes/xf86Rotate.c
index 7967e5b..f201ae3 100644
--- a/hw/xfree86/modes/xf86Rotate.c
+++ b/hw/xfree86/modes/xf86Rotate.c
@@ -109,6 +109,9 @@ xf86RotateCrtcRedisplay (xf86CrtcPtr crtc, RegionPtr region)
     error = SetPictureTransform (src, &crtc->crtc_to_framebuffer);
     if (error)
 	return;
+    if (crtc->transform_in_use && crtc->filter)
+	SetPicturePictFilter (src, crtc->filter,
+			      crtc->params, crtc->nparams);
 
     while (n--)
     {
@@ -380,13 +383,33 @@ xf86CrtcRotate (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation)
     }
     
 #ifdef RANDR_12_INTERFACE
+    if (crtc->randr_crtc)
     {
-	PictTransform	user_forward, user_reverse;
-	if (crtc->randr_crtc && RRCrtcGetTransform (crtc->randr_crtc, &user_forward, &user_reverse))
+	xFixed		*new_params = NULL;
+	int		new_nparams = 0;
+	PictFilterPtr   new_filter = NULL;
+
+	RRTransformPtr	transform = RRCrtcGetTransform (crtc->randr_crtc);
+	if (transform)
 	{
-	    PictureTransformMultiply (&crtc_to_fb, &user_forward, &crtc_to_fb);
-	    PictureTransformMultiply (&fb_to_crtc, &fb_to_crtc, &user_reverse);
+	    if (transform->nparams) {
+		new_params = xalloc (transform->nparams * sizeof (xFixed));
+		if (new_params) {
+		    memcpy (new_params, transform->params,
+			    transform->nparams * sizeof (xFixed));
+		    new_nparams = transform->nparams;
+		    new_filter = transform->filter;
+		}
+	    } else
+		new_filter = transform->filter;
+	    PictureTransformMultiply (&crtc_to_fb, &transform->transform, &crtc_to_fb);
+	    PictureTransformMultiply (&fb_to_crtc, &fb_to_crtc, &transform->inverse);
 	}
+	if (crtc->params)
+	    xfree (crtc->params);
+	crtc->params = new_params;
+	crtc->nparams = new_nparams;
+	crtc->filter = new_filter;
     }
 #endif
     /*
diff --git a/randr/randrstr.h b/randr/randrstr.h
index 320e9f7..cdaebe9 100644
--- a/randr/randrstr.h
+++ b/randr/randrstr.h
@@ -78,6 +78,7 @@ typedef struct _rrPropertyValue	RRPropertyValueRec, *RRPropertyValuePtr;
 typedef struct _rrProperty	RRPropertyRec, *RRPropertyPtr;
 typedef struct _rrCrtc		RRCrtcRec, *RRCrtcPtr;
 typedef struct _rrOutput	RROutputRec, *RROutputPtr;
+typedef struct _rrTransform	RRTransformRec, *RRTransformPtr;
 
 struct _rrMode {
     int		    refcnt;
@@ -104,6 +105,14 @@ struct _rrProperty {
     RRPropertyValueRec	current, pending;
 };
 
+struct _rrTransform {
+    PictTransform   transform;
+    PictTransform   inverse;
+    PictFilterPtr   filter;
+    xFixed	    *params;
+    int		    nparams;
+};
+
 struct _rrCrtc {
     RRCrtc	    id;
     ScreenPtr	    pScreen;
@@ -119,10 +128,8 @@ struct _rrCrtc {
     CARD16	    *gammaBlue;
     CARD16	    *gammaGreen;
     void	    *devPrivate;
-    PictTransform   client_pending_transform;
-    PictTransform   client_pending_inverse;
-    PictTransform   client_current_transform;
-    PictTransform   client_current_inverse;
+    RRTransformRec  client_pending_transform;
+    RRTransformRec  client_current_transform;
     PictTransform   transform;
     PictTransform   inverse;
 };
@@ -612,10 +619,8 @@ RRComputeTransform (RRModePtr		mode,
 /*
  * Return crtc transform
  */
-Bool
-RRCrtcGetTransform (RRCrtcPtr crtc,
-		    PictTransformPtr crtc_to_fb,
-		    PictTransformPtr fb_to_crtc);
+RRTransformPtr
+RRCrtcGetTransform (RRCrtcPtr crtc);
 
 /*
  * Mark the pending transform as current
@@ -643,7 +648,11 @@ RRCrtcDestroy (RRCrtcPtr crtc);
 int
 RRCrtcTransformSet (RRCrtcPtr		crtc,
 		    PictTransformPtr	transform,
-		    PictTransformPtr	inverse);
+		    PictTransformPtr	inverse,
+		    char		*filter,
+		    int			filter_len,
+		    xFixed		*params,
+		    int			nparams);
 
 /*
  * Initialize crtc type
diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c
index 0cb8638..e3ba4f8 100644
--- a/randr/rrcrtc.c
+++ b/randr/rrcrtc.c
@@ -48,6 +48,52 @@ RRCrtcChanged (RRCrtcPtr crtc, Bool layoutChanged)
     }
 }
 
+static void
+RRTransformInit (RRTransformPtr transform)
+{
+    PictureTransformInitIdentity (&transform->transform);
+    PictureTransformInitIdentity (&transform->inverse);
+    transform->filter = NULL;
+    transform->params = NULL;
+    transform->nparams = 0;
+}
+
+static Bool
+RRTransformSetFilter (RRTransformPtr	dst,
+		      PictFilterPtr	filter,
+		      xFixed		*params,
+		      int		nparams)
+{
+    xFixed  *new_params;
+
+    if (nparams)
+    {
+	new_params = xalloc (nparams * sizeof (xFixed));
+	if (!new_params)
+	    return FALSE;
+	memcpy (new_params, params, nparams * sizeof (xFixed));
+    }
+    else
+	new_params = NULL;
+    if (dst->params)
+	xfree (dst->params);
+    dst->filter = filter;
+    dst->params = new_params;
+    dst->nparams = nparams;
+    return TRUE;
+}
+
+static Bool
+RRTransformCopy (RRTransformPtr dst, RRTransformPtr src)
+{
+    if (!RRTransformSetFilter (dst, src->filter,
+			       src->params, src->nparams))
+	return FALSE;
+    dst->transform = src->transform;
+    dst->inverse = src->inverse;
+    return TRUE;
+}
+
 /*
  * Create a CRTC
  */
@@ -89,10 +135,8 @@ RRCrtcCreate (ScreenPtr pScreen, void *devPrivate)
     crtc->gammaRed = crtc->gammaBlue = crtc->gammaGreen = NULL;
     crtc->changed = FALSE;
     crtc->devPrivate = devPrivate;
-    PictureTransformInitIdentity (&crtc->client_pending_transform);
-    PictureTransformInitIdentity (&crtc->client_pending_inverse);
-    PictureTransformInitIdentity (&crtc->client_current_transform);
-    PictureTransformInitIdentity (&crtc->client_current_inverse);
+    RRTransformInit (&crtc->client_pending_transform);
+    RRTransformInit (&crtc->client_current_transform);
     PictureTransformInitIdentity (&crtc->transform);
     PictureTransformInitIdentity (&crtc->inverse);
 
@@ -368,14 +412,14 @@ RRCrtcSet (RRCrtcPtr    crtc,
 /*
  * Return crtc transform
  */
-Bool
-RRCrtcGetTransform (RRCrtcPtr crtc,
-		    PictTransformPtr crtc_to_fb,
-		    PictTransformPtr fb_to_crtc)
+RRTransformPtr
+RRCrtcGetTransform (RRCrtcPtr crtc)
 {
-    *crtc_to_fb = crtc->client_pending_transform;
-    *fb_to_crtc = crtc->client_pending_inverse;
-    return !PictureTransformIsIdentity (crtc_to_fb);
+    RRTransformPtr  transform = &crtc->client_pending_transform;
+
+    if (PictureTransformIsIdentity (&transform->transform))
+	return NULL;
+    return transform;
 }
 
 /*
@@ -384,11 +428,11 @@ RRCrtcGetTransform (RRCrtcPtr crtc,
 void
 RRCrtcPostPendingTransform (RRCrtcPtr crtc)
 {
-    crtc->client_current_transform = crtc->client_pending_transform;
-    crtc->client_current_inverse = crtc->client_pending_inverse;
+    RRTransformCopy (&crtc->client_current_transform,
+		     &crtc->client_pending_transform);
     RRComputeTransform (crtc->mode, crtc->rotation, crtc->x, crtc->y,
-			&crtc->client_current_transform,
-			&crtc->client_current_inverse,
+			&crtc->client_current_transform.transform,
+			&crtc->client_current_transform.inverse,
 			&crtc->transform,
 			&crtc->inverse);
 }
@@ -399,8 +443,8 @@ RRCrtcPostPendingTransform (RRCrtcPtr crtc)
 Bool
 RRCrtcPendingTransform (RRCrtcPtr crtc)
 {
-    return memcmp (&crtc->client_current_transform,
-		   &crtc->client_pending_transform,
+    return memcmp (&crtc->client_current_transform.transform,
+		   &crtc->client_pending_transform.transform,
 		   sizeof (PictTransform)) != 0;
 }
 
@@ -546,12 +590,41 @@ RRCrtcGammaSetSize (RRCrtcPtr	crtc,
 int
 RRCrtcTransformSet (RRCrtcPtr		crtc,
 		    PictTransformPtr	transform,
-		    PictTransformPtr	inverse)
+		    PictTransformPtr	inverse,
+		    char		*filter_name,
+		    int			filter_len,
+		    xFixed		*params,
+		    int			nparams)
 {
+    PictFilterPtr   filter = NULL;
+
     if (!PictureTransformIsInverse (transform, inverse))
 	return BadMatch;
-    crtc->client_pending_transform = *transform;
-    crtc->client_pending_inverse = *inverse;
+    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))
+		return BadMatch;
+	}
+    }
+    else
+    {
+	if (nparams)
+	    return BadMatch;
+    }
+    if (!RRTransformSetFilter (&crtc->client_pending_transform,
+			       filter, params, nparams))
+	return BadAlloc;
+
+    crtc->client_pending_transform.transform = *transform;
+    crtc->client_pending_transform.inverse = *inverse;
     return Success;
 }
 
@@ -1128,8 +1201,12 @@ ProcRRSetCrtcTransform (ClientPtr client)
     REQUEST(xRRSetCrtcTransformReq);
     RRCrtcPtr		    crtc;
     PictTransform	    transform, inverse;
+    char		    *filter;
+    int			    nbytes;
+    xFixed		    *params;
+    int			    nparams;
 
-    REQUEST_SIZE_MATCH (xRRSetCrtcTransformReq);
+    REQUEST_AT_LEAST_SIZE(xRRSetCrtcTransformReq);
     crtc = LookupCrtc (client, stuff->crtc, DixWriteAccess);
     if (!crtc)
 	return RRErrorBase + BadRRCrtc;
@@ -1137,42 +1214,124 @@ ProcRRSetCrtcTransform (ClientPtr client)
     PictTransform_from_xRenderTransform (&transform, &stuff->transform);
     PictTransform_from_xRenderTransform (&inverse, &stuff->inverse);
 
-    return RRCrtcTransformSet (crtc, &transform, &inverse);
+    filter = (char *) (stuff + 1);
+    nbytes = stuff->nbytesFilter;
+    params = (xFixed *) (filter + ((nbytes + 3) & ~3));
+    nparams = ((xFixed *) stuff + client->req_len) - params;
+    if (nparams < 0)
+	return BadLength;
+
+    return RRCrtcTransformSet (crtc, &transform, &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 ((nbytes + 3) & ~3) + (nparams * sizeof (xFixed));
+}
+
+static int
+transform_filter_encode (ClientPtr client, char *output,
+			 CARD16	*nbytesFilter,
+			 CARD16	*nparamsFilter,
+			 RRTransformPtr transform)
+{
+    char    *output_orig = output;
+    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);
+    output += nbytes;
+    while ((nbytes & 3) != 0)
+	*output++ = 0;
+    memcpy (output, transform->params, nparams * sizeof (xFixed));
+    if (client->swapped) {
+	swaps (nbytesFilter, n);
+	swaps (nparamsFilter, n);
+	SwapLongs ((CARD32 *) output, nparams * sizeof (xFixed));
+    }
+    output += nparams * sizeof (xFixed);
+    return output - output_orig;
+}
+
+static void
+transform_encode (ClientPtr client, xRenderTransform *wire, PictTransform *pict)
+{
+    xRenderTransform_from_PictTransform (wire, pict);
+    if (client->swapped)
+	SwapLongs ((CARD32 *) wire, sizeof (xRenderTransform));
+}
+
 int
 ProcRRGetCrtcTransform (ClientPtr client)
 {
     REQUEST(xRRGetCrtcTransformReq);
-    xRRGetCrtcTransformReply	reply;
+    xRRGetCrtcTransformReply	*reply;
     RRCrtcPtr			crtc;
-    int				n;
+    int				n, nextra;
+    RRTransformPtr		current, pending;
+    char			*extra;
 
     REQUEST_SIZE_MATCH (xRRGetCrtcTransformReq);
     crtc = LookupCrtc (client, stuff->crtc, DixWriteAccess);
     if (!crtc)
 	return RRErrorBase + BadRRCrtc;
 
-    reply.type = X_Reply;
-    reply.sequenceNumber = client->sequence;
-    reply.length = CrtcTransformExtra >> 2;
-    
-    xRenderTransform_from_PictTransform (&reply.pendingTransform,
-					 &crtc->client_pending_transform);
-    xRenderTransform_from_PictTransform (&reply.pendingInverse,
-					 &crtc->client_pending_inverse);
-    xRenderTransform_from_PictTransform (&reply.currentTransform,
-					 &crtc->client_current_transform);
-    xRenderTransform_from_PictTransform (&reply.currentInverse,
-					 &crtc->client_current_inverse);
+    pending = &crtc->client_pending_transform;
+    current = &crtc->client_current_transform;
+
+    nextra = (transform_filter_length (pending) +
+	      transform_filter_length (current));
+
+    reply = xalloc (sizeof (xRRGetCrtcTransformReply) + nextra);
+    if (!reply)
+	return BadAlloc;
+
+    extra = (char *) (reply + 1);
+    reply->type = X_Reply;
+    reply->sequenceNumber = client->sequence;
+    reply->length = (CrtcTransformExtra + nextra) >> 2;
+
+    /* XXX deal with DDXen that can't do transforms */
+    reply->hasTransforms = xTrue;
+
+    transform_encode (client, &reply->pendingTransform, &pending->transform);
+    transform_encode (client, &reply->pendingInverse, &pending->inverse);
+    extra += transform_filter_encode (client, extra,
+				      &reply->pendingNbytesFilter,
+				      &reply->pendingNparamsFilter,
+				      pending);
+
+    transform_encode (client, &reply->currentTransform, &current->transform);
+    transform_encode (client, &reply->currentInverse, &current->inverse);
+    extra += transform_filter_encode (client, extra,
+				      &reply->currentNbytesFilter,
+				      &reply->currentNparamsFilter,
+				      current);
+
     if (client->swapped) {
-	swaps (&reply.sequenceNumber, n);
-	swapl (&reply.length, n);
-	SwapLongs ((CARD32 *) &reply.pendingTransform, 40);
+	swaps (&reply->sequenceNumber, n);
+	swapl (&reply->length, n);
     }
-    WriteToClient (client, sizeof (xRRGetCrtcTransformReply), (char *) &reply);
+    WriteToClient (client, sizeof (xRRGetCrtcTransformReply) + nextra, (char *) reply);
     return client->noClientException;
 }
-- 
1.5.6.5




More information about the xorg mailing list