From 2a676f9fc281a0ad02cb71bd1f48e24a22e69158 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michel=20D=C3=A4nzer?= Date: Fri, 15 Mar 2013 18:28:27 +0100 Subject: [PATCH] glamor: Initial PRIME pixmap sharing hooks. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Michel Dänzer --- src/radeon_bo_helper.c | 64 +++++++++++++++++++++++++++++ src/radeon_bo_helper.h | 7 ++++ src/radeon_exa.c | 63 ++++------------------------- src/radeon_glamor.c | 108 +++++++++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 183 insertions(+), 59 deletions(-) diff --git a/src/radeon_bo_helper.c b/src/radeon_bo_helper.c index 593c690..feeadea 100644 --- a/src/radeon_bo_helper.c +++ b/src/radeon_bo_helper.c @@ -25,6 +25,7 @@ #endif #include "radeon.h" +#include "radeon_bo_gem.h" static const unsigned MicroBlockTable[5][3][2] = { @@ -181,3 +182,66 @@ radeon_alloc_pixmap_bo(ScrnInfoPtr pScrn, int width, int height, int depth, *new_pitch = pitch; return bo; } + +#ifdef RADEON_PIXMAP_SHARING + +Bool RADEONSharePixmapBacking(struct radeon_bo *bo, void **handle_p) +{ + int handle; + + if (radeon_gem_prime_share_bo(bo, &handle) != 0) + return FALSE; + + *handle_p = (void *)(long)handle; + return TRUE; +} + +Bool RADEONSetSharedPixmapBacking(PixmapPtr ppix, void *fd_handle, + struct radeon_surface *surface) +{ + ScrnInfoPtr pScrn = xf86ScreenToScrn(ppix->drawable.pScreen); + RADEONInfoPtr info = RADEONPTR(pScrn); + struct radeon_bo *bo; + int ihandle = (int)(long)fd_handle; + uint32_t size = ppix->devKind * ppix->drawable.height; + + bo = radeon_gem_bo_open_prime(info->bufmgr, ihandle, size); + if (!bo) + return FALSE; + + memset(surface, 0, sizeof(struct radeon_surface)); + + if (info->ChipFamily >= CHIP_FAMILY_R600 && info->surf_man) { + + surface->npix_x = ppix->drawable.width; + surface->npix_y = ppix->drawable.height; + surface->npix_z = 1; + surface->blk_w = 1; + surface->blk_h = 1; + surface->blk_d = 1; + surface->array_size = 1; + surface->bpe = ppix->drawable.bitsPerPixel / 8; + surface->nsamples = 1; + surface->flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_2D, TYPE); + surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_LINEAR, MODE); + if (radeon_surface_best(info->surf_man, surface)) { + return FALSE; + } + if (radeon_surface_init(info->surf_man, surface)) { + return FALSE; + } + /* we have to post hack the surface to reflect the actual size + of the shared pixmap */ + surface->level[0].pitch_bytes = ppix->devKind; + surface->level[0].nblk_x = ppix->devKind / surface->bpe; + } + radeon_set_pixmap_bo(ppix, bo); + + close(ihandle); + /* we have a reference from the alloc and one from set pixmap bo, + drop one */ + radeon_bo_unref(bo); + return TRUE; +} + +#endif /* RADEON_PIXMAP_SHARING */ diff --git a/src/radeon_bo_helper.h b/src/radeon_bo_helper.h index 0f6fffb..c3d80a3 100644 --- a/src/radeon_bo_helper.h +++ b/src/radeon_bo_helper.h @@ -28,4 +28,11 @@ radeon_alloc_pixmap_bo(ScrnInfoPtr pScrn, int width, int height, int depth, int usage_hint, int bitsPerPixel, int *new_pitch, struct radeon_surface *new_surface, uint32_t *new_tiling); +extern Bool +RADEONSharePixmapBacking(struct radeon_bo *bo, void **handle_p); + +extern Bool +RADEONSetSharedPixmapBacking(PixmapPtr ppix, void *fd_handle, + struct radeon_surface *surface); + #endif /* RADEON_BO_HELPER_H */ diff --git a/src/radeon_exa.c b/src/radeon_exa.c index 22e2cef..5558feb 100644 --- a/src/radeon_exa.c +++ b/src/radeon_exa.c @@ -41,7 +41,6 @@ #include "radeon_probe.h" #include "radeon_version.h" #include "radeon_exa_shared.h" -#include "radeon_bo_gem.h" #include "xf86.h" @@ -315,72 +314,24 @@ void RADEONEXADestroyPixmap(ScreenPtr pScreen, void *driverPriv) #ifdef RADEON_PIXMAP_SHARING Bool RADEONEXASharePixmapBacking(PixmapPtr ppix, ScreenPtr slave, void **fd_handle) { - struct radeon_exa_pixmap_priv *driver_priv; - int ret; - int handle; + struct radeon_exa_pixmap_priv *driver_priv = exaGetPixmapDriverPrivate(ppix); - driver_priv = exaGetPixmapDriverPrivate(ppix); - - ret = radeon_gem_prime_share_bo(driver_priv->bo, &handle); - if (ret) + if (!RADEONSharePixmapBacking(driver_priv->bo, fd_handle)) return FALSE; driver_priv->shared = TRUE; - *fd_handle = (void *)(long)handle; return TRUE; } Bool RADEONEXASetSharedPixmapBacking(PixmapPtr ppix, void *fd_handle) { - ScrnInfoPtr pScrn = xf86ScreenToScrn(ppix->drawable.pScreen); - RADEONInfoPtr info = RADEONPTR(pScrn); - struct radeon_exa_pixmap_priv *driver_priv; - struct radeon_bo *bo; - int ihandle = (int)(long)fd_handle; - uint32_t size = ppix->devKind * ppix->drawable.height; - struct radeon_surface surface; - - driver_priv = exaGetPixmapDriverPrivate(ppix); - - bo = radeon_gem_bo_open_prime(info->bufmgr, ihandle, size); - if (!bo) - return FALSE; - - memset(&surface, 0, sizeof(struct radeon_surface)); - - if (info->ChipFamily >= CHIP_FAMILY_R600 && info->surf_man) { - - surface.npix_x = ppix->drawable.width; - surface.npix_y = ppix->drawable.height; - surface.npix_z = 1; - surface.blk_w = 1; - surface.blk_h = 1; - surface.blk_d = 1; - surface.array_size = 1; - surface.bpe = ppix->drawable.bitsPerPixel / 8; - surface.nsamples = 1; - surface.flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_2D, TYPE); - surface.flags |= RADEON_SURF_SET(RADEON_SURF_MODE_LINEAR, MODE); - if (radeon_surface_best(info->surf_man, &surface)) { - return FALSE; - } - if (radeon_surface_init(info->surf_man, &surface)) { - return FALSE; - } - /* we have to post hack the surface to reflect the actual size - of the shared pixmap */ - surface.level[0].pitch_bytes = ppix->devKind; - surface.level[0].nblk_x = ppix->devKind / surface.bpe; - } - driver_priv->surface = surface; + struct radeon_exa_pixmap_priv *driver_priv = exaGetPixmapDriverPrivate(ppix); + + if (!RADEONSetSharedPixmapBacking(ppix, fd_handle, &driver_priv->surface)) + return FALSE; + driver_priv->shared = TRUE; driver_priv->tiling_flags = 0; - radeon_set_pixmap_bo(ppix, bo); - - close(ihandle); - /* we have a reference from the alloc and one from set pixmap bo, - drop one */ - radeon_bo_unref(bo); return TRUE; } #endif diff --git a/src/radeon_glamor.c b/src/radeon_glamor.c index 5ee193c..98a8f19 100644 --- a/src/radeon_glamor.c +++ b/src/radeon_glamor.c @@ -161,7 +161,7 @@ radeon_glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, struct radeon_pixmap *priv; PixmapPtr pixmap, new_pixmap = NULL; - if (!(usage & RADEON_CREATE_PIXMAP_DRI2)) { + if (!(usage & (CREATE_PIXMAP_USAGE_SHARED | RADEON_CREATE_PIXMAP_DRI2))) { pixmap = glamor_create_pixmap(screen, w, h, depth, usage); if (pixmap) return pixmap; @@ -204,13 +204,13 @@ radeon_glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, return pixmap; fallback_glamor: - if (usage & RADEON_CREATE_PIXMAP_DRI2) { + if (usage & (CREATE_PIXMAP_USAGE_SHARED | RADEON_CREATE_PIXMAP_DRI2)) { /* XXX need further work to handle the DRI2 failure case. * Glamor don't know how to handle a BO only pixmap. Put * a warning indicator here. */ xf86DrvMsg(scrn->scrnIndex, X_WARNING, - "Failed to create textured DRI2 pixmap."); + "Failed to create textured DRI2/PRIME pixmap."); return pixmap; } /* Create textured pixmap failed means glamor failed to @@ -244,6 +244,104 @@ static Bool radeon_glamor_destroy_pixmap(PixmapPtr pixmap) return TRUE; } +#ifdef RADEON_PIXMAP_SHARING + +static Bool +radeon_glamor_share_pixmap_backing(PixmapPtr pixmap, ScreenPtr slave, + void **handle_p) +{ + struct radeon_pixmap *priv = radeon_get_pixmap_private(pixmap); + + if (!priv || !priv->bo) { + ScreenPtr screen = pixmap->drawable.pScreen; + ScrnInfoPtr scrn = xf86ScreenToScrn(screen); + PixmapPtr bo_pixmap; + GCPtr gc; + + bo_pixmap = screen->CreatePixmap(screen, + pixmap->drawable.width, + pixmap->drawable.height, + pixmap->drawable.depth, + pixmap->usage_hint | + CREATE_PIXMAP_USAGE_SHARED); + if (!bo_pixmap) + return FALSE; + + priv = radeon_get_pixmap_private(bo_pixmap); + + /* Copy the current contents of the pixmap to the bo. */ + gc = GetScratchGC(pixmap->drawable.depth, screen); + if (!gc || !priv->bo) { + screen->DestroyPixmap(bo_pixmap); + return FALSE; + } + + ValidateGC(&bo_pixmap->drawable, gc); + gc->ops->CopyArea(&pixmap->drawable, &bo_pixmap->drawable, + gc, + 0, 0, + pixmap->drawable.width, + pixmap->drawable.height, + 0, 0); + FreeScratchGC(gc); + + radeon_set_pixmap_private(bo_pixmap, NULL); + screen->DestroyPixmap(bo_pixmap); + + /* And redirect the pixmap to the new bo (for 3D). */ + radeon_set_pixmap_private(pixmap, priv); + + if (!radeon_glamor_create_textured_pixmap(pixmap)) { + xf86DrvMsg(scrn->scrnIndex, X_ERROR, + "Failed to get PRIME drawable for glamor pixmap.\n"); + return FALSE; + } + + screen->ModifyPixmapHeader(pixmap, + pixmap->drawable.width, + pixmap->drawable.height, + 0, 0, + priv->stride, + NULL); + } + + return RADEONSharePixmapBacking(priv->bo, handle_p); +} + +static Bool +radeon_glamor_set_shared_pixmap_backing(PixmapPtr pixmap, void *handle) +{ + ScreenPtr screen = pixmap->drawable.pScreen; + ScrnInfoPtr scrn = xf86ScreenToScrn(screen); + struct radeon_surface surface; + struct radeon_pixmap *priv; + + if (!RADEONSetSharedPixmapBacking(pixmap, handle, &surface)) + return FALSE; + + priv = radeon_get_pixmap_private(pixmap); + priv->stride = pixmap->devKind; + priv->surface = surface; + priv->tiling_flags = 0; + + if (!radeon_glamor_create_textured_pixmap(pixmap)) { + xf86DrvMsg(scrn->scrnIndex, X_ERROR, + "Failed to get PRIME drawable for glamor pixmap.\n"); + return FALSE; + } + + screen->ModifyPixmapHeader(pixmap, + pixmap->drawable.width, + pixmap->drawable.height, + 0, 0, + priv->stride, + NULL); + + return TRUE; +} + +#endif /* RADEON_PIXMAP_SHARING */ + Bool radeon_glamor_init(ScreenPtr screen) { @@ -271,6 +369,10 @@ radeon_glamor_init(ScreenPtr screen) screen->CreatePixmap = radeon_glamor_create_pixmap; screen->DestroyPixmap = radeon_glamor_destroy_pixmap; +#ifdef RADEON_PIXMAP_SHARING + screen->SharePixmapBacking = radeon_glamor_share_pixmap_backing; + screen->SetSharedPixmapBacking = radeon_glamor_set_shared_pixmap_backing; +#endif xf86DrvMsg(scrn->scrnIndex, X_INFO, "Use GLAMOR acceleration.\n"); -- 1.8.2.rc3