diff options
author | Michel Dänzer <michel.daenzer@amd.com> | 2015-03-18 16:23:24 +0900 |
---|---|---|
committer | Michel Dänzer <michel@daenzer.net> | 2015-04-03 11:42:00 +0900 |
commit | ae92d1765fa370a8d94c2856ad6c45d273ec3c69 (patch) | |
tree | 1c602a906d80ac92620f4a2d48e1b4353d5a9d19 | |
parent | eea79472a84672ee4dc7adc4487cec6a4037048a (diff) |
glamor: Add Option "ShadowPrimary" v2
When this option is enabled, most pixmaps (including the screen pixmap)
are allocated in system RAM and mostly accessed by the CPU. Changed areas
of the screen pixmap are copied to dedicated per-CRTC scanout pixmaps
regularly, triggered by the vblank interrupt.
v2:
* Set region data pointer to NULL for keeping only the extents
* Move pRegion and pBox local variable declarations closer to their uses
in drmmode_set_mode_major()
-rw-r--r-- | configure.ac | 10 | ||||
-rw-r--r-- | man/radeon.man | 16 | ||||
-rw-r--r-- | src/drmmode_display.c | 89 | ||||
-rw-r--r-- | src/drmmode_display.h | 6 | ||||
-rw-r--r-- | src/radeon.h | 2 | ||||
-rw-r--r-- | src/radeon_bo_helper.c | 7 | ||||
-rw-r--r-- | src/radeon_dri3.c | 15 | ||||
-rw-r--r-- | src/radeon_glamor.c | 60 | ||||
-rw-r--r-- | src/radeon_glamor.h | 10 | ||||
-rw-r--r-- | src/radeon_kms.c | 179 |
10 files changed, 372 insertions, 22 deletions
diff --git a/configure.ac b/configure.ac index 57b4c1ca..4ca53525 100644 --- a/configure.ac +++ b/configure.ac @@ -125,6 +125,16 @@ else fi AM_CONDITIONAL(GLAMOR, test x$GLAMOR != xno) +AC_CHECK_DECL(fbGlyphs, + [AC_DEFINE(HAVE_FBGLYPHS, 1, [Have fbGlyphs API])], [], + [#include <X11/Xmd.h> + #include <X11/Xfuncproto.h> + #include <X11/extensions/renderproto.h> + #include <xorg-server.h> + #include <picture.h> + #include <glyphstr.h> + #include <fbpict.h>]) + AC_CHECK_DECL(xorg_list_init, [AC_DEFINE(HAVE_XORG_LIST, 1, [Have xorg_list API])], [], [#include <X11/Xdefs.h> diff --git a/man/radeon.man b/man/radeon.man index 6e46f894..27037730 100644 --- a/man/radeon.man +++ b/man/radeon.man @@ -290,6 +290,22 @@ as of TAHITI, otherwise The following driver .B Options are supported for +.B glamor +: +.TP +.BI "Option \*qShadowPrimary\*q \*q" boolean \*q +This option enables a so-called "shadow primary" buffer for fast CPU access to +pixel data, and separate scanout buffers for each display controller (CRTC). +This may improve performance for some 2D workloads, potentially at the expense +of other (e.g. 3D, video) workloads. +Note in particular that enabling this option currently disables page flipping. +The default is +.B off. + +.PP +The following driver +.B Options +are supported for .B EXA : .TP diff --git a/src/drmmode_display.c b/src/drmmode_display.c index d8d3ca36..1f228698 100644 --- a/src/drmmode_display.c +++ b/src/drmmode_display.c @@ -33,6 +33,7 @@ #include <sys/ioctl.h> #include <time.h> #include "cursorstr.h" +#include "damagestr.h" #include "micmap.h" #include "xf86cmap.h" #include "radeon.h" @@ -489,6 +490,26 @@ drmmode_crtc_scanout_destroy(drmmode_ptr drmmode, } +void +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); + + if (drmmode_crtc->scanout_damage) { + DamageDestroy(drmmode_crtc->scanout_damage); + drmmode_crtc->scanout_damage = NULL; + } + } +} + static void * drmmode_crtc_scanout_allocate(xf86CrtcPtr crtc, struct drmmode_scanout *scanout, @@ -510,6 +531,13 @@ drmmode_crtc_scanout_allocate(xf86CrtcPtr crtc, return NULL; } + if (scanout->bo) { + if (scanout->width == width && scanout->height == height) + return scanout->bo->ptr; + + drmmode_crtc_scanout_destroy(drmmode, scanout); + } + rotate_pitch = RADEON_ALIGN(width, drmmode_get_pitch_align(pScrn, drmmode->cpp, 0)) * drmmode->cpp; @@ -531,6 +559,8 @@ drmmode_crtc_scanout_allocate(xf86CrtcPtr crtc, if (ret) ErrorF("failed to add scanout fb\n"); + scanout->width = width; + scanout->height = height; return scanout->bo->ptr; } @@ -543,6 +573,13 @@ drmmode_crtc_scanout_create(xf86CrtcPtr crtc, struct drmmode_scanout *scanout, drmmode_ptr drmmode = drmmode_crtc->drmmode; unsigned long rotate_pitch; + if (scanout->pixmap) { + if (scanout->width == width && scanout->height == height) + return scanout->pixmap; + + drmmode_crtc_scanout_destroy(drmmode, scanout); + } + if (!data) data = drmmode_crtc_scanout_allocate(crtc, scanout, width, height); @@ -562,6 +599,14 @@ drmmode_crtc_scanout_create(xf86CrtcPtr crtc, struct drmmode_scanout *scanout, return scanout->pixmap; } +static void +radeon_screen_damage_report(DamagePtr damage, RegionPtr region, void *closure) +{ + /* Only keep track of the extents */ + RegionUninit(&damage->damage); + damage->damage.data = NULL; +} + static Bool drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation, int x, int y) @@ -631,6 +676,8 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode, } if (mode) { + ScreenPtr pScreen = pScrn->pScreen; + for (i = 0; i < xf86_config->num_output; i++) { xf86OutputPtr output = xf86_config->output[i]; drmmode_output_private_ptr drmmode_output; @@ -656,11 +703,46 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode, if (crtc->randr_crtc && crtc->randr_crtc->scanout_pixmap) { x = drmmode_crtc->prime_pixmap_x; y = 0; + + drmmode_crtc_scanout_destroy(drmmode, &drmmode_crtc->scanout); } else #endif if (drmmode_crtc->rotate.fb_id) { fb_id = drmmode_crtc->rotate.fb_id; x = y = 0; + + drmmode_crtc_scanout_destroy(drmmode, &drmmode_crtc->scanout); + } else if (info->shadow_primary) { + drmmode_crtc_scanout_create(crtc, + &drmmode_crtc->scanout, + NULL, mode->HDisplay, + mode->VDisplay); + + if (drmmode_crtc->scanout.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); + pBox->x2 = max(pBox->x2, x + mode->HDisplay); + pBox->y2 = max(pBox->y2, y + mode->VDisplay); + + fb_id = drmmode_crtc->scanout.fb_id; + x = y = 0; + } } ret = drmModeSetCrtc(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, fb_id, x, y, output_ids, output_count, &kmode); @@ -1689,7 +1771,7 @@ drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height) if (front_bo) radeon_bo_wait(front_bo); - if (info->allowColorTiling) { + if (info->allowColorTiling && !info->shadow_primary) { if (info->ChipFamily >= CHIP_FAMILY_R600) { if (info->allowColorTiling2D) { tiling_flags |= RADEON_TILING_MACRO; @@ -1770,7 +1852,10 @@ drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height) scrn->virtualY = height; scrn->displayWidth = pitch / cpp; - info->front_bo = radeon_bo_open(info->bufmgr, 0, screen_size, base_align, RADEON_GEM_DOMAIN_VRAM, 0); + info->front_bo = radeon_bo_open(info->bufmgr, 0, screen_size, base_align, + info->shadow_primary ? + RADEON_GEM_DOMAIN_GTT : + RADEON_GEM_DOMAIN_VRAM, 0); if (!info->front_bo) goto fail; diff --git a/src/drmmode_display.h b/src/drmmode_display.h index 66078962..43a3a4a3 100644 --- a/src/drmmode_display.h +++ b/src/drmmode_display.h @@ -76,6 +76,7 @@ struct drmmode_scanout { struct radeon_bo *bo; PixmapPtr pixmap; unsigned fb_id; + int width, height; }; typedef struct { @@ -84,6 +85,9 @@ typedef struct { int hw_id; struct radeon_bo *cursor_bo; struct drmmode_scanout rotate; + struct drmmode_scanout scanout; + DamagePtr scanout_damage; + Bool scanout_update_pending; int dpms_mode; CARD64 dpms_last_ust; uint32_t dpms_last_seq; @@ -125,6 +129,8 @@ extern Bool drmmode_set_desired_modes(ScrnInfoPtr pScrn, drmmode_ptr drmmode); extern void drmmode_copy_fb(ScrnInfoPtr pScrn, drmmode_ptr drmmode); extern Bool drmmode_setup_colormap(ScreenPtr pScreen, ScrnInfoPtr pScrn); +extern void drmmode_scanout_free(ScrnInfoPtr scrn); + extern void drmmode_uevent_init(ScrnInfoPtr scrn, drmmode_ptr drmmode); extern void drmmode_uevent_fini(ScrnInfoPtr scrn, drmmode_ptr drmmode); diff --git a/src/radeon.h b/src/radeon.h index 80adc5d6..afb66b26 100644 --- a/src/radeon.h +++ b/src/radeon.h @@ -151,6 +151,7 @@ typedef enum { OPTION_SWAPBUFFERS_WAIT, OPTION_DELETE_DP12, OPTION_DRI3, + OPTION_SHADOW_PRIMARY, } RADEONOpts; @@ -476,6 +477,7 @@ typedef struct { struct radeon_accel_state *accel_state; Bool accelOn; Bool use_glamor; + Bool shadow_primary; Bool exa_pixmaps; Bool exa_force_create; XF86ModReqInfo exaReq; diff --git a/src/radeon_bo_helper.c b/src/radeon_bo_helper.c index fdff0328..ebbb192a 100644 --- a/src/radeon_bo_helper.c +++ b/src/radeon_bo_helper.c @@ -88,12 +88,15 @@ radeon_alloc_pixmap_bo(ScrnInfoPtr pScrn, int width, int height, int depth, if (usage_hint & RADEON_CREATE_PIXMAP_DEPTH) tiling |= RADEON_TILING_MACRO | RADEON_TILING_MICRO; + if ((usage_hint == CREATE_PIXMAP_USAGE_BACKING_PIXMAP && + info->shadow_primary) #ifdef CREATE_PIXMAP_USAGE_SHARED - if ((usage_hint & 0xffff) == CREATE_PIXMAP_USAGE_SHARED) { + || (usage_hint & 0xffff) == CREATE_PIXMAP_USAGE_SHARED +#endif + ) { tiling = 0; domain = RADEON_GEM_DOMAIN_GTT; } -#endif } /* Small pixmaps must not be macrotiled on R300, hw cannot sample them diff --git a/src/radeon_dri3.c b/src/radeon_dri3.c index 3a7322e5..1415a0df 100644 --- a/src/radeon_dri3.c +++ b/src/radeon_dri3.c @@ -101,8 +101,17 @@ static PixmapPtr radeon_dri3_pixmap_from_fd(ScreenPtr screen, if (RADEONPTR(xf86ScreenToScrn(screen))->use_glamor) { pixmap = glamor_pixmap_from_fd(screen, fd, width, height, stride, depth, bpp); - if (pixmap) - return pixmap; + if (pixmap) { + struct radeon_pixmap *priv = + calloc(1, sizeof(struct radeon_pixmap)); + + if (priv) { + radeon_set_pixmap_private(pixmap, priv); + return pixmap; + } + + screen->DestroyPixmap(pixmap); + } } #endif @@ -118,7 +127,7 @@ static PixmapPtr radeon_dri3_pixmap_from_fd(ScreenPtr screen, return NULL; } - pixmap = screen->CreatePixmap(screen, 0, 0, depth, 0); + pixmap = screen->CreatePixmap(screen, 0, 0, depth, RADEON_CREATE_PIXMAP_DRI2); if (!pixmap) return NULL; diff --git a/src/radeon_glamor.c b/src/radeon_glamor.c index 74d9584b..eccb8f7c 100644 --- a/src/radeon_glamor.c +++ b/src/radeon_glamor.c @@ -166,26 +166,24 @@ radeon_glamor_create_textured_pixmap(PixmapPtr pixmap, struct radeon_pixmap *pri priv->stride); } -#ifndef CREATE_PIXMAP_USAGE_SHARED -#define CREATE_PIXMAP_USAGE_SHARED RADEON_CREATE_PIXMAP_DRI2 -#endif - -#define RADEON_CREATE_PIXMAP_SHARED(usage) \ - (((usage) & ~RADEON_CREATE_PIXMAP_TILING_FLAGS) == RADEON_CREATE_PIXMAP_DRI2 || \ - (usage) == CREATE_PIXMAP_USAGE_SHARED) - static PixmapPtr radeon_glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, unsigned usage) { ScrnInfoPtr scrn = xf86ScreenToScrn(screen); + RADEONInfoPtr info = RADEONPTR(scrn); struct radeon_pixmap *priv; PixmapPtr pixmap, new_pixmap = NULL; if (!RADEON_CREATE_PIXMAP_SHARED(usage)) { - pixmap = glamor_create_pixmap(screen, w, h, depth, usage); - if (pixmap) - return pixmap; + if (info->shadow_primary) { + if (usage != CREATE_PIXMAP_USAGE_BACKING_PIXMAP) + return fbCreatePixmap(screen, w, h, depth, usage); + } else { + pixmap = glamor_create_pixmap(screen, w, h, depth, usage); + if (pixmap) + return pixmap; + } } if (w > 32767 || h > 32767) @@ -220,6 +218,8 @@ radeon_glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, if (!radeon_glamor_create_textured_pixmap(pixmap, priv)) goto fallback_glamor; + + pixmap->devPrivate.ptr = NULL; } return pixmap; @@ -258,6 +258,13 @@ fallback_pixmap: static Bool radeon_glamor_destroy_pixmap(PixmapPtr pixmap) { if (pixmap->refcnt == 1) { + if (pixmap->devPrivate.ptr) { + struct radeon_bo *bo = radeon_get_pixmap_bo(pixmap); + + if (bo) + radeon_bo_unmap(bo); + } + glamor_egl_destroy_textured_pixmap(pixmap); radeon_set_pixmap_bo(pixmap, NULL); } @@ -316,6 +323,26 @@ Bool radeon_glamor_init(ScreenPtr screen) { ScrnInfoPtr scrn = xf86ScreenToScrn(screen); + RADEONInfoPtr info = RADEONPTR(scrn); +#ifdef RENDER +#ifdef HAVE_FBGLYPHS + UnrealizeGlyphProcPtr SavedUnrealizeGlyph = NULL; +#endif + PictureScreenPtr ps = NULL; + + if (info->shadow_primary) { + ps = GetPictureScreenIfSet(screen); + + if (ps) { +#ifdef HAVE_FBGLYPHS + SavedUnrealizeGlyph = ps->UnrealizeGlyph; +#endif + info->glamor.SavedGlyphs = ps->Glyphs; + info->glamor.SavedTriangles = ps->Triangles; + info->glamor.SavedTrapezoids = ps->Trapezoids; + } + } +#endif /* RENDER */ if (!glamor_init(screen, GLAMOR_USE_EGL_SCREEN | GLAMOR_USE_SCREEN | GLAMOR_USE_PICTURE_SCREEN | GLAMOR_INVERTED_Y_AXIS | @@ -338,6 +365,17 @@ radeon_glamor_init(ScreenPtr screen) #endif return FALSE; + if (info->shadow_primary) + radeon_glamor_screen_init(screen); + +#if defined(RENDER) && defined(HAVE_FBGLYPHS) + /* For ShadowPrimary, we need fbUnrealizeGlyph instead of + * glamor_unrealize_glyph + */ + if (ps) + ps->UnrealizeGlyph = SavedUnrealizeGlyph; +#endif + screen->CreatePixmap = radeon_glamor_create_pixmap; screen->DestroyPixmap = radeon_glamor_destroy_pixmap; #ifdef RADEON_PIXMAP_SHARING diff --git a/src/radeon_glamor.h b/src/radeon_glamor.h index ea385c76..1ba7049a 100644 --- a/src/radeon_glamor.h +++ b/src/radeon_glamor.h @@ -35,6 +35,16 @@ #include "radeon_surface.h" +#ifndef CREATE_PIXMAP_USAGE_SHARED +#define CREATE_PIXMAP_USAGE_SHARED RADEON_CREATE_PIXMAP_DRI2 +#endif + +#define RADEON_CREATE_PIXMAP_SHARED(usage) \ + (((usage) & ~RADEON_CREATE_PIXMAP_TILING_FLAGS) == RADEON_CREATE_PIXMAP_DRI2 || \ + (usage) == CREATE_PIXMAP_USAGE_SHARED) + +struct radeon_pixmap; + #ifndef GLAMOR_NO_DRI3 #define GLAMOR_NO_DRI3 0 #define glamor_fd_from_pixmap glamor_dri3_fd_from_pixmap diff --git a/src/radeon_kms.c b/src/radeon_kms.c index 3f723d55..64593ab1 100644 --- a/src/radeon_kms.c +++ b/src/radeon_kms.c @@ -70,6 +70,7 @@ const OptionInfoRec RADEONOptions_KMS[] = { { OPTION_SUBPIXEL_ORDER, "SubPixelOrder", OPTV_ANYSTR, {0}, FALSE }, #ifdef USE_GLAMOR { OPTION_ACCELMETHOD, "AccelMethod", OPTV_STRING, {0}, FALSE }, + { OPTION_SHADOW_PRIMARY, "ShadowPrimary", OPTV_BOOLEAN, {0}, FALSE }, #endif { OPTION_EXA_VSYNC, "EXAVSync", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_EXA_PIXMAPS, "EXAPixmaps", OPTV_BOOLEAN, {0}, FALSE }, @@ -308,6 +309,142 @@ radeon_dirty_update(ScreenPtr screen) } #endif +static Bool +radeon_scanout_extents_intersect(BoxPtr extents, int x, int y, int w, int h) +{ + extents->x1 = max(extents->x1 - x, 0); + extents->y1 = max(extents->y1 - y, 0); + extents->x2 = min(extents->x2 - x, w); + extents->y2 = min(extents->y2 - y, h); + + return (extents->x1 < extents->x2 && extents->y1 < extents->y2); +} + +static void +radeon_scanout_update_abort(ScrnInfoPtr scrn, void *event_data) +{ + xf86CrtcPtr xf86_crtc = event_data; + drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private; + + drmmode_crtc->scanout_update_pending = FALSE; +} + +static void +radeon_scanout_update_handler(ScrnInfoPtr scrn, uint32_t frame, uint64_t usec, + void *event_data) +{ + xf86CrtcPtr xf86_crtc = event_data; + drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private; + DamagePtr pDamage; + RegionPtr pRegion; + DrawablePtr pDraw; + ScreenPtr pScreen; + GCPtr gc; + BoxRec extents; + RADEONInfoPtr info; + Bool force; + + if (!drmmode_crtc->scanout.pixmap || + drmmode_crtc->dpms_mode != DPMSModeOn) + goto out; + + pDamage = drmmode_crtc->scanout_damage; + if (!pDamage) + goto out; + + pRegion = DamageRegion(pDamage); + if (!RegionNotEmpty(pRegion)) + goto out; + + pDraw = &drmmode_crtc->scanout.pixmap->drawable; + extents = *RegionExtents(pRegion); + if (!radeon_scanout_extents_intersect(&extents, xf86_crtc->x, xf86_crtc->y, + pDraw->width, pDraw->height)) + goto clear_damage; + + pScreen = pDraw->pScreen; + gc = GetScratchGC(pDraw->depth, pScreen); + info = RADEONPTR(scrn); + force = info->accel_state->force; + info->accel_state->force = TRUE; + + ValidateGC(pDraw, gc); + (*gc->ops->CopyArea)(&pScreen->GetScreenPixmap(pScreen)->drawable, + pDraw, gc, + xf86_crtc->x + extents.x1, xf86_crtc->y + extents.y1, + extents.x2 - extents.x1, extents.y2 - extents.y1, + extents.x1, extents.y1); + FreeScratchGC(gc); + + info->accel_state->force = force; + + radeon_cs_flush_indirect(scrn); + +clear_damage: + RegionEmpty(pRegion); + +out: + drmmode_crtc->scanout_update_pending = FALSE; +} + +static void +radeon_scanout_update(xf86CrtcPtr xf86_crtc) +{ + drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private; + struct radeon_drm_queue_entry *drm_queue_entry; + ScrnInfoPtr scrn; + drmVBlank vbl; + DamagePtr pDamage; + RegionPtr pRegion; + DrawablePtr pDraw; + BoxRec extents; + + if (drmmode_crtc->scanout_update_pending || + !drmmode_crtc->scanout.pixmap || + drmmode_crtc->dpms_mode != DPMSModeOn) + return; + + pDamage = drmmode_crtc->scanout_damage; + if (!pDamage) + return; + + pRegion = DamageRegion(pDamage); + if (!RegionNotEmpty(pRegion)) + return; + + pDraw = &drmmode_crtc->scanout.pixmap->drawable; + extents = *RegionExtents(pRegion); + if (!radeon_scanout_extents_intersect(&extents, xf86_crtc->x, xf86_crtc->y, + pDraw->width, pDraw->height)) + return; + + scrn = xf86_crtc->scrn; + drm_queue_entry = radeon_drm_queue_alloc(scrn, RADEON_DRM_QUEUE_CLIENT_DEFAULT, + RADEON_DRM_QUEUE_ID_DEFAULT, + xf86_crtc, + radeon_scanout_update_handler, + radeon_scanout_update_abort); + if (!drm_queue_entry) { + xf86DrvMsg(scrn->scrnIndex, X_WARNING, + "radeon_drm_queue_alloc failed for scanout update\n"); + return; + } + + vbl.request.type = DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT; + vbl.request.type |= radeon_populate_vbl_request_type(xf86_crtc); + vbl.request.sequence = 1; + vbl.request.signal = (unsigned long)drm_queue_entry; + if (drmWaitVBlank(RADEONPTR(scrn)->dri2.drm_fd, &vbl)) { + xf86DrvMsg(scrn->scrnIndex, X_WARNING, + "drmWaitVBlank failed for scanout update: %s\n", + strerror(errno)); + radeon_drm_abort_entry(drm_queue_entry); + return; + } + + drmmode_crtc->scanout_update_pending = TRUE; +} + static void RADEONBlockHandler_KMS(BLOCKHANDLER_ARGS_DECL) { SCREEN_PTR(arg); @@ -318,7 +455,16 @@ static void RADEONBlockHandler_KMS(BLOCKHANDLER_ARGS_DECL) (*pScreen->BlockHandler) (BLOCKHANDLER_ARGS); pScreen->BlockHandler = RADEONBlockHandler_KMS; + if (info->shadow_primary) { + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + int c; + + for (c = 0; c < xf86_config->num_crtc; c++) + radeon_scanout_update(xf86_config->crtc[c]); + } + radeon_cs_flush_indirect(pScrn); + #ifdef RADEON_PIXMAP_SHARING radeon_dirty_update(pScreen); #endif @@ -936,11 +1082,32 @@ Bool RADEONPreInit_KMS(ScrnInfoPtr pScrn, int flags) xf86DrvMsg(pScrn->scrnIndex, X_INFO, "KMS Color Tiling 2D: %sabled\n", info->allowColorTiling2D ? "en" : "dis"); +#if USE_GLAMOR + if (info->use_glamor) { + info->shadow_primary = xf86ReturnOptValBool(info->Options, + OPTION_SHADOW_PRIMARY, FALSE); + + if (info->shadow_primary) + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ShadowPrimary enabled\n"); + } +#endif + if (info->dri2.pKernelDRMVersion->version_minor >= 8) { info->allowPageFlip = xf86ReturnOptValBool(info->Options, OPTION_PAGE_FLIP, TRUE); - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "KMS Pageflipping: %sabled\n", info->allowPageFlip ? "en" : "dis"); +#if USE_GLAMOR + if (info->shadow_primary) { + xf86DrvMsg(pScrn->scrnIndex, + info->allowPageFlip ? X_WARNING : X_DEFAULT, + "KMS Pageflipping: disabled%s\n", + info->allowPageFlip ? " because of ShadowPrimary" : ""); + info->allowPageFlip = FALSE; + } else +#endif + { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "KMS Pageflipping: %sabled\n", info->allowPageFlip ? "en" : "dis"); + } } info->swapBuffersWait = xf86ReturnOptValBool(info->Options, @@ -1506,6 +1673,7 @@ void RADEONLeaveVT_KMS(VT_FUNC_ARGS_DECL) radeon_drop_drm_master(pScrn); xf86RotateFreeShadow(pScrn); + drmmode_scanout_free(pScrn); xf86_hide_cursors (pScrn); info->accel_state->XInited3D = FALSE; @@ -1556,7 +1724,7 @@ static Bool radeon_setup_kernel_mem(ScreenPtr pScreen) } } - if (info->allowColorTiling) { + if (info->allowColorTiling && !info->shadow_primary) { if (info->ChipFamily >= CHIP_FAMILY_R600) { if (info->allowColorTiling2D) { tiling_flags |= RADEON_TILING_MACRO; @@ -1659,7 +1827,10 @@ static Bool radeon_setup_kernel_mem(ScreenPtr pScreen) if (info->front_bo == NULL) { info->front_bo = radeon_bo_open(info->bufmgr, 0, screen_size, - base_align, RADEON_GEM_DOMAIN_VRAM, 0); + base_align, + info->shadow_primary ? + RADEON_GEM_DOMAIN_GTT : + RADEON_GEM_DOMAIN_VRAM, 0); if (info->r600_shadow_fb == TRUE) { if (radeon_bo_map(info->front_bo, 1)) { ErrorF("Failed to map cursor buffer memory\n"); |