On 09/21/2011 01:23 PM, Keith Packard wrote:
On Thu, 25 Aug 2011 16:34:17 -0700, Aaron Plattner<[email protected]>  wrote:

If a driver can use hardware to handle the crtc transform, then
there's no need for the server's shadow layer to do it.  Add a crtc
flag that lets the driver indicate that it is handling the transform.
If it's set, consider the transformed size of the screen but don't
actually enable the shadow layer.  Also stop adjusting the cursor
image and position.

I can't get git am -3 to take this at all today; what server is this
based on?


I blame charset=iso-8859-1 due to my lame MTA. Try the attached patches. Sorry.

-- Aaron
>From 1f6c82dc07f829ada5e45c202a8808585d86ed7c Mon Sep 17 00:00:00 2001
From: Aaron Plattner <[email protected]>
Date: Thu, 25 Aug 2011 10:19:48 -0700
Subject: [PATCH 1/2] xfree86/modes: Let the driver handle the transform

If a driver can use hardware to handle the crtc transform, then
there's no need for the server's shadow layer to do it.  Add a crtc
flag that lets the driver indicate that it is handling the transform.
If it's set, consider the transformed size of the screen but don't
actually enable the shadow layer.  Also stop adjusting the cursor
image and position.

Signed-off-by: Aaron Plattner <[email protected]>
---
 hw/xfree86/modes/xf86Crtc.h    |   16 +++++-
 hw/xfree86/modes/xf86Cursors.c |   31 +++++++---
 hw/xfree86/modes/xf86Rotate.c  |  131 +++++++++++++++++++++-------------------
 3 files changed, 107 insertions(+), 71 deletions(-)

diff --git a/hw/xfree86/modes/xf86Crtc.h b/hw/xfree86/modes/xf86Crtc.h
index 68a968c..0d7a6a6 100644
--- a/hw/xfree86/modes/xf86Crtc.h
+++ b/hw/xfree86/modes/xf86Crtc.h
@@ -1,5 +1,6 @@
 /*
  * Copyright © 2006 Keith Packard
+ * Copyright © 2011 Aaron Plattner
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
@@ -223,7 +224,7 @@ typedef struct _xf86CrtcFuncs {
 
 } xf86CrtcFuncsRec, *xf86CrtcFuncsPtr;
 
-#define XF86_CRTC_VERSION 3
+#define XF86_CRTC_VERSION 4
 
 struct _xf86Crtc {
     /**
@@ -361,6 +362,19 @@ struct _xf86Crtc {
      * Clear the shadow
      */
     Bool	    shadowClear;
