diff -urN a/src/radeon_bo_helper.c b/src/radeon_bo_helper.c --- a/src/radeon_bo_helper.c 2013-03-15 20:36:50.047013000 +0100 +++ b/src/radeon_bo_helper.c 2013-03-15 23:44:18.836032000 +0100 @@ -25,6 +25,7 @@ #endif #include "radeon.h" +#include "radeon_bo_gem.h" static const unsigned MicroBlockTable[5][3][2] = { @@ -181,3 +182,67 @@ *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)) + return FALSE; + + *handle_p = (void*)(long)handle; + return TRUE; +} + +Bool RADEONSetSharedPixmapBacking(PixmapPtr ppix, void *fd_handle, + struct radeon_surface *surface) +{ + ScrnInfoPtr scrn = xf86ScreenToScrn(ppix->drawable.pScreen); + RADEONInfoPtr info = RADEONPTR(scrn); + 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 ppix */ + 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 ppix bo, + drop one */ + radeon_bo_unref(bo); + return TRUE; +} + +#endif diff -urN a/src/radeon_bo_helper.h b/src/radeon_bo_helper.h --- a/src/radeon_bo_helper.h 2013-03-15 20:36:50.047013000 +0100 +++ b/src/radeon_bo_helper.h 2013-03-16 00:16:15.217337136 +0100 @@ -28,4 +28,12 @@ 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 -urN a/src/radeon_exa.c b/src/radeon_exa.c --- a/src/radeon_exa.c 2013-03-15 20:36:50.043013000 +0100 +++ b/src/radeon_exa.c 2013-03-15 23:36:43.245769000 +0100 @@ -315,72 +315,24 @@ #ifdef RADEON_PIXMAP_SHARING Bool RADEONEXASharePixmapBacking(PixmapPtr ppix, ScreenPtr slave, void **fd_handle) { - struct radeon_exa_pixmap_priv *driver_priv; - int ret; - int handle; - - driver_priv = exaGetPixmapDriverPrivate(ppix); - - ret = radeon_gem_prime_share_bo(driver_priv->bo, &handle); - if (ret) - return FALSE; - + struct radeon_exa_pixmap_priv *driver_priv = exaGetPixmapDriverPrivate(ppix); + + 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; + struct radeon_exa_pixmap_priv *driver_priv = exaGetPixmapDriverPrivate(ppix); - 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) { + if (!RADEONSetSharedPixmapBacking(ppix, fd_handle, &driver_priv->surface)) + return FALSE; - 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; 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 -urN a/src/radeon_glamor.c b/src/radeon_glamor.c --- a/src/radeon_glamor.c 2013-03-15 20:36:50.047013000 +0100 +++ b/src/radeon_glamor.c 2013-03-15 23:47:37.192152000 +0100 @@ -34,6 +34,7 @@ #include "radeon.h" #include "radeon_bo_helper.h" +#include "radeon_bo_gem.h" #if HAS_DEVPRIVATEKEYREC DevPrivateKeyRec glamor_pixmap_index; @@ -160,12 +161,24 @@ { ScrnInfoPtr scrn = xf86ScreenToScrn(screen); struct radeon_pixmap *priv; - PixmapPtr pixmap, new_pixmap = NULL; + PixmapPtr pixmap = NULL, new_pixmap = NULL; if (!(usage & RADEON_CREATE_PIXMAP_DRI2)) { pixmap = glamor_create_pixmap(screen, w, h, depth, usage); - if (pixmap) - return pixmap; + if (pixmap){ + if(usage & CREATE_PIXMAP_USAGE_SHARED) { + // alloc priv, else NULL in radeon_glamor_set_pixmap_backing + priv = calloc(1, sizeof(struct radeon_pixmap)); + if(!priv) { + glamor_destroy_pixmap(pixmap); + pixmap = NULL; + } + else { + radeon_set_pixmap_private(pixmap, priv); + return pixmap; + } + } + } } if (w > 32767 || h > 32767) @@ -245,6 +258,74 @@ return TRUE; } +#ifdef RADEON_PIXMAP_SHARING +Bool radeon_glamor_share_pixmap_backing(PixmapPtr pixmap, ScreenPtr slave, void **fd_handle) +{ + struct radeon_pixmap *priv = radeon_get_pixmap_private(pixmap); + if (!priv) + return FALSE; + + if (!priv->bo) { + ScreenPtr screen = pixmap->drawable.pScreen; + 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 | + RADEON_CREATE_PIXMAP_DRI2); + + if (!bo_pixmap) + return FALSE; + + priv = radeon_get_pixmap_private(bo_pixmap); + if (!priv) { + screen->DestroyPixmap(bo_pixmap); + return FALSE; + } + + + /* 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); + } + + return RADEONSharePixmapBacking(priv->bo, fd_handle); +} + +Bool radeon_glamor_set_shared_pixmap_backing(PixmapPtr pixmap, void* fd_handle) +{ + struct radeon_pixmap *priv = radeon_get_pixmap_private(pixmap); + + if (!RADEONSetSharedPixmapBacking(pixmap, fd_handle, &priv->surface)) + return FALSE; + + priv->tiling_flags = 0; + return TRUE; +} + +#endif Bool radeon_glamor_init(ScreenPtr screen) { @@ -273,6 +354,11 @@ 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"); return TRUE; diff -urN a/src/radeon_glamor.h b/src/radeon_glamor.h --- a/src/radeon_glamor.h 2013-03-15 20:36:50.042013000 +0100 +++ b/src/radeon_glamor.h 2013-03-15 20:17:58.299542000 +0100 @@ -41,6 +41,9 @@ Bool radeon_glamor_create_textured_pixmap(PixmapPtr pixmap); void radeon_glamor_exchange_buffers(PixmapPtr src, PixmapPtr dst); +Bool radeon_glamor_share_pixmap_backing(PixmapPtr pixmap, ScreenPtr slave, void **fd_handle); +Bool radeon_glamor_set_shared_pixmap_backing(PixmapPtr pixmap, void* fd_handle); + Bool radeon_glamor_pixmap_is_offscreen(PixmapPtr pixmap); struct radeon_pixmap { @@ -84,6 +87,9 @@ static inline void radeon_glamor_exchange_buffers(PixmapPtr src, PixmapPtr dst) {} +static inline Bool radeon_glamor_share_pixmap_backing(PixmapPtr pixmap, ScreenPtr slave, void **fd_handle) {return FALSE; } +static inline Bool radeon_glamor_set_shared_pixmap_backing(PixmapPtr pixmap, void* fd_handle) { return FALSE; } + static inline Bool radeon_glamor_pixmap_is_offscreen(PixmapPtr pixmap) { return FALSE; } static inline struct radeon_pixmap *radeon_get_pixmap_private(PixmapPtr pixmap) { return NULL; }