One of the lacking features with output offloading was
that screen rotation didn't work at all.
This patch makes 0/90/180/270 rotation work with USB output
and GPU outputs.
When it allocates the shared pixmap it allocates it rotated,
and any updates to the shared pixmap are done using a composite
path that does the rotation. The slave GPU then doesn't need
to know about the rotation and just displays the pixmap.
Signed-off-by: Dave Airlie airl...@redhat.com
---
dix/pixmap.c | 155 ++-
hw/xfree86/drivers/modesetting/drmmode_display.c | 2 +-
hw/xfree86/modes/xf86Rotate.c| 2 +
include/pixmap.h | 12 +-
include/pixmapstr.h | 5 +
include/scrnintstr.h | 5 +-
randr/rrcrtc.c | 60 ++---
7 files changed, 179 insertions(+), 62 deletions(-)
diff --git a/dix/pixmap.c b/dix/pixmap.c
index 00e298f..a20c38d 100644
--- a/dix/pixmap.c
+++ b/dix/pixmap.c
@@ -40,7 +40,9 @@ from The Open Group.
#include gcstruct.h
#include servermd.h
#include site.h
-
+#include X11/extensions/render.h
+#include picturestr.h
+#include randrstr.h
/*
* Scratch pixmap management and device independent pixmap allocation
* function.
@@ -164,9 +166,10 @@ PixmapPtr PixmapShareToSlave(PixmapPtr pixmap, ScreenPtr
slave)
}
Bool
-PixmapStartDirtyTracking2(PixmapPtr src,
- PixmapPtr slave_dst,
- int x, int y, int dst_x, int dst_y)
+PixmapStartDirtyTracking(PixmapPtr src,
+ PixmapPtr slave_dst,
+ int x, int y, int dst_x, int dst_y,
+ Rotation rotation)
{
ScreenPtr screen = src-drawable.pScreen;
PixmapDirtyUpdatePtr dirty_update;
@@ -181,11 +184,22 @@ PixmapStartDirtyTracking2(PixmapPtr src,
dirty_update-y = y;
dirty_update-dst_x = dst_x;
dirty_update-dst_y = dst_y;
-
+dirty_update-rotation = rotation;
dirty_update-damage = DamageCreate(NULL, NULL,
DamageReportNone,
TRUE, src-drawable.pScreen,
src-drawable.pScreen);
+
+if (rotation != RR_Rotate_0) {
+RRTransformCompute(x, y,
+ slave_dst-drawable.width,
+ slave_dst-drawable.height,
+ rotation,
+ NULL,
+ dirty_update-transform,
+ dirty_update-f_transform,
+ dirty_update-f_inverse);
+}
if (!dirty_update-damage) {
free(dirty_update);
return FALSE;
@@ -197,14 +211,6 @@ PixmapStartDirtyTracking2(PixmapPtr src,
}
Bool
-PixmapStartDirtyTracking(PixmapPtr src,
-PixmapPtr slave_dst,
-int x, int y)
-{
- return PixmapStartDirtyTracking2(src, slave_dst, x, y, 0, 0);
-}
-
-Bool
PixmapStopDirtyTracking(PixmapPtr src, PixmapPtr slave_dst)
{
ScreenPtr screen = src-drawable.pScreen;
@@ -220,6 +226,95 @@ PixmapStopDirtyTracking(PixmapPtr src, PixmapPtr slave_dst)
return TRUE;
}
+static void
+PixmapDirtyCopyArea(PixmapPtr dst,
+PixmapDirtyUpdatePtr dirty,
+RegionPtr dirty_region)
+{
+ScreenPtr pScreen = dirty-src-drawable.pScreen;
+int n;
+BoxPtr b;
+GCPtr pGC;
+
+n = RegionNumRects(dirty_region);
+b = RegionRects(dirty_region);
+
+pGC = GetScratchGC(dirty-src-drawable.depth, pScreen);
+ValidateGC(dst-drawable, pGC);
+
+while (n--) {
+BoxRec dst_box;
+int w, h;
+
+dst_box = *b;
+w = dst_box.x2 - dst_box.x1;
+h = dst_box.y2 - dst_box.y1;
+
+pGC-ops-CopyArea(dirty-src-drawable, dst-drawable, pGC,
+ dirty-x + dst_box.x1, dirty-y + dst_box.y1, w, h,
+ dirty-dst_x + dst_box.x1,
+ dirty-dst_y + dst_box.y1);
+b++;
+}
+FreeScratchGC(pGC);
+}
+
+static void
+PixmapDirtyCompositeRotate(PixmapPtr dst_pixmap,
+ PixmapDirtyUpdatePtr dirty,
+ RegionPtr dirty_region)
+{
+ScreenPtr pScreen = dirty-src-drawable.pScreen;
+PictFormatPtr format = PictureWindowFormat(pScreen-root);
+PicturePtr src, dst;
+XID include_inferiors = IncludeInferiors;
+int n = RegionNumRects(dirty_region);
+BoxPtr b = RegionRects(dirty_region);
+int error;
+
+src = CreatePicture(None,
+dirty-src-drawable,
+format,
+CPSubwindowMode,
+include_inferiors, serverClient, error);
+if (!src)
+return;
+
+dst = CreatePicture(None,
+dst_pixmap-drawable,
+