diff options
author | Dave Airlie <airlied@gmail.com> | 2015-06-12 15:59:13 +1000 |
---|---|---|
committer | Dave Airlie <airlied@gmail.com> | 2015-06-15 09:17:14 +1000 |
commit | 342aea427a536dd30f1326a3a29fa284e29df526 (patch) | |
tree | c3239b7f2ebdfa99c285a4b1d73ee6693b2f2ea0 | |
parent | fdb4e0808e5611f7154fd931632c0c42f92766d5 (diff) |
prime: add rotation support for offloaded outputsxserver-queue
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 <airlied@redhat.com>
-rw-r--r-- | dix/pixmap.c | 155 | ||||
-rw-r--r-- | hw/xfree86/drivers/modesetting/drmmode_display.c | 2 | ||||
-rw-r--r-- | hw/xfree86/modes/xf86Rotate.c | 2 | ||||
-rw-r--r-- | include/pixmap.h | 12 | ||||
-rw-r--r-- | include/pixmapstr.h | 5 | ||||
-rw-r--r-- | include/scrnintstr.h | 5 | ||||
-rw-r--r-- | randr/rrcrtc.c | 60 |
7 files changed, 179 insertions, 62 deletions
diff --git a/dix/pixmap.c b/dix/pixmap.c index 00e298f5c..a20c38dd2 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, + format, 0L, NULL, serverClient, &error); + if (!dst) + return; + + error = SetPictureTransform(src, &dirty->transform); + if (error) + return; + while (n--) { + BoxRec dst_box; + + dst_box = *b; + dst_box.x1 += dirty->x; + dst_box.x2 += dirty->x; + dst_box.y1 += dirty->y; + dst_box.y2 += dirty->y; + pixman_f_transform_bounds(&dirty->f_inverse, &dst_box); + + CompositePicture(PictOpSrc, + src, NULL, dst, + dst_box.x1, + dst_box.y1, + 0, 0, + dst_box.x1, + dst_box.y1, + dst_box.x2 - dst_box.x1, + dst_box.y2 - dst_box.y1); + b++; + } + + FreePicture(src, None); + FreePicture(dst, None); +} + /* * this function can possibly be improved and optimised, by clipping * instead of iterating @@ -227,10 +322,7 @@ PixmapStopDirtyTracking(PixmapPtr src, PixmapPtr slave_dst) Bool PixmapSyncDirtyHelper(PixmapDirtyUpdatePtr dirty, RegionPtr dirty_region) { ScreenPtr pScreen = dirty->src->drawable.pScreen; - int n; - BoxPtr b; RegionPtr region = DamageRegion(dirty->damage); - GCPtr pGC; PixmapPtr dst; SourceValidateProcPtr SourceValidate; @@ -242,6 +334,14 @@ Bool PixmapSyncDirtyHelper(PixmapDirtyUpdatePtr dirty, RegionPtr dirty_region) */ SourceValidate = pScreen->SourceValidate; pScreen->SourceValidate = NULL; + /* nasty hobbits */ + if (dirty->rotation == RR_Rotate_90 || + dirty->rotation == RR_Rotate_270) { + int tmp; + tmp = dirty_region->extents.x2; + dirty_region->extents.x2 = dirty_region->extents.y2; + dirty_region->extents.y2 = tmp; + } RegionTranslate(dirty_region, dirty->x, dirty->y); RegionIntersect(dirty_region, dirty_region, region); @@ -256,26 +356,11 @@ Bool PixmapSyncDirtyHelper(PixmapDirtyUpdatePtr dirty, RegionPtr dirty_region) dst = dirty->slave_dst; RegionTranslate(dirty_region, -dirty->x, -dirty->y); - 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); + if (!pScreen->root || dirty->rotation == RR_Rotate_0) + PixmapDirtyCopyArea(dst, dirty, dirty_region); + else + PixmapDirtyCompositeRotate(dst, dirty, dirty_region); pScreen->SourceValidate = SourceValidate; return TRUE; } diff --git a/hw/xfree86/drivers/modesetting/drmmode_display.c b/hw/xfree86/drivers/modesetting/drmmode_display.c index e36c092c3..3e4bf70a7 100644 --- a/hw/xfree86/drivers/modesetting/drmmode_display.c +++ b/hw/xfree86/drivers/modesetting/drmmode_display.c @@ -551,7 +551,7 @@ drmmode_set_scanout_pixmap_gpu(xf86CrtcPtr crtc, PixmapPtr ppix) screen->height = screenpix->drawable.height = max_height; } drmmode_crtc->prime_pixmap_x = this_x; - PixmapStartDirtyTracking2(ppix, screenpix, 0, 0, this_x, 0); + PixmapStartDirtyTracking(ppix, screenpix, 0, 0, this_x, 0, RR_Rotate_0); return TRUE; } diff --git a/hw/xfree86/modes/xf86Rotate.c b/hw/xfree86/modes/xf86Rotate.c index 01cc764fd..63f27ca75 100644 --- a/hw/xfree86/modes/xf86Rotate.c +++ b/hw/xfree86/modes/xf86Rotate.c @@ -361,6 +361,8 @@ xf86CrtcRotate(xf86CrtcPtr crtc) RRTransformPtr transform = NULL; Bool damage = FALSE; + if (pScreen->isGPU) + return TRUE; if (crtc->transformPresent) transform = &crtc->transform; diff --git a/include/pixmap.h b/include/pixmap.h index 9656c3ade..a553c2eaa 100644 --- a/include/pixmap.h +++ b/include/pixmap.h @@ -50,7 +50,7 @@ SOFTWARE. #include "misc.h" #include "screenint.h" #include "regionstr.h" - +#include <X11/extensions/randr.h> /* types for Drawable */ #define DRAWABLE_WINDOW 0 #define DRAWABLE_PIXMAP 1 @@ -115,16 +115,12 @@ extern _X_EXPORT void FreePixmap(PixmapPtr /*pPixmap */ ); extern _X_EXPORT PixmapPtr PixmapShareToSlave(PixmapPtr pixmap, ScreenPtr slave); +#define HAS_DIRTYTRACKING_ROTATION 1 extern _X_EXPORT Bool PixmapStartDirtyTracking(PixmapPtr src, PixmapPtr slave_dst, - int x, int y); - -#define HAS_DIRTYTRACKING2 1 -extern _X_EXPORT Bool -PixmapStartDirtyTracking2(PixmapPtr src, - PixmapPtr slave_dst, - int x, int y, int dst_x, int dst_y); + int x, int y, int dst_x, int dst_y, + Rotation rotation); extern _X_EXPORT Bool PixmapStopDirtyTracking(PixmapPtr src, PixmapPtr slave_dst); diff --git a/include/pixmapstr.h b/include/pixmapstr.h index 380e48335..4bd246562 100644 --- a/include/pixmapstr.h +++ b/include/pixmapstr.h @@ -51,6 +51,8 @@ SOFTWARE. #include "regionstr.h" #include "privates.h" #include "damage.h" +#include <X11/extensions/randr.h> +#include "picturestr.h" typedef struct _Drawable { unsigned char type; /* DRAWABLE_<type> */ @@ -91,6 +93,9 @@ typedef struct _PixmapDirtyUpdate { DamagePtr damage; struct xorg_list ent; int dst_x, dst_y; + Rotation rotation; + PictTransform transform; + struct pixman_f_transform f_transform, f_inverse; } PixmapDirtyUpdateRec; static inline void diff --git a/include/scrnintstr.h b/include/scrnintstr.h index faf05630c..a627fe7ac 100644 --- a/include/scrnintstr.h +++ b/include/scrnintstr.h @@ -55,6 +55,7 @@ SOFTWARE. #include <X11/Xproto.h> #include "dix.h" #include "privates.h" +#include <X11/extensions/randr.h> typedef struct _PixmapFormat { unsigned char depth; @@ -340,7 +341,9 @@ typedef Bool (*SharePixmapBackingProcPtr)(PixmapPtr, ScreenPtr, void **); typedef Bool (*SetSharedPixmapBackingProcPtr)(PixmapPtr, void *); typedef Bool (*StartPixmapTrackingProcPtr)(PixmapPtr, PixmapPtr, - int x, int y); + int x, int y, + int dst_x, int dst_y, + Rotation rotation); typedef Bool (*StopPixmapTrackingProcPtr)(PixmapPtr, PixmapPtr); diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c index e95b049df..050d9751a 100644 --- a/randr/rrcrtc.c +++ b/randr/rrcrtc.c @@ -387,7 +387,7 @@ RRCrtcDetachScanoutPixmap(RRCrtcPtr crtc) static Bool rrCreateSharedPixmap(RRCrtcPtr crtc, int width, int height, - int x, int y) + int x, int y, Rotation rotation) { PixmapPtr mpix, spix; ScreenPtr master = crtc->pScreen->current_master; @@ -434,13 +434,33 @@ rrCreateSharedPixmap(RRCrtcPtr crtc, int width, int height, crtc->scanout_pixmap = spix; - master->StartPixmapTracking(mscreenpix, spix, x, y); + master->StartPixmapTracking(mscreenpix, spix, x, y, 0, 0, rotation); return TRUE; } +static void crtc_to_box(BoxPtr box, RRCrtcPtr crtc) +{ + box->x1 = crtc->x; + box->y1 = crtc->y; + switch (crtc->rotation) { + case RR_Rotate_0: + case RR_Rotate_180: + default: + box->x2 = crtc->x + crtc->mode->mode.width; + box->y2 = crtc->y + crtc->mode->mode.height; + break; + case RR_Rotate_90: + case RR_Rotate_270: + box->x2 = crtc->x + crtc->mode->mode.height; + box->y2 = crtc->y + crtc->mode->mode.width; + break; + } +} + static Bool rrCheckPixmapBounding(ScreenPtr pScreen, - RRCrtcPtr rr_crtc, int x, int y, int w, int h) + RRCrtcPtr rr_crtc, Rotation rotation, + int x, int y, int w, int h) { RegionRec root_pixmap_region, total_region, new_crtc_region; int c; @@ -461,16 +481,19 @@ rrCheckPixmapBounding(ScreenPtr pScreen, if (crtc == rr_crtc) { newbox.x1 = x; - newbox.x2 = x + w; newbox.y1 = y; - newbox.y2 = y + h; + if (rotation == RR_Rotate_90 || + rotation == RR_Rotate_270) { + newbox.x2 = x + h; + newbox.y2 = y + w; + } else { + newbox.x2 = x + w; + newbox.y2 = y + h; + } } else { if (!crtc->mode) continue; - newbox.x1 = crtc->x; - newbox.x2 = crtc->x + crtc->mode->mode.width; - newbox.y1 = crtc->y; - newbox.y2 = crtc->y + crtc->mode->mode.height; + crtc_to_box(&newbox, crtc); } RegionInit(&new_crtc_region, &newbox, 1); RegionUnion(&total_region, &total_region, &new_crtc_region); @@ -483,17 +506,20 @@ rrCheckPixmapBounding(ScreenPtr pScreen, if (slave_crtc == rr_crtc) { newbox.x1 = x; - newbox.x2 = x + w; newbox.y1 = y; - newbox.y2 = y + h; + if (rotation == RR_Rotate_90 || + rotation == RR_Rotate_270) { + newbox.x2 = x + h; + newbox.y2 = y + w; + } else { + newbox.x2 = x + w; + newbox.y2 = y + h; + } } else { if (!slave_crtc->mode) continue; - newbox.x1 = slave_crtc->x; - newbox.x2 = slave_crtc->x + slave_crtc->mode->mode.width; - newbox.y1 = slave_crtc->y; - newbox.y2 = slave_crtc->y + slave_crtc->mode->mode.height; + crtc_to_box(&newbox, slave_crtc); } RegionInit(&new_crtc_region, &newbox, 1); RegionUnion(&total_region, &total_region, &new_crtc_region); @@ -561,12 +587,12 @@ RRCrtcSet(RRCrtcPtr crtc, height = mode->mode.height; } ret = rrCheckPixmapBounding(master, crtc, - x, y, width, height); + rotation, x, y, width, height); if (!ret) return FALSE; if (pScreen->current_master) { - ret = rrCreateSharedPixmap(crtc, width, height, x, y); + ret = rrCreateSharedPixmap(crtc, width, height, x, y, rotation); } } #if RANDR_12_INTERFACE |