diff options
-rw-r--r-- | src/drmmode_display.c | 95 | ||||
-rw-r--r-- | src/drmmode_display.h | 3 | ||||
-rw-r--r-- | src/radeon_kms.c | 92 |
3 files changed, 124 insertions, 66 deletions
diff --git a/src/drmmode_display.c b/src/drmmode_display.c index 2afeeb02..2b80c21d 100644 --- a/src/drmmode_display.c +++ b/src/drmmode_display.c @@ -523,10 +523,20 @@ drmmode_crtc_scanout_destroy(drmmode_ptr drmmode, radeon_bo_unref(scanout->bo); scanout->bo = NULL; } +} - if (scanout->damage) { - DamageDestroy(scanout->damage); - scanout->damage = NULL; +static void +drmmode_crtc_scanout_free(drmmode_crtc_private_ptr drmmode_crtc) +{ + drmmode_crtc_scanout_destroy(drmmode_crtc->drmmode, + &drmmode_crtc->scanout[0]); + drmmode_crtc_scanout_destroy(drmmode_crtc->drmmode, + &drmmode_crtc->scanout[1]); + + if (drmmode_crtc->scanout_damage) { + DamageDestroy(drmmode_crtc->scanout_damage); + drmmode_crtc->scanout_damage = NULL; + RegionUninit(&drmmode_crtc->scanout_last_region); } } @@ -536,15 +546,8 @@ drmmode_scanout_free(ScrnInfoPtr scrn) xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); int c; - for (c = 0; c < xf86_config->num_crtc; c++) { - drmmode_crtc_private_ptr drmmode_crtc = - xf86_config->crtc[c]->driver_private; - - drmmode_crtc_scanout_destroy(drmmode_crtc->drmmode, - &drmmode_crtc->scanout[0]); - drmmode_crtc_scanout_destroy(drmmode_crtc->drmmode, - &drmmode_crtc->scanout[1]); - } + for (c = 0; c < xf86_config->num_crtc; c++) + drmmode_crtc_scanout_free(xf86_config->crtc[c]->driver_private); } static void * @@ -797,8 +800,7 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode, fb_id = drmmode_crtc->rotate.fb_id; x = y = 0; - drmmode_crtc_scanout_destroy(drmmode, &drmmode_crtc->scanout[0]); - drmmode_crtc_scanout_destroy(drmmode, &drmmode_crtc->scanout[1]); + drmmode_crtc_scanout_free(drmmode_crtc); } else if ( #ifdef RADEON_PIXMAP_SHARING !pScreen->isGPU && @@ -813,42 +815,40 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode, &drmmode_crtc->scanout[i], mode->HDisplay, mode->VDisplay); - - if (drmmode_crtc->scanout[i].pixmap) { - RegionPtr pRegion; - BoxPtr pBox; - - if (!drmmode_crtc->scanout[i].damage) { - drmmode_crtc->scanout[i].damage = - DamageCreate(radeon_screen_damage_report, - NULL, DamageReportRawRegion, - TRUE, pScreen, NULL); - DamageRegister(&pScreen->GetScreenPixmap(pScreen)->drawable, - drmmode_crtc->scanout[i].damage); - } - - pRegion = DamageRegion(drmmode_crtc->scanout[i].damage); - RegionUninit(pRegion); - pRegion->data = NULL; - pBox = RegionExtents(pRegion); - pBox->x1 = min(pBox->x1, x); - pBox->y1 = min(pBox->y1, y); - - switch (crtc->rotation & 0xf) { - case RR_Rotate_90: - case RR_Rotate_270: - pBox->x2 = max(pBox->x2, x + mode->VDisplay); - pBox->y2 = max(pBox->y2, y + mode->HDisplay); - break; - default: - pBox->x2 = max(pBox->x2, x + mode->HDisplay); - pBox->y2 = max(pBox->y2, y + mode->VDisplay); - } - } } if (drmmode_crtc->scanout[0].pixmap && (!info->tear_free || drmmode_crtc->scanout[1].pixmap)) { + RegionPtr pRegion; + BoxPtr pBox; + + if (!drmmode_crtc->scanout_damage) { + drmmode_crtc->scanout_damage = + DamageCreate(radeon_screen_damage_report, + NULL, DamageReportRawRegion, + TRUE, pScreen, NULL); + DamageRegister(&pScreen->GetScreenPixmap(pScreen)->drawable, + drmmode_crtc->scanout_damage); + } + + pRegion = DamageRegion(drmmode_crtc->scanout_damage); + RegionUninit(pRegion); + pRegion->data = NULL; + pBox = RegionExtents(pRegion); + pBox->x1 = min(pBox->x1, x); + pBox->y1 = min(pBox->y1, y); + + switch (crtc->rotation & 0xf) { + case RR_Rotate_90: + case RR_Rotate_270: + pBox->x2 = max(pBox->x2, x + mode->VDisplay); + pBox->y2 = max(pBox->y2, y + mode->HDisplay); + break; + default: + pBox->x2 = max(pBox->x2, x + mode->HDisplay); + pBox->y2 = max(pBox->y2, y + mode->VDisplay); + } + drmmode_crtc->scanout_id = 0; fb_id = drmmode_crtc->scanout[0].fb_id; x = y = 0; @@ -1125,8 +1125,7 @@ drmmode_set_scanout_pixmap(xf86CrtcPtr crtc, PixmapPtr ppix) if (crtc->randr_crtc->scanout_pixmap) PixmapStopDirtyTracking(crtc->randr_crtc->scanout_pixmap, drmmode_crtc->scanout[0].pixmap); - drmmode_crtc_scanout_destroy(drmmode_crtc->drmmode, - &drmmode_crtc->scanout[0]); + drmmode_crtc_scanout_free(drmmode_crtc); return TRUE; } diff --git a/src/drmmode_display.h b/src/drmmode_display.h index 53c79268..5df9773d 100644 --- a/src/drmmode_display.h +++ b/src/drmmode_display.h @@ -73,7 +73,6 @@ typedef struct { struct drmmode_scanout { struct radeon_bo *bo; PixmapPtr pixmap; - DamagePtr damage; unsigned fb_id; int width, height; }; @@ -85,6 +84,8 @@ typedef struct { struct radeon_bo *cursor_bo; struct drmmode_scanout rotate; struct drmmode_scanout scanout[2]; + DamagePtr scanout_damage; + RegionRec scanout_last_region; unsigned scanout_id; Bool scanout_update_pending; int dpms_mode; diff --git a/src/radeon_kms.c b/src/radeon_kms.c index 568c49e3..bcaa024c 100644 --- a/src/radeon_kms.c +++ b/src/radeon_kms.c @@ -402,8 +402,6 @@ radeon_scanout_extents_intersect(xf86CrtcPtr xf86_crtc, BoxPtr extents, int w, return (extents->x1 < extents->x2 && extents->y1 < extents->y2); } -#ifdef RADEON_PIXMAP_SHARING - static RegionPtr transform_region(RegionPtr region, struct pict_f_transform *transform, int w, int h) @@ -442,6 +440,70 @@ transform_region(RegionPtr region, struct pict_f_transform *transform, return transformed; } +static void +radeon_sync_scanout_pixmaps(xf86CrtcPtr xf86_crtc, RegionPtr new_region, + int scanout_id) +{ + drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private; + DrawablePtr dst = &drmmode_crtc->scanout[scanout_id].pixmap->drawable; + DrawablePtr src = &drmmode_crtc->scanout[scanout_id ^ 1].pixmap->drawable; + RegionPtr last_region = &drmmode_crtc->scanout_last_region; + ScrnInfoPtr scrn = xf86_crtc->scrn; + ScreenPtr pScreen = scrn->pScreen; + RADEONInfoPtr info = RADEONPTR(scrn); + RegionRec remaining; + RegionPtr sync_region = NULL; + BoxRec extents; + Bool force; + GCPtr gc; + + if (RegionNil(last_region)) + return; + + RegionNull(&remaining); + RegionSubtract(&remaining, last_region, new_region); + if (RegionNil(&remaining)) + goto uninit; + + extents = *RegionExtents(&remaining); + if (!radeon_scanout_extents_intersect(xf86_crtc, &extents, dst->width, + dst->height)) + goto uninit; + +#if XF86_CRTC_VERSION >= 4 + if (xf86_crtc->driverIsPerformingTransform) { + sync_region = transform_region(&remaining, + &xf86_crtc->f_framebuffer_to_crtc, + dst->width, dst->height); + } else +#endif /* XF86_CRTC_VERSION >= 4 */ + { + sync_region = RegionDuplicate(&remaining); + RegionTranslate(sync_region, -xf86_crtc->x, -xf86_crtc->y); + } + + force = info->accel_state->force; + info->accel_state->force = TRUE; + + gc = GetScratchGC(dst->depth, pScreen); + if (gc) { + ValidateGC(dst, gc); + gc->funcs->ChangeClip(gc, CT_REGION, sync_region, 0); + sync_region = NULL; + gc->ops->CopyArea(src, dst, gc, 0, 0, dst->width, dst->height, 0, 0); + FreeScratchGC(gc); + } + + info->accel_state->force = force; + + uninit: + if (sync_region) + RegionDestroy(sync_region); + RegionUninit(&remaining); +} + +#ifdef RADEON_PIXMAP_SHARING + static RegionPtr dirty_region(PixmapDirtyUpdatePtr dirty) { @@ -660,13 +722,12 @@ static Bool radeon_scanout_do_update(xf86CrtcPtr xf86_crtc, int scanout_id) { drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private; - ScrnInfoPtr scrn; - DamagePtr pDamage; - RegionPtr pRegion; + RegionPtr pRegion = DamageRegion(drmmode_crtc->scanout_damage); + ScrnInfoPtr scrn = xf86_crtc->scrn; + ScreenPtr pScreen = scrn->pScreen; + RADEONInfoPtr info = RADEONPTR(scrn); DrawablePtr pDraw; - ScreenPtr pScreen; BoxRec extents; - RADEONInfoPtr info; Bool force; if (!xf86_crtc->enabled || @@ -674,24 +735,21 @@ radeon_scanout_do_update(xf86CrtcPtr xf86_crtc, int scanout_id) !drmmode_crtc->scanout[scanout_id].pixmap) return FALSE; - pDamage = drmmode_crtc->scanout[scanout_id].damage; - if (!pDamage) - return FALSE; - - pRegion = DamageRegion(pDamage); if (!RegionNotEmpty(pRegion)) return FALSE; pDraw = &drmmode_crtc->scanout[scanout_id].pixmap->drawable; - pScreen = pDraw->pScreen; extents = *RegionExtents(pRegion); - RegionEmpty(pRegion); if (!radeon_scanout_extents_intersect(xf86_crtc, &extents, pDraw->width, pDraw->height)) return FALSE; - scrn = xf86_crtc->scrn; - info = RADEONPTR(scrn); + if (info->tear_free) { + radeon_sync_scanout_pixmaps(xf86_crtc, pRegion, scanout_id); + RegionCopy(&drmmode_crtc->scanout_last_region, pRegion); + } + RegionEmpty(pRegion); + force = info->accel_state->force; info->accel_state->force = TRUE; @@ -807,7 +865,7 @@ radeon_scanout_update(xf86CrtcPtr xf86_crtc) drmmode_crtc->pending_dpms_mode != DPMSModeOn) return; - pDamage = drmmode_crtc->scanout[0].damage; + pDamage = drmmode_crtc->scanout_damage; if (!pDamage) return; |