[PATCH 2/6] randr: Add sprite position transforms

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


This implements sprite position transformations. Sprite image
transforms are passed all the way to the DDX layer, but the images are
not yet manipulated before being passed to the drivers.

Signed-off-by: Keith Packard <keithp at keithp.com>
---
 hw/xfree86/modes/xf86Crtc.c    |    5 ++
 hw/xfree86/modes/xf86Crtc.h    |   25 ++++++++++
 hw/xfree86/modes/xf86Cursors.c |    4 +-
 hw/xfree86/modes/xf86RandR12.c |   31 +++++++++---
 hw/xfree86/modes/xf86Rotate.c  |   44 ++++++++++++++++-
 randr/Makefile.am              |    1 +
 randr/randrstr.h               |   63 ++++++++++++++++--------
 randr/rrcrtc.c                 |   23 +++++++--
 randr/rrsprite.c               |  104 ++++++++++++++++++++++++++++++++++++++++
 randr/rrtransform.c            |   64 ++++++++++++++++++++++--
 randr/rrtransform.h            |   15 +++++-
 11 files changed, 333 insertions(+), 46 deletions(-)
 create mode 100644 randr/rrsprite.c

diff --git a/hw/xfree86/modes/xf86Crtc.c b/hw/xfree86/modes/xf86Crtc.c
index 5e9fc69..87a5608 100644
--- a/hw/xfree86/modes/xf86Crtc.c
+++ b/hw/xfree86/modes/xf86Crtc.c
@@ -106,12 +106,17 @@ xf86CrtcCreate (ScrnInfoPtr		scrn,
     pixman_transform_init_identity (&crtc->crtc_to_framebuffer);
     pixman_f_transform_init_identity (&crtc->f_crtc_to_framebuffer);
     pixman_f_transform_init_identity (&crtc->f_framebuffer_to_crtc);
+    pixman_f_transform_init_identity (&crtc->f_screen_to_crtc);
+    pixman_f_transform_init_identity (&crtc->user_sprite_position_transform);
+    pixman_f_transform_init_identity (&crtc->f_crtc_to_cursor);
+    pixman_f_transform_init_identity (&crtc->user_sprite_image_transform);
     crtc->filter = NULL;
     crtc->params = NULL;
     crtc->nparams = 0;
     crtc->filter_width = 0;
     crtc->filter_height = 0;
     crtc->transform_in_use = FALSE;
+    crtc->sprite_transform_in_use = FALSE;
     crtc->transformPresent = FALSE;
     crtc->desiredTransformPresent = FALSE;
     memset (&crtc->bounds, '\0', sizeof (crtc->bounds));
diff --git a/hw/xfree86/modes/xf86Crtc.h b/hw/xfree86/modes/xf86Crtc.h
index f43e0a7..8b42efc 100644
--- a/hw/xfree86/modes/xf86Crtc.h
+++ b/hw/xfree86/modes/xf86Crtc.h
@@ -345,6 +345,7 @@ struct _xf86Crtc {
     int		    filter_width; /* ABI 2 */
     int		    filter_height; /* ABI 2 */
     Bool	    transform_in_use;
+    Bool	    sprite_transform_in_use;
     RRTransformRec  transform; /* ABI 2 */
     Bool	    transformPresent; /* ABI 2 */
     RRTransformRec  desiredTransform; /* ABI 2 */
@@ -384,6 +385,22 @@ struct _xf86Crtc {
      * Clear the shadow
      */
     Bool	    shadowClear;
+
+    /**
+     * Sprite position transforms
+     */
+
+    /* Transform a screen coordinate to a crtc coordinate */
+    struct pixman_f_transform f_screen_to_crtc;
+
+    /* The user-specified portion of the screen to crtc conversion */
+    struct pixman_f_transform user_sprite_position_transform;
+
+    /* Transform a hardware cursor coordinate to a cursor coordinate */
+    struct pixman_f_transform f_crtc_to_cursor;
+
+    /* The user-specified portion of the cursor to hardware transform */
+    struct pixman_f_transform user_sprite_image_transform;
 };
 
 typedef struct _xf86OutputFuncs {
@@ -777,6 +794,14 @@ xf86CrtcSetOrigin (xf86CrtcPtr crtc, int x, int y);
 extern _X_EXPORT Bool
 xf86CrtcRotate (xf86CrtcPtr crtc);
 
+
+/*
+ * Update cursor transform matrices after user changes
+ * This is just the cursor subset of xf86CrtcRotate
+ */
+extern _X_EXPORT void
+xf86CrtcRotateCursor (xf86CrtcPtr crtc);
+
 /*
  * Clean up any rotation data, used when a crtc is turned off
  * as well as when rotation is disabled.
diff --git a/hw/xfree86/modes/xf86Cursors.c b/hw/xfree86/modes/xf86Cursors.c
index 0667447..7b43bcb 100644
--- a/hw/xfree86/modes/xf86Cursors.c
+++ b/hw/xfree86/modes/xf86Cursors.c
@@ -338,7 +338,7 @@ xf86_crtc_set_cursor_position (xf86CrtcPtr crtc, int x, int y)
     /*
      * Transform position of cursor on screen
      */
-    if (crtc->transform_in_use)
+    if (crtc->sprite_transform_in_use)
     {
 	ScreenPtr	screen = scrn->pScreen;
 	xf86CursorScreenPtr ScreenPriv =
@@ -349,7 +349,7 @@ xf86_crtc_set_cursor_position (xf86CrtcPtr crtc, int x, int y)
 	v.v[0] = (x + ScreenPriv->HotX) + 0.5;
 	v.v[1] = (y + ScreenPriv->HotY) + 0.5;
 	v.v[2] = 1;
-	pixman_f_transform_point (&crtc->f_framebuffer_to_crtc, &v);
+	pixman_f_transform_point (&crtc->f_screen_to_crtc, &v);
 	/* cursor will have 0.5 added to it already so floor is sufficent */
 	x = floor (v.v[0]);
 	y = floor (v.v[1]);
diff --git a/hw/xfree86/modes/xf86RandR12.c b/hw/xfree86/modes/xf86RandR12.c
index d60ee3c..bbf28cd 100644
--- a/hw/xfree86/modes/xf86RandR12.c
+++ b/hw/xfree86/modes/xf86RandR12.c
@@ -180,14 +180,14 @@ xf86RandR13VerifyPanningArea (xf86CrtcPtr crtc, int screenWidth, int screenHeigh
  */
 
 static void
-xf86ComputeCrtcPan (Bool transform_in_use,
+xf86ComputeCrtcPan (Bool sprite_transform_in_use,
 		    struct pixman_f_transform *m,
 		    double screen_x, double screen_y,
 		    double crtc_x, double crtc_y,
 		    int old_pan_x, int old_pan_y,
 		    int *new_pan_x, int *new_pan_y)
 {
-    if (transform_in_use) {
+    if (sprite_transform_in_use) {
 	/*
 	 * Given the current transform, M, the current position
 	 * on the Screen, S, and the desired position on the CRTC,
@@ -374,8 +374,8 @@ xf86RandR13Pan (xf86CrtcPtr crtc, int x, int y)
 	c.v[0] = x;
 	c.v[1] = y;
 	c.v[2] = 1.0;
-	if (crtc->transform_in_use) {
-	    pixman_f_transform_point(&crtc->f_framebuffer_to_crtc, &c);
+	if (crtc->sprite_transform_in_use) {
+	    pixman_f_transform_point(&crtc->f_screen_to_crtc, &c);
 	} else {
 	    c.v[0] -= crtc->x;
 	    c.v[1] -= crtc->y;
@@ -402,8 +402,8 @@ xf86RandR13Pan (xf86CrtcPtr crtc, int x, int y)
 	    }
 	}
 	if (panned)
-	    xf86ComputeCrtcPan (crtc->transform_in_use,
-				&crtc->f_framebuffer_to_crtc,
+	    xf86ComputeCrtcPan (crtc->sprite_transform_in_use,
+				&crtc->f_screen_to_crtc,
 				x, y, c.v[0], c.v[1],
 				newX, newY, &newX, &newY);
     }
@@ -414,7 +414,7 @@ xf86RandR13Pan (xf86CrtcPtr crtc, int x, int y)
      * XXX This computation only works when we do not have a transform
      * in use.
      */
-    if (!crtc->transform_in_use)
+    if (!crtc->sprite_transform_in_use)
     {
 	/* Validate against [xy]1 after [xy]2, to be sure that results are > 0 for [xy]1 > 0 */
 	if (crtc->panningTotalArea.x2 > crtc->panningTotalArea.x1) {
@@ -1732,6 +1732,20 @@ xf86RandR12ChangeGamma(int scrnIndex, Gamma gamma)
     return Success;
 }
 
+static void
+xf86RandR14SetCrtcSpriteTransform(ScreenPtr		pScreen,
+				  RRCrtcPtr		randr_crtc,
+				  struct pixman_f_transform *f_position_transform,
+				  struct pixman_f_transform *f_image_transform)
+{
+    xf86CrtcPtr		crtc = randr_crtc->devPrivate;
+
+    crtc->user_sprite_position_transform = *f_position_transform;
+    crtc->user_sprite_image_transform = *f_image_transform;
+    xf86CrtcRotateCursor(crtc);
+    xf86_reload_cursors(pScreen);
+}
+
 static Bool
 xf86RandR12EnterVT (int screen_index, int flags)
 {
@@ -1740,6 +1754,7 @@ xf86RandR12EnterVT (int screen_index, int flags)
     XF86RandRInfoPtr randrp  = XF86RANDRINFO(pScreen);
     rrScrPrivPtr     rp = rrGetScrPriv(pScreen);
     Bool	     ret;
+    int i;
 
     if (randrp->orig_EnterVT) {
 	pScrn->EnterVT = randrp->orig_EnterVT;
@@ -1751,7 +1766,6 @@ xf86RandR12EnterVT (int screen_index, int flags)
     }
 
     /* reload gamma */
-    int i;
     for (i = 0; i < rp->numCrtcs; i++)
 	xf86RandR12CrtcSetGamma(pScreen, rp->crtcs[i]);
 
@@ -1782,6 +1796,7 @@ xf86RandR12Init12 (ScreenPtr pScreen)
     rp->rrSetConfig = NULL;
     pScrn->PointerMoved = xf86RandR12PointerMoved;
     pScrn->ChangeGamma = xf86RandR12ChangeGamma;
+    rp->rrSetCrtcSpriteTransform = xf86RandR14SetCrtcSpriteTransform;
 
     randrp->orig_EnterVT = pScrn->EnterVT;
     pScrn->EnterVT = xf86RandR12EnterVT;
diff --git a/hw/xfree86/modes/xf86Rotate.c b/hw/xfree86/modes/xf86Rotate.c
index 57c3499..ddc6d4c 100644
--- a/hw/xfree86/modes/xf86Rotate.c
+++ b/hw/xfree86/modes/xf86Rotate.c
@@ -369,6 +369,39 @@ xf86CrtcFitsScreen (xf86CrtcPtr crtc, struct pict_f_transform *crtc_to_fb)
 	    0 <= b.y1 && b.y2 <= pScrn->virtualY);
 }
 
+/*
+ * A subset of xf86CrtcRotate that just deals with
+ * cursor image/position transforms. Used when changing
+ * the cursor transform
+ */
+void
+xf86CrtcRotateCursor (xf86CrtcPtr crtc)
+{
+    /* if this is called during ScreenInit() we don't have pScrn->pScreen yet */
+    RRTransformPtr	transform = NULL;
+    PictTransform	crtc_to_fb;
+    struct pict_f_transform f_crtc_to_fb, f_fb_to_crtc, f_screen_to_crtc, f_crtc_to_cursor;
+
+    if (crtc->transformPresent)
+	transform = &crtc->transform;
+
+    (void) RRTransformCompute (crtc->x, crtc->y,
+			       crtc->mode.HDisplay, crtc->mode.VDisplay,
+			       crtc->rotation,
+			       transform,
+			       &crtc->user_sprite_position_transform,
+			       &crtc->user_sprite_image_transform,
+
+			       &crtc_to_fb,
+			       &f_crtc_to_fb,
+			       &f_fb_to_crtc,
+			       &f_screen_to_crtc,
+			       &f_crtc_to_cursor,
+			       &crtc->sprite_transform_in_use);
+    crtc->f_screen_to_crtc = f_screen_to_crtc;
+    crtc->f_crtc_to_cursor = f_crtc_to_cursor;
+}
+
 Bool
 xf86CrtcRotate (xf86CrtcPtr crtc)
 {
@@ -377,7 +410,7 @@ xf86CrtcRotate (xf86CrtcPtr crtc)
     /* if this is called during ScreenInit() we don't have pScrn->pScreen yet */
     ScreenPtr		pScreen = screenInfo.screens[pScrn->scrnIndex];
     PictTransform	crtc_to_fb;
-    struct pict_f_transform f_crtc_to_fb, f_fb_to_crtc;
+    struct pict_f_transform f_crtc_to_fb, f_fb_to_crtc, f_screen_to_crtc, f_crtc_to_cursor;
     xFixed		*new_params = NULL;
     int			new_nparams = 0;
     PictFilterPtr	new_filter = NULL;
@@ -393,10 +426,15 @@ xf86CrtcRotate (xf86CrtcPtr crtc)
 			     crtc->mode.HDisplay, crtc->mode.VDisplay,
 			     crtc->rotation,
 			     transform,
+			     &crtc->user_sprite_position_transform,
+			     &crtc->user_sprite_image_transform,
 
 			     &crtc_to_fb,
 			     &f_crtc_to_fb,
-			     &f_fb_to_crtc) &&
+			     &f_fb_to_crtc,
+			     &f_screen_to_crtc,
+			     &f_crtc_to_cursor,
+			     &crtc->sprite_transform_in_use) &&
 	xf86CrtcFitsScreen (crtc, &f_crtc_to_fb))
     {
 	/*
@@ -505,6 +543,8 @@ xf86CrtcRotate (xf86CrtcPtr crtc)
     crtc->crtc_to_framebuffer = crtc_to_fb;
     crtc->f_crtc_to_framebuffer = f_crtc_to_fb;
     crtc->f_framebuffer_to_crtc = f_fb_to_crtc;
+    crtc->f_screen_to_crtc = f_screen_to_crtc;
+    crtc->f_crtc_to_cursor = f_crtc_to_cursor;
     free(crtc->params);
     crtc->params = new_params;
     crtc->nparams = new_nparams;
diff --git a/randr/Makefile.am b/randr/Makefile.am
index de338b9..4b38e52 100644
--- a/randr/Makefile.am
+++ b/randr/Makefile.am
@@ -20,6 +20,7 @@ librandr_la_SOURCES =	\
 	rrproperty.c	\
 	rrscreen.c	\
 	rrsdispatch.c	\
+	rrsprite.c	\
 	rrtransform.h	\
 	rrtransform.c
 
diff --git a/randr/randrstr.h b/randr/randrstr.h
index 7ea6080..5e2a351 100644
--- a/randr/randrstr.h
+++ b/randr/randrstr.h
@@ -55,9 +55,10 @@
 #define RANDR_10_INTERFACE 1
 #define RANDR_12_INTERFACE 1
 #define RANDR_13_INTERFACE 1 /* requires RANDR_12_INTERFACE */
+#define RANDR_14_INTERFACE 1 /* requires RANDR_13_INTERFACE */
 #define RANDR_GET_CRTC_INTERFACE 1
 
-#define RANDR_INTERFACE_VERSION 0x0103
+#define RANDR_INTERFACE_VERSION 0x0104
 
 typedef XID	RRMode;
 typedef XID	RROutput;
@@ -122,9 +123,16 @@ struct _rrCrtc {
     Bool	    transforms;
     RRTransformRec  client_pending_transform;
     RRTransformRec  client_current_transform;
+    PictTransform   client_sprite_position_transform;
+    PictTransform   client_sprite_image_transform;
+    struct pict_f_transform	client_sprite_f_position_transform;
+    struct pict_f_transform	client_sprite_f_image_transform;
+
     PictTransform   transform;
     struct pict_f_transform f_transform;
     struct pict_f_transform f_inverse;
+    struct pict_f_transform f_sprite_position;		/* crtc from screen */
+    struct pict_f_transform f_sprite_image_inverse;	/* image from crtc */
 };
 
 struct _rrOutput {
@@ -233,6 +241,16 @@ typedef Bool (*RRSetConfigProcPtr) (ScreenPtr		pScreen,
 #endif
 	
 
+typedef void (*RRSetCrtcSpriteTransformPtr) (ScreenPtr pScreen,
+					     RRCrtcPtr randr_crtc,
+					     struct pict_f_transform *position_transform,
+					     struct pict_f_transform *image_transform);
+
+typedef void (*RRGetCrtcSpriteTransformPtr) (ScreenPtr pScreen,
+					     RRCrtcPtr randr_crtc,
+					     struct pict_f_transform *position_transform,
+					     struct pict_f_transform *image_transform);
+
 typedef struct _rrScrPriv {
     /*
      * 'public' part of the structure; DDXen fill this in
@@ -256,7 +274,9 @@ typedef struct _rrScrPriv {
     RRGetPanningProcPtr	rrGetPanning;
     RRSetPanningProcPtr	rrSetPanning;
 #endif
-    
+    RRSetCrtcSpriteTransformPtr	rrSetCrtcSpriteTransform;
+    RRGetCrtcSpriteTransformPtr	rrGetCrtcSpriteTransform;
+
     /*
      * Private part of the structure; not considered part of the ABI
      */
@@ -606,25 +626,6 @@ extern _X_EXPORT void
 RRCrtcGetScanoutSize(RRCrtcPtr crtc, int *width, int *height);
 
 /*
- * Compute the complete transformation matrix including
- * client-specified transform, rotation/reflection values and the crtc 
- * offset.
- *
- * Return TRUE if the resulting transform is not a simple translation.
- */
-extern _X_EXPORT Bool
-RRTransformCompute (int			    x,
-		    int			    y,
-		    int			    width,
-		    int			    height,
-		    Rotation		    rotation,
-		    RRTransformPtr	    rr_transform,
-
-		    PictTransformPtr	    transform,
-		    struct pict_f_transform *f_transform,
-		    struct pict_f_transform *f_inverse);
-
-/*
  * Return crtc transform
  */
 extern _X_EXPORT RRTransformPtr
@@ -700,6 +701,19 @@ ProcRRGetPanning (ClientPtr client);
 int
 ProcRRSetPanning (ClientPtr client);
 
+void
+RRCrtcSpriteTransformSet(RRCrtcPtr crtc,
+			 PictTransform *position_transform,
+			 PictTransform *image_transform,
+			 struct pict_f_transform *f_position_transform,
+			 struct pict_f_transform *f_image_transform);
+
+int
+ProcRRSetCrtcSpriteTransform (ClientPtr client);
+
+int
+ProcRRGetCrtcSpriteTransform (ClientPtr client);
+
 /* rrdispatch.c */
 extern _X_EXPORT Bool
 RRClientKnowsRates (ClientPtr	pClient);
@@ -889,6 +903,13 @@ ProcRRConfigureOutputProperty (ClientPtr client);
 extern _X_EXPORT int
 ProcRRDeleteOutputProperty (ClientPtr client);
 
+/* rrsprite.c */
+extern _X_EXPORT int
+ProcRRSetCrtcSpriteTransform (ClientPtr client);
+
+extern _X_EXPORT int
+ProcRRGetCrtcSpriteTransform (ClientPtr client);
+
 /* rrxinerama.c */
 #ifdef XINERAMA
 extern _X_EXPORT void
diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c
index 98206a2..c2f6963 100644
--- a/randr/rrcrtc.c
+++ b/randr/rrcrtc.c
@@ -93,6 +93,8 @@ RRCrtcCreate (ScreenPtr pScreen, void *devPrivate)
     pixman_transform_init_identity (&crtc->transform);
     pixman_f_transform_init_identity (&crtc->f_transform);
     pixman_f_transform_init_identity (&crtc->f_inverse);
+    pixman_f_transform_init_identity (&crtc->f_sprite_position);
+    pixman_f_transform_init_identity (&crtc->f_sprite_image_inverse);
 
     if (!AddResource (crtc->id, RRCrtcType, (pointer) crtc))
 	return NULL;
@@ -231,15 +233,21 @@ RRCrtcNotify (RRCrtcPtr	    crtc,
 	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->client_sprite_f_position_transform,
+			    &crtc->client_sprite_f_image_transform,
 			    &crtc->transform, &crtc->f_transform,
-			    &crtc->f_inverse);
+			    &crtc->f_inverse, &crtc->f_sprite_position,
+			    &crtc->f_sprite_image_inverse,
+			    NULL);
     }
+
     return TRUE;
 }
 
@@ -511,7 +519,7 @@ RRCrtcGammaNotify (RRCrtcPtr	crtc)
 }
 
 static void
-RRModeGetScanoutSize (RRModePtr mode, PictTransformPtr transform,
+RRModeGetScanoutSize (RRModePtr mode, struct pixman_f_transform *transform,
 		      int *width, int *height)
 {
     BoxRec  box;
@@ -527,7 +535,7 @@ RRModeGetScanoutSize (RRModePtr mode, PictTransformPtr transform,
     box.x2 = mode->mode.width;
     box.y2 = mode->mode.height;
 
-    pixman_transform_bounds (transform, &box);
+    pixman_f_transform_bounds (transform, &box);
     *width = box.x2 - box.x1;
     *height = box.y2 - box.y1;
 }
@@ -538,7 +546,7 @@ RRModeGetScanoutSize (RRModePtr mode, PictTransformPtr transform,
 void
 RRCrtcGetScanoutSize(RRCrtcPtr crtc, int *width, int *height)
 {
-    return RRModeGetScanoutSize (crtc->mode, &crtc->transform, width, height);
+    RRModeGetScanoutSize (crtc->mode, &crtc->f_transform, width, height);
 }
 
 /*
@@ -924,9 +932,12 @@ ProcRRSetCrtcConfig (ClientPtr client)
 				mode->mode.width, mode->mode.height,
 				rotation,
 				&crtc->client_pending_transform,
-				&transform, &f_transform, &f_inverse);
+				&crtc->client_sprite_f_position_transform,
+				&crtc->client_sprite_f_image_transform,
+				&transform, &f_transform, &f_inverse, NULL, NULL, NULL);
 
-	    RRModeGetScanoutSize (mode, &transform, &source_width, &source_height);
+	    RRModeGetScanoutSize (mode, &f_transform,
+				  &source_width, &source_height);
 	    if (stuff->x + source_width > pScreen->width)
 	    {
 		client->errorValue = stuff->x;
diff --git a/randr/rrsprite.c b/randr/rrsprite.c
new file mode 100644
index 0000000..5bf312c
--- /dev/null
+++ b/randr/rrsprite.c
@@ -0,0 +1,104 @@
+/*
+ * 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 "swaprep.h"
+
+void
+RRCrtcSpriteTransformSet(RRCrtcPtr crtc,
+			 PictTransform *position_transform,
+			 PictTransform *image_transform,
+			 struct pict_f_transform *f_position_transform,
+			 struct pict_f_transform *f_image_transform)
+{
+    ScreenPtr			pScreen;
+    rrScrPrivPtr		pScrPriv;
+
+    pScreen = crtc->pScreen;
+    pScrPriv = rrGetScrPriv(pScreen);
+    crtc->client_sprite_position_transform = *position_transform;
+    crtc->client_sprite_image_transform = *image_transform;
+    crtc->client_sprite_f_position_transform = *f_position_transform;
+    crtc->client_sprite_f_image_transform = *f_image_transform;
+    if (pScrPriv->rrSetCrtcSpriteTransform)
+	(*pScrPriv->rrSetCrtcSpriteTransform) (pScreen, crtc,
+					       &crtc->client_sprite_f_position_transform,
+					       &crtc->client_sprite_f_image_transform);
+}
+
+int
+ProcRRSetCrtcSpriteTransform (ClientPtr client)
+{
+    REQUEST(xRRSetCrtcSpriteTransformReq);
+    RRCrtcPtr		    crtc;
+    PictTransform	    position_transform, image_transform;
+    struct pixman_f_transform f_position_transform, f_image_transform;
+
+    REQUEST_AT_LEAST_SIZE(xRRSetCrtcSpriteTransformReq);
+    VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess);
+
+    PictTransform_from_xRenderTransform (&position_transform, &stuff->positionTransform);
+    PictTransform_from_xRenderTransform (&image_transform, &stuff->imageTransform);
+    pixman_f_transform_from_pixman_transform (&f_position_transform, &position_transform);
+    pixman_f_transform_from_pixman_transform (&f_image_transform, &image_transform);
+
+    RRCrtcSpriteTransformSet (crtc, &position_transform, &image_transform,
+			      &f_position_transform, &f_image_transform);
+    return Success;
+}
+
+#define CrtcSpriteTransformExtra	(SIZEOF(xRRGetCrtcSpriteTransformReply) - 32)
+
+int
+ProcRRGetCrtcSpriteTransform (ClientPtr client)
+{
+    REQUEST(xRRGetCrtcSpriteTransformReq);
+    xRRGetCrtcSpriteTransformReply	*reply;
+    RRCrtcPtr			crtc;
+    int				n;
+    char			*extra;
+
+    REQUEST_SIZE_MATCH (xRRGetCrtcSpriteTransformReq);
+    VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess);
+
+    reply = malloc(sizeof (xRRGetCrtcSpriteTransformReply));
+    if (!reply)
+	return BadAlloc;
+
+    extra = (char *) (reply + 1);
+    reply->type = X_Reply;
+    reply->sequenceNumber = client->sequence;
+    reply->length = bytes_to_int32(CrtcSpriteTransformExtra);
+
+    xRenderTransform_from_PictTransform(&reply->positionTransform, &crtc->client_sprite_position_transform);
+    xRenderTransform_from_PictTransform(&reply->imageTransform, &crtc->client_sprite_image_transform);
+
+    if (client->swapped) {
+	swaps (&reply->sequenceNumber, n);
+	swapl (&reply->length, n);
+	SwapLongs((CARD32 *) &reply->positionTransform, bytes_to_int32(sizeof(xRenderTransform)));
+	SwapLongs((CARD32 *) &reply->imageTransform, bytes_to_int32(sizeof(xRenderTransform)));
+    }
+    WriteToClient (client, sizeof (xRRGetCrtcSpriteTransformReply), (char *) reply);
+    free(reply);
+    return Success;
+}
diff --git a/randr/rrtransform.c b/randr/rrtransform.c
index e162049..3eda5f3 100644
--- a/randr/rrtransform.c
+++ b/randr/rrtransform.c
@@ -134,6 +134,24 @@ RRTransformRescale(struct pixman_f_transform *f_transform, double limit)
 	    f_transform->m[j][i] *= scale;
 }
 
+#define EPSILON (1e-20)
+#define IS_F_SAME(a,b)	(fabs((a)-(b)) < EPSILON)
+#define IS_F_ZERO(a)	(fabs(a) < EPSILON)
+
+static Bool
+pict_f_transform_is_identity (const struct pixman_f_transform *t)
+{
+    return (IS_F_SAME (t->m[0][0], t->m[1][1]) &&
+	    IS_F_SAME (t->m[0][0], t->m[2][2]) &&
+	    !IS_F_ZERO (t->m[0][0]) &&
+	    IS_F_ZERO (t->m[0][1]) &&
+	    IS_F_ZERO (t->m[0][2]) &&
+	    IS_F_ZERO (t->m[1][0]) &&
+	    IS_F_ZERO (t->m[1][2]) &&
+	    IS_F_ZERO (t->m[2][0]) &&
+	    IS_F_ZERO (t->m[2][1]));
+}
+
 /*
  * Compute the complete transformation matrix including
  * client-specified transform, rotation/reflection values and the crtc 
@@ -148,23 +166,39 @@ RRTransformCompute (int			    x,
 		    int			    height,
 		    Rotation		    rotation,
 		    RRTransformPtr	    rr_transform,
+		    struct pixman_f_transform *sprite_position_transform,
+		    struct pixman_f_transform *sprite_image_transform,
 
 		    PictTransformPtr	    transform,
 		    struct pixman_f_transform *f_transform,
-		    struct pixman_f_transform *f_inverse)
+		    struct pixman_f_transform *f_inverse,
+		    struct pixman_f_transform *f_fb_to_sprite,
+		    struct pixman_f_transform *f_sprite_to_image,
+		    Bool		      *sprite_transform_in_use)
 {
     PictTransform	    t_transform, inverse;
     struct pixman_f_transform tf_transform, tf_inverse;
+    struct pixman_f_transform sf_position_transform, sf_image_transform;
+    struct pixman_f_transform f_image_to_sprite;
     Bool		    overflow = FALSE;
+    Bool		    ret = TRUE;
 
     if (!transform) transform = &t_transform;
     if (!f_transform) f_transform = &tf_transform;
     if (!f_inverse) f_inverse = &tf_inverse;
+    if (!f_fb_to_sprite) f_fb_to_sprite = &sf_position_transform;
+    if (!f_sprite_to_image) f_sprite_to_image = &sf_image_transform;
+
+    /* invert the sprite image transform to have it go from dest to source */
+    if (!pixman_f_transform_invert (&f_image_to_sprite, f_sprite_to_image))
+	pixman_f_transform_init_identity(&f_image_to_sprite);
 
     pixman_transform_init_identity (transform);
     pixman_transform_init_identity (&inverse);
     pixman_f_transform_init_identity (f_transform);
     pixman_f_transform_init_identity (f_inverse);
+    pixman_f_transform_init_identity (f_fb_to_sprite);
+    pixman_f_transform_init_identity (f_sprite_to_image);
     if (rotation != RR_Rotate_0)
     {
 	double	f_rot_cos, f_rot_sin, f_rot_dx, f_rot_dy;
@@ -246,7 +280,14 @@ RRTransformCompute (int			    x,
 	pixman_f_transform_translate (f_transform, f_inverse, f_scale_dx, f_scale_dy);
     }
     
-#ifdef RANDR_12_INTERFACE
+    /*
+     * Sprite position is affected by the transform matrix,
+     * but the image is not
+     */
+    pixman_f_transform_multiply(f_sprite_to_image,
+				f_transform,
+				&f_image_to_sprite);
+
     if (rr_transform)
     {
         if (!pixman_transform_multiply (transform, &rr_transform->transform, transform))
@@ -254,7 +295,7 @@ RRTransformCompute (int			    x,
 	pixman_f_transform_multiply (f_transform, &rr_transform->f_transform, f_transform);
 	pixman_f_transform_multiply (f_inverse, f_inverse, &rr_transform->f_inverse);
     }
-#endif
+
     /*
      * Compute the class of the resulting transform
      */
@@ -264,7 +305,7 @@ RRTransformCompute (int			    x,
 
 	pixman_f_transform_init_translate (f_transform,  x,  y);
 	pixman_f_transform_init_translate (f_inverse,   -x, -y);
-	return FALSE;
+	ret = FALSE;
     }
     else
     {
@@ -278,6 +319,19 @@ RRTransformCompute (int			    x,
 	    RRTransformRescale(&f_scaled, 16384.0);
 	    pixman_transform_from_pixman_f_transform(transform, &f_scaled);
 	}
-	return TRUE;
+	ret = TRUE;
     }
+
+    /*
+     * Sprite position is affected by the transform matrix,
+     * but the image is not
+     */
+    pixman_f_transform_multiply(f_fb_to_sprite,
+				f_inverse,
+				sprite_position_transform);
+    if (sprite_transform_in_use)
+	*sprite_transform_in_use = ret || !pict_f_transform_is_identity(f_fb_to_sprite);
+    return ret;
 }
+
+
diff --git a/randr/rrtransform.h b/randr/rrtransform.h
index 561762d..5cfcf8d 100644
--- a/randr/rrtransform.h
+++ b/randr/rrtransform.h
@@ -59,6 +59,13 @@ RRTransformSetFilter (RRTransformPtr	dst,
 extern _X_EXPORT Bool
 RRTransformCopy (RRTransformPtr dst, RRTransformPtr src);
 
+/*
+ * Compute the complete transformation matrix including
+ * client-specified transform, rotation/reflection values and the crtc
+ * offset.
+ *
+ * Return TRUE if the resulting transform is not a simple translation.
+ */
 extern _X_EXPORT Bool
 RRTransformCompute (int			    x,
 		    int			    y,
@@ -66,10 +73,14 @@ RRTransformCompute (int			    x,
 		    int			    height,
 		    Rotation		    rotation,
 		    RRTransformPtr	    rr_transform,
+		    struct pict_f_transform *sprite_position_transform,
+		    struct pict_f_transform *sprite_image_transform,
 
 		    PictTransformPtr	    transform,
 		    struct pict_f_transform *f_transform,
-		    struct pict_f_transform *f_inverse);
-
+		    struct pict_f_transform *f_inverse,
+		    struct pict_f_transform *f_fb_to_sprite,
+		    struct pict_f_transform *f_sprite_to_image,
+		    Bool		    *sprite_transform_in_use);
 
 #endif /* _RRTRANSFORM_H_ */
-- 
1.7.2.3



More information about the xorg-devel mailing list