summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2014-07-17 14:40:51 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2014-07-17 15:20:05 +0100
commita45b2ea11c15f35c36330ff27cb45854a29c2e2c (patch)
tree59e71316b8e266f34ae340fa7315b29f222e92e5
parent339c9dd0d5206180995731ab22304776e544f2f7 (diff)
sna: Handle rotated slaved scanouts
As per the usual handling of rotated scanouts with unsupported rotations, we stage the drawing onto a backbuffer then rotate onto the crtc later. The difference here is that we must read the contents from the master pixmap rather than our own screen pixmap. Spotted was looking at slaved scanouts mistakenly setting the CRTC transformed flag. Reported-by: Tomas Pruzina <pruzinat@gmail.com> Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=81383 Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r--src/sna/sna_display.c155
-rw-r--r--src/sna/sna_driver.c5
2 files changed, 116 insertions, 44 deletions
diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c
index 7c70b4cc..584cb0d1 100644
--- a/src/sna/sna_display.c
+++ b/src/sna/sna_display.c
@@ -118,7 +118,8 @@ struct sna_crtc {
xf86CrtcPtr base;
struct drm_mode_modeinfo kmode;
int dpms_mode;
- PixmapPtr scanout_pixmap;
+ PixmapPtr slave_pixmap;
+ DamagePtr slave_damage;
struct kgem_bo *bo, *shadow_bo;
struct sna_cursor *cursor;
uint32_t offset;
@@ -967,7 +968,7 @@ sna_crtc_apply(xf86CrtcPtr crtc)
VG_CLEAR(arg);
arg.crtc_id = sna_crtc->id;
arg.fb_id = fb_id(sna_crtc->bo);
- if (sna_crtc->transform) {
+ if (sna_crtc->transform || sna_crtc->slave_pixmap) {
arg.x = 0;
arg.y = 0;
sna_crtc->offset = 0;
@@ -1309,6 +1310,21 @@ static void sna_mode_disable_shadow(struct sna *sna)
sna->mode.shadow_dirty = false;
}
+static void sna_crtc_slave_damage(DamagePtr damage, RegionPtr region, void *closure)
+{
+ struct sna_crtc *crtc = closure;
+ struct sna *sna = to_sna(crtc->base->scrn);
+ RegionPtr scr;
+
+ assert(crtc->slave_damage == damage);
+ assert(sna->mode.shadow_damage);
+
+ RegionTranslate(region, crtc->base->x, crtc->base->y);
+ scr = DamageRegion(sna->mode.shadow_damage);
+ RegionUnion(scr, scr, region);
+ RegionTranslate(region, -crtc->base->x, -crtc->base->y);
+}
+
static bool sna_crtc_enable_shadow(struct sna *sna, struct sna_crtc *crtc)
{
if (crtc->shadow) {
@@ -1325,6 +1341,21 @@ static bool sna_crtc_enable_shadow(struct sna *sna, struct sna_crtc *crtc)
assert(sna->mode.shadow == NULL);
}
+ if (crtc->slave_pixmap) {
+ assert(crtc->slave_damage == NULL);
+
+ crtc->slave_damage = DamageCreate(sna_crtc_slave_damage, NULL,
+ DamageReportRawRegion, TRUE,
+ sna->scrn->pScreen, crtc);
+ if (crtc->slave_damage == NULL) {
+ if (!--sna->mode.shadow_active)
+ sna_mode_disable_shadow(sna);
+ return false;
+ }
+
+ DamageRegister(&crtc->slave_pixmap->drawable, crtc->slave_damage);
+ }
+
crtc->shadow = true;
sna->mode.shadow_active++;
return true;
@@ -1339,8 +1370,12 @@ static void sna_crtc_disable_shadow(struct sna *sna, struct sna_crtc *crtc)
DBG(("%s: disabling for crtc %d\n", __FUNCTION__, crtc->id));
assert(sna->mode.shadow_active > 0);
- if (!--sna->mode.shadow_active)
- sna_mode_disable_shadow(sna);
+ if (crtc->slave_damage) {
+ assert(crtc->slave_pixmap);
+ DamageUnregister(&crtc->slave_scanout->drawable, crtc->slave_damage);
+ DamageDestroy(crtc->slave_damage);
+ crtc->slave_damage = NULL;
+ }
if (crtc->shadow_bo) {
if (!crtc->transform) {
@@ -1361,6 +1396,9 @@ static void sna_crtc_disable_shadow(struct sna *sna, struct sna_crtc *crtc)
crtc->shadow_bo = NULL;
}
+ if (!--sna->mode.shadow_active)
+ sna_mode_disable_shadow(sna);
+
crtc->shadow = false;
}
@@ -1703,21 +1741,7 @@ static struct kgem_bo *sna_crtc_attach(xf86CrtcPtr crtc)
sna_crtc->transform = false;
sna_crtc->rotation = RR_Rotate_0;
- if (sna_crtc->scanout_pixmap) {
- DBG(("%s: attaching to scanout pixmap\n", __FUNCTION__));
-
- bo = sna_pixmap_pin(sna_crtc->scanout_pixmap, PIN_SCANOUT);
- if (bo == NULL)
- return NULL;
-
- if (!get_fb(sna, bo,
- sna_crtc->scanout_pixmap->drawable.width,
- sna_crtc->scanout_pixmap->drawable.height))
- return NULL;
-
- sna_crtc->transform = true;
- return kgem_bo_reference(bo);
- } else if (use_shadow(sna, crtc)) {
+ if (use_shadow(sna, crtc)) {
unsigned long tiled_limit;
int tiling;
@@ -1756,17 +1780,29 @@ static struct kgem_bo *sna_crtc_attach(xf86CrtcPtr crtc)
sna_crtc->transform = true;
return bo;
} else {
- unsigned rotation;
+ if (sna_crtc->slave_pixmap) {
+ DBG(("%s: attaching to scanout pixmap\n", __FUNCTION__));
+ bo = sna_pixmap_pin(sna_crtc->slave_pixmap, PIN_SCANOUT);
+ if (bo == NULL)
+ return NULL;
- DBG(("%s: attaching to framebuffer\n", __FUNCTION__));
- bo = sna_pixmap_pin(sna->front, PIN_SCANOUT);
- if (bo == NULL)
- return NULL;
+ if (!get_fb(sna, bo,
+ sna_crtc->slave_pixmap->drawable.width,
+ sna_crtc->slave_pixmap->drawable.height))
+ return NULL;
+ } else {
+ DBG(("%s: attaching to framebuffer\n", __FUNCTION__));
+ bo = sna_pixmap_pin(sna->front, PIN_SCANOUT);
+ if (bo == NULL)
+ return NULL;
- if (!get_fb(sna, bo, scrn->virtualX, scrn->virtualY))
- return NULL;
+ if (!get_fb(sna, bo, scrn->virtualX, scrn->virtualY))
+ return NULL;
+ }
if (sna->flags & SNA_TEAR_FREE) {
+ assert(sna_crtc->slave_pixmap == NULL);
+
DBG(("%s: enabling TearFree shadow\n", __FUNCTION__));
if (!sna_crtc_enable_shadow(sna, sna_crtc))
return NULL;
@@ -1805,9 +1841,8 @@ static struct kgem_bo *sna_crtc_attach(xf86CrtcPtr crtc)
} else
sna_crtc_disable_shadow(sna, sna_crtc);
- rotation = rotation_reduce(&sna_crtc->primary, crtc->rotation);
- assert(sna_crtc->primary.rotation.supported & rotation);
- sna_crtc->rotation = rotation;
+ sna_crtc->rotation = rotation_reduce(&sna_crtc->primary, crtc->rotation);
+ assert(sna_crtc->primary.rotation.supported & sna_crtc->rotation);
return kgem_bo_reference(bo);
}
}
@@ -2127,11 +2162,19 @@ sna_crtc_destroy(xf86CrtcPtr crtc)
static Bool
sna_crtc_set_scanout_pixmap(xf86CrtcPtr crtc, PixmapPtr pixmap)
{
- assert(to_sna_crtc(crtc));
+ struct sna_crtc *sna_crtc = to_sna_crtc(crtc);
+
+ if (sna_crtc == NULL)
+ return FALSE;
+
DBG(("%s: CRTC:%d, pipe=%d setting scanout pixmap=%ld\n",
- __FUNCTION__,to_sna_crtc(crtc)->id, to_sna_crtc(crtc)->pipe,
+ __FUNCTION__, sna_crtc->id, sna_crtc->pipe,
pixmap ? pixmap->drawable.serialNumber : 0));
- to_sna_crtc(crtc)->scanout_pixmap = pixmap;
+
+ sna_crtc->slave_pixmap = pixmap;
+ if (pixmap == NULL)
+ sna_crtc_disable(crtc);
+
return TRUE;
}
#endif
@@ -6053,11 +6096,26 @@ static void transformed_box(BoxRec *box, xf86CrtcPtr crtc)
box->y2 = crtc->mode.VDisplay;
}
+inline static DrawablePtr crtc_source(xf86CrtcPtr crtc, int16_t *sx, int16_t *sy)
+{
+ struct sna_crtc *sna_crtc = to_sna_crtc(crtc);
+ if (sna_crtc->slave_pixmap) {
+ *sx = -crtc->x;
+ *sy = -crtc->y;
+ return &sna_crtc->slave_pixmap->drawable;
+ } else {
+ *sx = *sy = 0;
+ return &to_sna(crtc->scrn)->front->drawable;
+ }
+}
+
static void
sna_crtc_redisplay__fallback(xf86CrtcPtr crtc, RegionPtr region, struct kgem_bo *bo)
{
+ int16_t sx, sy;
struct sna *sna = to_sna(crtc->scrn);
ScreenPtr screen = sna->scrn->pScreen;
+ DrawablePtr draw = crtc_source(crtc, &sx, &sy);
PictFormatPtr format;
PicturePtr src, dst;
PixmapPtr pixmap;
@@ -6066,7 +6124,7 @@ sna_crtc_redisplay__fallback(xf86CrtcPtr crtc, RegionPtr region, struct kgem_bo
DBG(("%s: compositing transformed damage boxes\n", __FUNCTION__));
- error = sna_render_format_for_depth(sna->front->drawable.depth);
+ error = sna_render_format_for_depth(draw->depth);
depth = PIXMAN_FORMAT_DEPTH(error);
format = PictureMatchFormat(screen, depth, error);
if (format == NULL) {
@@ -6085,11 +6143,11 @@ sna_crtc_redisplay__fallback(xf86CrtcPtr crtc, RegionPtr region, struct kgem_bo
if (!screen->ModifyPixmapHeader(pixmap,
crtc->mode.HDisplay, crtc->mode.VDisplay,
- depth, sna->front->drawable.bitsPerPixel,
+ depth, draw->bitsPerPixel,
bo->pitch, ptr))
goto free_pixmap;
- src = CreatePicture(None, &sna->front->drawable, format,
+ src = CreatePicture(None, draw, format,
0, NULL, serverClient, &error);
if (!src)
goto free_pixmap;
@@ -6124,7 +6182,7 @@ sna_crtc_redisplay__fallback(xf86CrtcPtr crtc, RegionPtr region, struct kgem_bo
box.x1, box.y1, box.x2, box.y2));
fbComposite(PictOpSrc, src, NULL, dst,
- box.x1, box.y1,
+ box.x1 + sx, box.y1 + sy,
0, 0,
box.x1, box.y1,
box.x2 - box.x1, box.y2 - box.y1);
@@ -6142,8 +6200,10 @@ free_pixmap:
static void
sna_crtc_redisplay__composite(xf86CrtcPtr crtc, RegionPtr region, struct kgem_bo *bo)
{
+ int16_t sx, sy;
struct sna *sna = to_sna(crtc->scrn);
ScreenPtr screen = crtc->scrn->pScreen;
+ DrawablePtr draw = crtc_source(crtc, &sx, &sy);
struct sna_composite_op tmp;
PictFormatPtr format;
PicturePtr src, dst;
@@ -6153,7 +6213,7 @@ sna_crtc_redisplay__composite(xf86CrtcPtr crtc, RegionPtr region, struct kgem_bo
DBG(("%s: compositing transformed damage boxes\n", __FUNCTION__));
- error = sna_render_format_for_depth(sna->front->drawable.depth);
+ error = sna_render_format_for_depth(draw->depth);
depth = PIXMAN_FORMAT_DEPTH(error);
format = PictureMatchFormat(screen, depth, error);
if (format == NULL) {
@@ -6168,7 +6228,7 @@ sna_crtc_redisplay__composite(xf86CrtcPtr crtc, RegionPtr region, struct kgem_bo
if (!screen->ModifyPixmapHeader(pixmap,
crtc->mode.HDisplay, crtc->mode.VDisplay,
- depth, sna->front->drawable.bitsPerPixel,
+ depth, draw->bitsPerPixel,
bo->pitch, NULL))
goto free_pixmap;
@@ -6177,7 +6237,7 @@ sna_crtc_redisplay__composite(xf86CrtcPtr crtc, RegionPtr region, struct kgem_bo
goto free_pixmap;
}
- src = CreatePicture(None, &sna->front->drawable, format,
+ src = CreatePicture(None, draw, format,
0, NULL, serverClient, &error);
if (!src)
goto free_pixmap;
@@ -6200,7 +6260,7 @@ sna_crtc_redisplay__composite(xf86CrtcPtr crtc, RegionPtr region, struct kgem_bo
if (!sna->render.composite(sna,
PictOpSrc, src, NULL, dst,
- 0, 0,
+ sx, sy,
0, 0,
0, 0,
crtc->mode.HDisplay, crtc->mode.VDisplay,
@@ -6238,10 +6298,11 @@ free_pixmap:
static void
sna_crtc_redisplay(xf86CrtcPtr crtc, RegionPtr region)
{
+ int16_t tx, ty, sx, sy;
struct sna *sna = to_sna(crtc->scrn);
struct sna_crtc *sna_crtc = to_sna_crtc(crtc);
- struct sna_pixmap *priv = sna_pixmap(sna->front);
- int16_t tx, ty;
+ DrawablePtr draw = crtc_source(crtc, &sx, &sy);
+ struct sna_pixmap *priv = sna_pixmap((PixmapPtr)draw);
assert(sna_crtc);
DBG(("%s: crtc %d [pipe=%d], damage (%d, %d), (%d, %d) x %d\n",
@@ -6257,7 +6318,7 @@ sna_crtc_redisplay(xf86CrtcPtr crtc, RegionPtr region)
RegionTranslate(region, -crtc->bounds.x1, -crtc->bounds.y1);
sna_blt_fill_boxes(sna, GXcopy,
- sna_crtc->bo, sna->front->drawable.bitsPerPixel,
+ sna_crtc->bo, draw->bitsPerPixel,
priv->clear_color,
region_rects(region), region_num_rects(region));
return;
@@ -6276,7 +6337,7 @@ sna_crtc_redisplay(xf86CrtcPtr crtc, RegionPtr region)
tmp.bitsPerPixel = sna->front->drawable.bitsPerPixel;
if (sna->render.copy_boxes(sna, GXcopy,
- &sna->front->drawable, priv->gpu_bo, 0, 0,
+ draw, priv->gpu_bo, sx, sy,
&tmp, sna_crtc->bo, -tx, -ty,
region_rects(region), region_num_rects(region), 0))
return;
@@ -6403,6 +6464,9 @@ void sna_mode_redisplay(struct sna *sna)
if (RegionNotEmpty(&damage))
sna_crtc_redisplay__fallback(crtc, &damage, sna_crtc->bo);
RegionUninit(&damage);
+
+ if (sna_crtc->slave_damage)
+ DamageEmpty(sna_crtc->slave_damage);
}
RegionEmpty(region);
@@ -6530,6 +6594,9 @@ disable1:
}
}
RegionUninit(&damage);
+
+ if (sna_crtc->slave_damage)
+ DamageEmpty(sna_crtc->slave_damage);
}
if (sna->mode.shadow) {
diff --git a/src/sna/sna_driver.c b/src/sna/sna_driver.c
index 4454b327..2eac852f 100644
--- a/src/sna/sna_driver.c
+++ b/src/sna/sna_driver.c
@@ -487,6 +487,11 @@ static void setup_dri(struct sna *sna)
static bool enable_tear_free(struct sna *sna)
{
+#if HAS_PIXMAP_SHARING
+ if (sna->scrn->is_gpu)
+ return false;
+#endif
+
/* Under certain conditions, we should enable TearFree by default,
* for example when the hardware requires pageflipping to run within
* its power/performance budget.