+
+    /**
+     * Indicates that the driver is handling the transform, so the shadow
+     * surface should be disabled.  The driver writes this field before calling
+     * xf86CrtcRotate to indicate that it is handling the transform (including
+     * rotation and reflection).
+     *
+     * Setting this flag also causes the server to stop adjusting the cursor
+     * image and position.
+     *
+     * Added in ABI version 4
+     */
+    Bool	    driverIsPerformingTransform;
 };
 
 typedef struct _xf86OutputFuncs {
diff --git a/hw/xfree86/modes/xf86Cursors.c b/hw/xfree86/modes/xf86Cursors.c
index 0667447..4281ab3 100644
--- a/hw/xfree86/modes/xf86Cursors.c
+++ b/hw/xfree86/modes/xf86Cursors.c
@@ -1,6 +1,6 @@
 /*
  * Copyright © 2007 Keith Packard
- * Copyright © 2010 Aaron Plattner
+ * Copyright © 2010-2011 Aaron Plattner
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
@@ -47,6 +47,18 @@
 #include "inputstr.h"
 
 /*
+ * Returns the rotation being performed by the server.  If the driver indicates
+ * that it's handling the screen transform, then this returns RR_Rotate_0.
+ */
+static Rotation
+xf86_crtc_cursor_rotation (xf86CrtcPtr crtc)
+{
+    if (crtc->driverIsPerformingTransform)
+	return RR_Rotate_0;
+    return crtc->rotation;
+}
+
+/*
  * Given a screen coordinate, rotate back to a cursor source coordinate
  */
 static void
@@ -214,6 +226,7 @@ xf86_crtc_convert_cursor_to_argb (xf86CrtcPtr crtc, unsigned char *src)
     int			xin, yin;
     int			flags = cursor_info->Flags;
     CARD32		bits;
+    const Rotation	rotation = xf86_crtc_cursor_rotation(crtc);
 
 #ifdef ARGB_CURSOR
     crtc->cursor_argb = FALSE;
@@ -222,7 +235,7 @@ xf86_crtc_convert_cursor_to_argb (xf86CrtcPtr crtc, unsigned char *src)
     for (y = 0; y < cursor_info->MaxHeight; y++)
 	for (x = 0; x < cursor_info->MaxWidth; x++) 
 	{
-	    xf86_crtc_rotate_coord (crtc->rotation,
+	    xf86_crtc_rotate_coord (rotation,
 				    cursor_info->MaxWidth,
 				    cursor_info->MaxHeight,
 				    x, y, &xin, &yin);
@@ -338,7 +351,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->transform_in_use && !crtc->driverIsPerformingTransform)
     {
 	ScreenPtr	screen = scrn->pScreen;
 	xf86CursorScreenPtr ScreenPriv =
@@ -420,12 +433,13 @@ xf86_crtc_load_cursor_image (xf86CrtcPtr crtc, CARD8 *src)
     xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
     xf86CursorInfoPtr	cursor_info = xf86_config->cursor_info;
     CARD8		*cursor_image;
+    const Rotation	rotation = xf86_crtc_cursor_rotation(crtc);
 
 #ifdef ARGB_CURSOR
     crtc->cursor_argb = FALSE;
 #endif
 
-    if (crtc->rotation == RR_Rotate_0)
+    if (rotation == RR_Rotate_0)
 	cursor_image = src;
     else
     {
@@ -439,7 +453,7 @@ xf86_crtc_load_cursor_image (xf86CrtcPtr crtc, CARD8 *src)
         for (y = 0; y < cursor_info->MaxHeight; y++)
 	    for (x = 0; x < cursor_info->MaxWidth; x++) 
 	    {
-		xf86_crtc_rotate_coord (crtc->rotation,
+		xf86_crtc_rotate_coord (rotation,
 					cursor_info->MaxWidth,
 					cursor_info->MaxHeight,
 					x, y, &xin, &yin);
@@ -532,12 +546,13 @@ xf86_crtc_load_cursor_argb (xf86CrtcPtr crtc, CursorPtr cursor)
     int			source_height = cursor->bits->height;
     int			image_width = cursor_info->MaxWidth;
     int			image_height = cursor_info->MaxHeight;
-    
+    const Rotation	rotation = xf86_crtc_cursor_rotation(crtc);
+
     for (y = 0; y < image_height; y++)
 	for (x = 0; x < image_width; x++)
 	{
-	    xf86_crtc_rotate_coord (crtc->rotation, image_width, image_height,
-				    x, y, &xin, &yin);
+	    xf86_crtc_rotate_coord (rotation, image_width, image_height, x, y,
+				    &xin, &yin);
 	    if (xin < source_width && yin < source_height)
 		bits = cursor_source[yin * source_width + xin];
 	    else
diff --git a/hw/xfree86/modes/xf86Rotate.c b/hw/xfree86/modes/xf86Rotate.c
index 57c3499..45aabf0 100644
--- a/hw/xfree86/modes/xf86Rotate.c
+++ b/hw/xfree86/modes/xf86Rotate.c
@@ -1,5 +1,6 @@
 /*
  * Copyright © 2006 Keith Packard
+ * Copyright © 2011 Aaron Plattner
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
@@ -84,7 +85,10 @@ xf86RotateCrtcRedisplay (xf86CrtcPtr crtc, RegionPtr region)
     int			n = RegionNumRects(region);
     BoxPtr		b = RegionRects(region);
     XID			include_inferiors = IncludeInferiors;
-    
+
+    if (crtc->driverIsPerformingTransform)
+	return;
+
     src = CreatePicture (None,
 			 &root->drawable,
 			 format,
@@ -290,7 +294,7 @@ xf86RotateDestroy (xf86CrtcPtr crtc)
     }
 
     for (c = 0; c < xf86_config->num_crtc; c++)
-	if (xf86_config->crtc[c]->transform_in_use)
+	if (xf86_config->crtc[c]->rotatedData)
 	    return;
 
     /*
@@ -414,52 +418,73 @@ xf86CrtcRotate (xf86CrtcPtr crtc)
     }
     else
     {
-	/*
-	 * these are the size of the shadow pixmap, which
-	 * matches the mode, not the pre-rotated copy in the
-	 * frame buffer
-	 */
-	int	    width = crtc->mode.HDisplay;
-	int	    height = crtc->mode.VDisplay;
-	void	    *shadowData = crtc->rotatedData;
-	PixmapPtr   shadow = crtc->rotatedPixmap;
-	int	    old_width = shadow ? shadow->drawable.width : 0;
-	int	    old_height = shadow ? shadow->drawable.height : 0;
-
-	/* Allocate memory for rotation */
-	if (old_width != width || old_height != height)
-	{
-	    if (shadow || shadowData)
+	if (crtc->driverIsPerformingTransform) {
+	    xf86RotateDestroy(crtc);
+	} else {
+	    /*
+	     * these are the size of the shadow pixmap, which
+	     * matches the mode, not the pre-rotated copy in the
+	     * frame buffer
+	     */
+	    int		width = crtc->mode.HDisplay;
+	    int		height = crtc->mode.VDisplay;
+	    void	*shadowData = crtc->rotatedData;
+	    PixmapPtr	shadow = crtc->rotatedPixmap;
+	    int		old_width = shadow ? shadow->drawable.width : 0;
+	    int		old_height = shadow ? shadow->drawable.height : 0;
+
+	    /* Allocate memory for rotation */
+	    if (old_width != width || old_height != height)
 	    {
-		crtc->funcs->shadow_destroy (crtc, shadow, shadowData);
-		crtc->rotatedPixmap = NULL;
-		crtc->rotatedData = NULL;
+		if (shadow || shadowData)
+		{
+		    crtc->funcs->shadow_destroy (crtc, shadow, shadowData);
+		    crtc->rotatedPixmap = NULL;
+		    crtc->rotatedData = NULL;
+		}
+		shadowData = crtc->funcs->shadow_allocate (crtc, width, height);
+		if (!shadowData)
+		    goto bail1;
+		crtc->rotatedData = shadowData;
+		/* shadow will be damaged in xf86RotatePrepare */
+	    }
+	    else
+	    {
+		/* mark shadowed area as damaged so it will be repainted */
+		damage = TRUE;
 	    }
-	    shadowData = crtc->funcs->shadow_allocate (crtc, width, height);
-	    if (!shadowData)
-		goto bail1;
-	    crtc->rotatedData = shadowData;
-	    /* shadow will be damaged in xf86RotatePrepare */
-	}
-	else
-	{
-	    /* mark shadowed area as damaged so it will be repainted */
-	    damage = TRUE;
-	}
 
-	if (!xf86_config->rotation_damage)
-	{
-	    /* Create damage structure */
-	    xf86_config->rotation_damage = DamageCreate (NULL, NULL,
-						DamageReportNone,
-						TRUE, pScreen, pScreen);
 	    if (!xf86_config->rotation_damage)
-		goto bail2;
-	    
-	    /* Wrap block handler */
-	    if (!xf86_config->BlockHandler) {
-		xf86_config->BlockHandler = pScreen->BlockHandler;
-		pScreen->BlockHandler = xf86RotateBlockHandler;
+	    {
+		/* Create damage structure */
+		xf86_config->rotation_damage = DamageCreate (NULL, NULL,
+						    DamageReportNone,
+						    TRUE, pScreen, pScreen);
+		if (!xf86_config->rotation_damage)
+		    goto bail2;
+
+		/* Wrap block handler */
+		if (!xf86_config->BlockHandler) {
+		    xf86_config->BlockHandler = pScreen->BlockHandler;
+		    pScreen->BlockHandler = xf86RotateBlockHandler;
+		}
+	    }
+
+	    if (0)
+	    {
+	bail2:
+		if (shadow || shadowData)
+		{
+		    crtc->funcs->shadow_destroy (crtc, shadow, shadowData);
+		    crtc->rotatedPixmap = NULL;
+		    crtc->rotatedData = NULL;
+		}
+	bail1:
+		if (old_width && old_height)
+		    crtc->rotatedPixmap =
+			crtc->funcs->shadow_create (crtc, NULL, old_width,
+						    old_height);
+		return FALSE;
 	    }
 	}
 #ifdef RANDR_12_INTERFACE
@@ -482,24 +507,6 @@ xf86CrtcRotate (xf86CrtcPtr crtc)
 	    }
 	}
 #endif
-
-	if (0)
-	{
-    bail2:
-	    if (shadow || shadowData)
-	    {
-		crtc->funcs->shadow_destroy (crtc, shadow, shadowData);
-		crtc->rotatedPixmap = NULL;
-		crtc->rotatedData = NULL;
-	    }
-    bail1:
-	    if (old_width && old_height)
-		crtc->rotatedPixmap = crtc->funcs->shadow_create (crtc,
-								  NULL,
-								  old_width,
-								  old_height);
-	    return FALSE;
-	}
 	crtc->transform_in_use = TRUE;
     }
     crtc->crtc_to_framebuffer = crtc_to_fb;
-- 
1.7.4.1

>From 5047f1d8e84b29cba22cf03dc1b7fa05445da034 Mon Sep 17 00:00:00 2001
From: Aaron Plattner <[email protected]>
Date: Thu, 25 Aug 2011 15:41:55 -0700
Subject: [PATCH 2/2] xfree86/modes: Make cursor position transform a helper function

When the driver can handle the crtc transform in hardware, it sets
crtc->driverIsPerformingTransform, which turns off both the shadow
layer and the cursor's position-transforming code.  However, some
drivers actually do require the cursor position to still be
transformed in these cases.  Move the cursor position transform into a
helper function that can be called by such drivers.

Signed-off-by: Aaron Plattner <[email protected]>
---
 hw/xfree86/modes/xf86Crtc.h    |    8 +++++
 hw/xfree86/modes/xf86Cursors.c |   57 +++++++++++++++++++++------------------
 2 files changed, 39 insertions(+), 26 deletions(-)

diff --git a/hw/xfree86/modes/xf86Crtc.h b/hw/xfree86/modes/xf86Crtc.h
index 0d7a6a6..ffb2eff 100644
--- a/hw/xfree86/modes/xf86Crtc.h
+++ b/hw/xfree86/modes/xf86Crtc.h
@@ -948,6 +948,14 @@ xf86_hide_cursors (ScrnInfoPtr scrn);
 extern _X_EXPORT void
 xf86_cursors_fini (ScreenPtr screen);
 
+/**
+ * Transform the cursor's coordinates based on the crtc transform.  Normally
+ * this is done by the server, but if crtc->driverIsPerformingTransform is TRUE,
+ * then the server does not transform the cursor position automatically.
+ */
+extern _X_EXPORT void
+xf86CrtcTransformCursorPos (xf86CrtcPtr crtc, int *x, int *y);
+
 /*
  * For overlay video, compute the relevant CRTC and
  * clip video to that.
diff --git a/hw/xfree86/modes/xf86Cursors.c b/hw/xfree86/modes/xf86Cursors.c
index 4281ab3..276bd27 100644
--- a/hw/xfree86/modes/xf86Cursors.c
+++ b/hw/xfree86/modes/xf86Cursors.c
@@ -337,7 +337,36 @@ xf86_show_cursors (ScrnInfoPtr scrn)
 	    xf86_crtc_show_cursor (crtc);
     }
 }
-    
+
+void xf86CrtcTransformCursorPos (xf86CrtcPtr crtc, int *x, int *y)
+{
+    ScrnInfoPtr scrn = crtc->scrn;
+    ScreenPtr screen = scrn->pScreen;
+    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+    xf86CursorInfoPtr cursor_info = xf86_config->cursor_info;
+    xf86CursorScreenPtr ScreenPriv =
+	(xf86CursorScreenPtr)dixLookupPrivate(&screen->devPrivates,
+					      xf86CursorScreenKey);
+    struct pict_f_vector v;
+    int dx, dy;
+
+    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);
+    /* cursor will have 0.5 added to it already so floor is sufficent */
+    *x = floor (v.v[0]);
+    *y = floor (v.v[1]);
+    /*
+     * Transform position of cursor upper left corner
+     */
+    xf86_crtc_rotate_coord_back (crtc->rotation, cursor_info->MaxWidth,
+				 cursor_info->MaxHeight, ScreenPriv->HotX,
+				 ScreenPriv->HotY, &dx, &dy);
+    *x -= dx;
+    *y -= dy;
+}
+
 static void
 xf86_crtc_set_cursor_position (xf86CrtcPtr crtc, int x, int y)
 {
@@ -346,36 +375,12 @@ xf86_crtc_set_cursor_position (xf86CrtcPtr crtc, int x, int y)
     xf86CursorInfoPtr	cursor_info = xf86_config->cursor_info;
     DisplayModePtr	mode = &crtc->mode;
     Bool		in_range;
-    int			dx, dy;
 
     /*
      * Transform position of cursor on screen
      */
     if (crtc->transform_in_use && !crtc->driverIsPerformingTransform)
-    {
-	ScreenPtr	screen = scrn->pScreen;
-	xf86CursorScreenPtr ScreenPriv =
-	    (xf86CursorScreenPtr)dixLookupPrivate(&screen->devPrivates,
-						  xf86CursorScreenKey);
-	struct pict_f_vector   v;
-
-	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);
-	/* cursor will have 0.5 added to it already so floor is sufficent */
-	x = floor (v.v[0]);
-	y = floor (v.v[1]);
-	/*
-	 * Transform position of cursor upper left corner
-	 */
-	xf86_crtc_rotate_coord_back (crtc->rotation,
-				     cursor_info->MaxWidth,
-				     cursor_info->MaxHeight,
-				     ScreenPriv->HotX, ScreenPriv->HotY, &dx, &dy);
-	x -= dx;
-	y -= dy;
-   }
+	xf86CrtcTransformCursorPos(crtc, &x, &y);
     else
     {
 	x -= crtc->x;
-- 
1.7.4.1

_______________________________________________
[email protected]: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: http://lists.x.org/mailman/listinfo/xorg-devel

Reply via email to