summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configure.ac10
-rw-r--r--man/radeon.man16
-rw-r--r--src/drmmode_display.c89
-rw-r--r--src/drmmode_display.h6
-rw-r--r--src/radeon.h2
-rw-r--r--src/radeon_bo_helper.c7
-rw-r--r--src/radeon_dri3.c15
-rw-r--r--src/radeon_glamor.c60
-rw-r--r--src/radeon_glamor.h10
-rw-r--r--src/radeon_kms.c179
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");