summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2010-03-12 16:07:09 +1000
committerDave Airlie <airlied@redhat.com>2010-03-16 16:09:40 +1000
commit02dd67057e583c786927865cde365508b7a43eda (patch)
treefaec61b7bb43ee30f57df96a6e3a268ebc39cf8b
parent221ef11b31756deb7134801730e76c040e841f5c (diff)
prime slave support for ATI driver (v3)prime-test
get the Window vs Pixmap stuff right When we have a primed window, we change the pixmap while doing the copy to point at the prime slave pixmap, and change it back to the prime master pixmap once copied. v3: change map/unmap to bo wait
-rw-r--r--src/radeon.h4
-rw-r--r--src/radeon_dri2.c181
-rw-r--r--src/radeon_exa.c9
-rw-r--r--src/radeon_exa_funcs.c9
4 files changed, 168 insertions, 35 deletions
diff --git a/src/radeon.h b/src/radeon.h
index 59c2282c..aa67d489 100644
--- a/src/radeon.h
+++ b/src/radeon.h
@@ -483,6 +483,7 @@ struct radeon_exa_pixmap_priv {
struct radeon_bo *bo;
int flags;
Bool bo_mapped;
+ Bool prime;
};
typedef struct {
@@ -510,6 +511,7 @@ struct radeon_2d_state {
uint32_t dp_src_frgd_clr;
uint32_t dp_src_bkgd_clr;
uint32_t default_sc_bottom_right;
+ uint32_t dst_domain;
struct radeon_bo *dst_bo;
struct radeon_bo *src_bo;
};
@@ -1345,7 +1347,7 @@ void radeon_kms_update_vram_limit(ScrnInfoPtr pScrn, int new_fb_size);
#endif
struct radeon_bo *radeon_get_pixmap_bo(PixmapPtr pPix);
void radeon_set_pixmap_bo(PixmapPtr pPix, struct radeon_bo *bo);
-
+void radeon_set_pixmap_prime(PixmapPtr pPix);
#ifdef XF86DRI
# ifdef USE_XAA
/* radeon_accelfuncs.c */
diff --git a/src/radeon_dri2.c b/src/radeon_dri2.c
index 103972f5..d54c94f7 100644
--- a/src/radeon_dri2.c
+++ b/src/radeon_dri2.c
@@ -46,6 +46,16 @@
#define USE_DRI2_1_1_0
#endif
+static inline PixmapPtr get_drawable_pixmap(DrawablePtr drawable)
+{
+ ScreenPtr screen = drawable->pScreen;
+
+ if (drawable->type == DRAWABLE_PIXMAP)
+ return (PixmapPtr) drawable;
+ else
+ return screen->GetWindowPixmap((WindowPtr) drawable);
+}
+
#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,6,99,0, 0)
typedef DRI2BufferPtr BufferPtr;
#else
@@ -55,6 +65,7 @@ typedef DRI2Buffer2Ptr BufferPtr;
struct dri2_buffer_priv {
PixmapPtr pixmap;
unsigned int attachment;
+ PixmapPtr prime_pixmap;
};
@@ -87,11 +98,7 @@ radeon_dri2_create_buffers(DrawablePtr drawable,
depth_pixmap = NULL;
for (i = 0; i < count; i++) {
if (attachments[i] == DRI2BufferFrontLeft) {
- if (drawable->type == DRAWABLE_PIXMAP) {
- pixmap = (Pixmap*)drawable;
- } else {
- pixmap = (*pScreen->GetWindowPixmap)((WindowPtr)drawable);
- }
+ pixmap = get_drawable_pixmap(drawable);
pixmap->refcnt++;
} else if (attachments[i] == DRI2BufferStencil && depth_pixmap) {
pixmap = depth_pixmap;
@@ -169,12 +176,8 @@ radeon_dri2_create_buffer(DrawablePtr drawable,
depth_pixmap = NULL;
if (attachment == DRI2BufferFrontLeft) {
- if (drawable->type == DRAWABLE_PIXMAP) {
- pixmap = (PixmapPtr)drawable;
- } else {
- pixmap = (*pScreen->GetWindowPixmap)((WindowPtr)drawable);
- }
- pixmap->refcnt++;
+ pixmap = NULL;
+ /* we'll pick up a real pixmap later in copy region */
} else if (attachment == DRI2BufferStencil && depth_pixmap) {
pixmap = depth_pixmap;
pixmap->refcnt++;
@@ -204,23 +207,25 @@ radeon_dri2_create_buffer(DrawablePtr drawable,
if (attachment == DRI2BufferDepth) {
depth_pixmap = pixmap;
}
- info->exa_force_create = TRUE;
- exaMoveInPixmap(pixmap);
- info->exa_force_create = FALSE;
- driver_priv = exaGetPixmapDriverPrivate(pixmap);
- r = radeon_gem_get_kernel_name(driver_priv->bo, &buffers->name);
- if (r)
- return NULL;
+
+ if (pixmap) {
+ info->exa_force_create = TRUE;
+ exaMoveInPixmap(pixmap);
+ info->exa_force_create = FALSE;
+ driver_priv = exaGetPixmapDriverPrivate(pixmap);
+ r = radeon_gem_get_kernel_name(driver_priv->bo, &buffers->name);
+ if (r)
+ return NULL;
+ buffers->pitch = pixmap->devKind;
+ buffers->cpp = pixmap->drawable.bitsPerPixel / 8;
+ }
buffers->attachment = attachment;
- buffers->pitch = pixmap->devKind;
- buffers->cpp = pixmap->drawable.bitsPerPixel / 8;
buffers->driverPrivate = privates;
buffers->format = format;
buffers->flags = 0; /* not tiled */
privates->pixmap = pixmap;
privates->attachment = attachment;
-
return buffers;
}
#endif
@@ -237,7 +242,8 @@ radeon_dri2_destroy_buffers(DrawablePtr drawable,
for (i = 0; i < count; i++) {
private = buffers[i].driverPrivate;
- (*pScreen->DestroyPixmap)(private->pixmap);
+ if (private->pixmap)
+ (*pScreen->DestroyPixmap)(private->pixmap);
}
if (buffers) {
xfree(buffers[0].driverPrivate);
@@ -272,26 +278,47 @@ radeon_dri2_copy_region(DrawablePtr drawable,
struct dri2_buffer_priv *dst_private = dest_buffer->driverPrivate;
ScreenPtr pScreen = drawable->pScreen;
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
- PixmapPtr src_pixmap;
- PixmapPtr dst_pixmap;
RegionPtr copy_clip;
GCPtr gc;
RADEONInfoPtr info = RADEONPTR(pScrn);
Bool vsync;
+ PixmapPtr orig_win_pixmap = NULL;
+ DrawablePtr src, dst;
+
+ src = &src_private->pixmap->drawable;
+ dst = &dst_private->pixmap->drawable;
- src_pixmap = src_private->pixmap;
- dst_pixmap = dst_private->pixmap;
if (src_private->attachment == DRI2BufferFrontLeft) {
- src_pixmap = (PixmapPtr)drawable;
+ src = drawable;
}
if (dst_private->attachment == DRI2BufferFrontLeft) {
- dst_pixmap = (PixmapPtr)drawable;
+
+ /* if rendering to front use the current drawable,
+ retrieves the pixmap for the current drawable,
+ and if its on the other screen, check if we've
+ created a prime linked pixmap already. If not
+ call dri2 module to create a prime-link between
+ the pixmap on the master and the one on the slave,
+ then if the drawable is a Window, set the window
+ pixmap to the slave pixmap. Once copying is finished
+ we set the window pixmap back to its original state
+ */
+ dst = drawable;
+ orig_win_pixmap = get_drawable_pixmap(dst);
+ if (orig_win_pixmap->drawable.pScreen != pScreen) {
+ if (dst_private->prime_pixmap != orig_win_pixmap)
+ DRI2UpdatePrime(drawable, dest_buffer);
+
+ if (WindowDrawable(drawable->type))
+ pScreen->SetWindowPixmap((WindowPtr)drawable,
+ dst_private->pixmap);
+ }
}
gc = GetScratchGC(drawable->depth, pScreen);
copy_clip = REGION_CREATE(pScreen, NULL, 0);
REGION_COPY(pScreen, copy_clip, region);
(*gc->funcs->ChangeClip) (gc, CT_REGION, copy_clip, 0);
- ValidateGC(&dst_pixmap->drawable, gc);
+ ValidateGC(dst, gc);
/* If this is a full buffer swap or frontbuffer flush, throttle on the
* previous one
@@ -304,7 +331,7 @@ radeon_dri2_copy_region(DrawablePtr drawable,
extents->x2 == drawable->width &&
extents->y2 == drawable->height) {
struct radeon_exa_pixmap_priv *exa_priv =
- exaGetPixmapDriverPrivate(dst_pixmap);
+ exaGetPixmapDriverPrivate(get_drawable_pixmap(dst));
if (exa_priv && exa_priv->bo)
radeon_bo_wait(exa_priv->bo);
@@ -315,13 +342,79 @@ radeon_dri2_copy_region(DrawablePtr drawable,
vsync = info->accel_state->vsync;
info->accel_state->vsync = TRUE;
- (*gc->ops->CopyArea)(&src_pixmap->drawable, &dst_pixmap->drawable, gc,
+ (*gc->ops->CopyArea)(src, dst, gc,
0, 0, drawable->width, drawable->height, 0, 0);
info->accel_state->vsync = vsync;
FreeScratchGC(gc);
radeon_cs_flush_indirect(pScrn);
+
+ if (orig_win_pixmap) {
+ /* if we have an original window pixmap i.e. we are in prime
+ mode, then we need to wait for the second GPU to sync
+ the pixmap before we return and report damage */
+ int ret;
+ struct radeon_exa_pixmap_priv *exa_priv;
+ exa_priv = exaGetPixmapDriverPrivate(get_drawable_pixmap(dst));
+ if (exa_priv && exa_priv->bo) {
+ radeon_bo_wait(exa_priv->bo);
+ }
+ /* put back the original pixmap now */
+ pScreen->SetWindowPixmap((WindowPtr)drawable, orig_win_pixmap);
+ }
+
+}
+
+static Bool
+radeon_dri2_create_prime_slave(ScreenPtr pScreen, DrawablePtr drawable,
+ DRI2BufferPtr buffer, uint32_t handle)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ struct dri2_buffer_priv *privates;
+ PixmapPtr pixmap;
+ struct radeon_bo *bo;
+ int padded_width;
+ int size;
+ PixmapPtr master_pixmap = get_drawable_pixmap(drawable);
+
+ /* go get the BO handle */
+ padded_width = ((master_pixmap->drawable.width * master_pixmap->drawable.bitsPerPixel + FB_MASK) >> FB_SHIFT) * sizeof(FbBits);
+ padded_width = (padded_width + 63) & ~63;
+ size = padded_width * master_pixmap->drawable.height;
+
+ bo = radeon_bo_open(info->bufmgr, handle, size, 0, 0, RADEON_BO_FLAGS_SLAVE);
+ if (!bo) {
+ ErrorF("failed to make BO\n");
+ return FALSE;
+ }
+
+ pixmap = (*pScreen->CreatePixmap)(pScreen, 0, 0, (buffer->format != 0) ? buffer->format : master_pixmap->drawable.depth, 0);
+ if (!pixmap)
+ return FALSE;
+
+ if (!(*pScreen->ModifyPixmapHeader)(pixmap, master_pixmap->drawable.width,
+ master_pixmap->drawable.height,
+ (buffer->format != 0) ? buffer->format : master_pixmap->drawable.depth,
+ master_pixmap->drawable.bitsPerPixel, padded_width, NULL)) {
+ ErrorF("MPH failed\n");
+ return FALSE;
+ }
+
+ exaMoveInPixmap(pixmap);
+ radeon_set_pixmap_bo(pixmap, bo);
+ radeon_set_pixmap_prime(pixmap);
+
+ privates = buffer->driverPrivate;
+
+ buffer->pitch = pixmap->devKind;
+ buffer->cpp = pixmap->drawable.bitsPerPixel / 8;
+ buffer->flags = 0; /* not tiled */
+ privates->pixmap = pixmap;
+ privates->attachment = DRI2BufferFrontLeft;
+ privates->prime_pixmap = master_pixmap;
+ return TRUE;
}
Bool
@@ -330,6 +423,9 @@ radeon_dri2_screen_init(ScreenPtr pScreen)
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
RADEONInfoPtr info = RADEONPTR(pScrn);
DRI2InfoRec dri2_info = { 0 };
+#if DRI2INFOREC_VERSION >= 4
+ const char *driverNames[1];
+#endif
if (!info->useEXA) {
xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "DRI2 requires EXA\n");
@@ -349,6 +445,11 @@ radeon_dri2_screen_init(ScreenPtr pScreen)
}
dri2_info.fd = info->dri2.drm_fd;
dri2_info.deviceName = info->dri2.device_name;
+#if DRI2INFOREC_VERSION >= 3
+ dri2_info.version = 3;
+ dri2_info.CreateBuffer = radeon_dri2_create_buffer;
+ dri2_info.DestroyBuffer = radeon_dri2_destroy_buffer;
+#else
#ifndef USE_DRI2_1_1_0
dri2_info.version = 1;
dri2_info.CreateBuffers = radeon_dri2_create_buffers;
@@ -358,8 +459,26 @@ radeon_dri2_screen_init(ScreenPtr pScreen)
dri2_info.CreateBuffer = radeon_dri2_create_buffer;
dri2_info.DestroyBuffer = radeon_dri2_destroy_buffer;
#endif
+#endif
dri2_info.CopyRegion = radeon_dri2_copy_region;
+
+
+#if DRI2INFOREC_VERSION >= 4
+ dri2_info.version = 4;
+ dri2_info.numDrivers = 1;
+ dri2_info.driverNames = driverNames;
+ driverNames[0] = dri2_info.driverName;
+#endif
+
+#if DRI2INFOREC_VERSION >= 5
+ dri2_info.version = 5;
+ dri2_info.CreatePrimeSlave = radeon_dri2_create_prime_slave;
+#endif
info->dri2.enabled = DRI2ScreenInit(pScreen, &dri2_info);
+
+ if (info->dri2.enabled) {
+ DRI2RegisterPrime(pScreen, DRI2_PRIME_SLAVE, &dri2_info);
+ }
return info->dri2.enabled;
}
diff --git a/src/radeon_exa.c b/src/radeon_exa.c
index f8b0cc92..e4a82b96 100644
--- a/src/radeon_exa.c
+++ b/src/radeon_exa.c
@@ -472,6 +472,15 @@ struct radeon_bo *radeon_get_pixmap_bo(PixmapPtr pPix)
return driver_priv->bo;
}
+void radeon_set_pixmap_prime(PixmapPtr pPix)
+{
+ struct radeon_exa_pixmap_priv *driver_priv;
+
+ driver_priv = exaGetPixmapDriverPrivate(pPix);
+ if (driver_priv)
+ driver_priv->prime = TRUE;
+}
+
void radeon_set_pixmap_bo(PixmapPtr pPix, struct radeon_bo *bo)
{
struct radeon_exa_pixmap_priv *driver_priv;
diff --git a/src/radeon_exa_funcs.c b/src/radeon_exa_funcs.c
index a3098d8f..8abe7e27 100644
--- a/src/radeon_exa_funcs.c
+++ b/src/radeon_exa_funcs.c
@@ -115,7 +115,7 @@ static void FUNC_NAME(Emit2DState)(ScrnInfoPtr pScrn, int op)
OUT_ACCEL_REG(RADEON_DST_PITCH_OFFSET, info->state_2d.dst_pitch_offset);
if (info->cs)
- OUT_RELOC(info->state_2d.dst_bo, 0, RADEON_GEM_DOMAIN_VRAM);
+ OUT_RELOC(info->state_2d.dst_bo, 0, info->state_2d.dst_domain);
if (has_src) {
OUT_ACCEL_REG(RADEON_SRC_PITCH_OFFSET, info->state_2d.src_pitch_offset);
@@ -179,8 +179,10 @@ FUNC_NAME(RADEONPrepareSolid)(PixmapPtr pPix, int alu, Pixel pm, Pixel fg)
RADEON_FALLBACK(("Not enough RAM to hw accel solid operation\n"));
driver_priv = exaGetPixmapDriverPrivate(pPix);
- if (driver_priv)
+ if (driver_priv) {
info->state_2d.dst_bo = driver_priv->bo;
+ info->state_2d.dst_domain = driver_priv->prime ? RADEON_GEM_DOMAIN_GTT : RADEON_GEM_DOMAIN_VRAM;
+ }
}
#endif
@@ -300,8 +302,9 @@ FUNC_NAME(RADEONPrepareCopy)(PixmapPtr pSrc, PixmapPtr pDst,
info->state_2d.src_bo = driver_priv->bo;
driver_priv = exaGetPixmapDriverPrivate(pDst);
- radeon_cs_space_add_persistent_bo(info->cs, driver_priv->bo, 0, RADEON_GEM_DOMAIN_VRAM);
+ radeon_cs_space_add_persistent_bo(info->cs, driver_priv->bo, 0, driver_priv->prime ? RADEON_GEM_DOMAIN_GTT : RADEON_GEM_DOMAIN_VRAM);
info->state_2d.dst_bo = driver_priv->bo;
+ info->state_2d.dst_domain = driver_priv->prime ? RADEON_GEM_DOMAIN_GTT : RADEON_GEM_DOMAIN_VRAM;
ret = radeon_cs_space_check(info->cs);
if (ret)