diff options
author | Dave Airlie <airlied@redhat.com> | 2010-03-12 16:07:09 +1000 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2010-03-16 16:09:40 +1000 |
commit | 02dd67057e583c786927865cde365508b7a43eda (patch) | |
tree | faec61b7bb43ee30f57df96a6e3a268ebc39cf8b | |
parent | 221ef11b31756deb7134801730e76c040e841f5c (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.h | 4 | ||||
-rw-r--r-- | src/radeon_dri2.c | 181 | ||||
-rw-r--r-- | src/radeon_exa.c | 9 | ||||
-rw-r--r-- | src/radeon_exa_funcs.c | 9 |
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) |