radeon_bo_helper.c revision 39413783
1de2362d3Smrg/* 2de2362d3Smrg * Copyright 2012 Advanced Micro Devices, Inc. 3de2362d3Smrg * 4de2362d3Smrg * Permission is hereby granted, free of charge, to any person obtaining a 5de2362d3Smrg * copy of this software and associated documentation files (the "Software"), 6de2362d3Smrg * to deal in the Software without restriction, including without limitation 7de2362d3Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8de2362d3Smrg * and/or sell copies of the Software, and to permit persons to whom the 9de2362d3Smrg * Software is furnished to do so, subject to the following conditions: 10de2362d3Smrg * 11de2362d3Smrg * The above copyright notice and this permission notice shall be included in 12de2362d3Smrg * all copies or substantial portions of the Software. 13de2362d3Smrg * 14de2362d3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15de2362d3Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16de2362d3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17de2362d3Smrg * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18de2362d3Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19de2362d3Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20de2362d3Smrg * OTHER DEALINGS IN THE SOFTWARE. 21de2362d3Smrg */ 22de2362d3Smrg 23de2362d3Smrg#ifdef HAVE_CONFIG_H 24de2362d3Smrg# include "config.h" 25de2362d3Smrg#endif 26de2362d3Smrg 27de2362d3Smrg#include "radeon.h" 280d16fef4Smrg#include "radeon_glamor.h" 29de2362d3Smrg#include "radeon_bo_gem.h" 30de2362d3Smrg 3139413783Smrg 3239413783Smrg#ifdef USE_GLAMOR 3339413783Smrg 3439413783Smrgstatic uint32_t 3539413783Smrgradeon_get_gbm_format(int depth, int bitsPerPixel) 3639413783Smrg{ 3739413783Smrg switch (depth) { 3839413783Smrg#ifdef GBM_FORMAT_R8 3939413783Smrg case 8: 4039413783Smrg return GBM_FORMAT_R8; 4139413783Smrg#endif 4239413783Smrg case 16: 4339413783Smrg return GBM_FORMAT_RGB565; 4439413783Smrg case 32: 4539413783Smrg return GBM_FORMAT_ARGB8888; 4639413783Smrg case 30: 4739413783Smrg return GBM_FORMAT_XRGB2101010; 4839413783Smrg case 24: 4939413783Smrg if (bitsPerPixel == 32) 5039413783Smrg return GBM_FORMAT_XRGB8888; 5139413783Smrg /* fall through */ 5239413783Smrg default: 5339413783Smrg ErrorF("%s: Unsupported depth/bpp %d/%d\n", __func__, depth, 5439413783Smrg bitsPerPixel); 5539413783Smrg return ~0U; 5639413783Smrg } 5739413783Smrg} 5839413783Smrg 5939413783Smrg#endif /* USE_GLAMOR */ 6039413783Smrg 6139413783Smrg 62de2362d3Smrgstatic const unsigned MicroBlockTable[5][3][2] = { 63de2362d3Smrg /*linear tiled square-tiled */ 64de2362d3Smrg {{32, 1}, {8, 4}, {0, 0}}, /* 8 bits per pixel */ 65de2362d3Smrg {{16, 1}, {8, 2}, {4, 4}}, /* 16 bits per pixel */ 66de2362d3Smrg {{ 8, 1}, {4, 2}, {0, 0}}, /* 32 bits per pixel */ 67de2362d3Smrg {{ 4, 1}, {0, 0}, {2, 2}}, /* 64 bits per pixel */ 68de2362d3Smrg {{ 2, 1}, {0, 0}, {0, 0}} /* 128 bits per pixel */ 69de2362d3Smrg}; 70de2362d3Smrg 71de2362d3Smrg/* Return true if macrotiling can be enabled */ 72de2362d3Smrgstatic Bool RADEONMacroSwitch(int width, int height, int bpp, 73de2362d3Smrg uint32_t flags, Bool rv350_mode) 74de2362d3Smrg{ 75de2362d3Smrg unsigned tilew, tileh, microtiled, logbpp; 76de2362d3Smrg 77de2362d3Smrg logbpp = RADEONLog2(bpp / 8); 78de2362d3Smrg if (logbpp > 4) 79de2362d3Smrg return 0; 80de2362d3Smrg 81de2362d3Smrg microtiled = !!(flags & RADEON_TILING_MICRO); 82de2362d3Smrg tilew = MicroBlockTable[logbpp][microtiled][0] * 8; 83de2362d3Smrg tileh = MicroBlockTable[logbpp][microtiled][1] * 8; 84de2362d3Smrg 85de2362d3Smrg /* See TX_FILTER1_n.MACRO_SWITCH. */ 86de2362d3Smrg if (rv350_mode) { 87de2362d3Smrg return width >= tilew && height >= tileh; 88de2362d3Smrg } else { 89de2362d3Smrg return width > tilew && height > tileh; 90de2362d3Smrg } 91de2362d3Smrg} 92de2362d3Smrg 9339413783Smrgstatic unsigned eg_tile_split_opp(unsigned tile_split) 9439413783Smrg{ 9539413783Smrg switch (tile_split) { 9639413783Smrg case 0: tile_split = 64; break; 9739413783Smrg case 1: tile_split = 128; break; 9839413783Smrg case 2: tile_split = 256; break; 9939413783Smrg case 3: tile_split = 512; break; 10039413783Smrg default: 10139413783Smrg case 4: tile_split = 1024; break; 10239413783Smrg case 5: tile_split = 2048; break; 10339413783Smrg case 6: tile_split = 4096; break; 10439413783Smrg } 10539413783Smrg return tile_split; 10639413783Smrg} 10739413783Smrg 10839413783SmrgBool 10939413783Smrgradeon_surface_initialize(RADEONInfoPtr info, struct radeon_surface *surface, 11039413783Smrg int width, int height, int cpp, uint32_t tiling_flags, 11139413783Smrg int usage_hint) 11239413783Smrg{ 11339413783Smrg memset(surface, 0, sizeof(struct radeon_surface)); 11439413783Smrg 11539413783Smrg surface->npix_x = width; 11639413783Smrg /* need to align height to 8 for old kernel */ 11739413783Smrg surface->npix_y = RADEON_ALIGN(height, 8); 11839413783Smrg surface->npix_z = 1; 11939413783Smrg surface->blk_w = 1; 12039413783Smrg surface->blk_h = 1; 12139413783Smrg surface->blk_d = 1; 12239413783Smrg surface->array_size = 1; 12339413783Smrg surface->last_level = 0; 12439413783Smrg surface->bpe = cpp; 12539413783Smrg surface->nsamples = 1; 12639413783Smrg if (height < 128) { 12739413783Smrg /* disable 2d tiling for small surface to work around 12839413783Smrg * the fact that ddx align height to 8 pixel for old 12939413783Smrg * obscure reason i can't remember 13039413783Smrg */ 13139413783Smrg tiling_flags &= ~RADEON_TILING_MACRO; 13239413783Smrg } 13339413783Smrg 13439413783Smrg surface->flags = RADEON_SURF_SCANOUT | RADEON_SURF_HAS_TILE_MODE_INDEX | 13539413783Smrg RADEON_SURF_SET(RADEON_SURF_TYPE_2D, TYPE); 13639413783Smrg 13739413783Smrg if (usage_hint & RADEON_CREATE_PIXMAP_SZBUFFER) { 13839413783Smrg surface->flags |= RADEON_SURF_ZBUFFER; 13939413783Smrg surface->flags |= RADEON_SURF_SBUFFER; 14039413783Smrg } 14139413783Smrg 14239413783Smrg if ((tiling_flags & RADEON_TILING_MACRO)) { 14339413783Smrg surface->flags = RADEON_SURF_CLR(surface->flags, MODE); 14439413783Smrg surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE); 14539413783Smrg } else if ((tiling_flags & RADEON_TILING_MICRO)) { 14639413783Smrg surface->flags = RADEON_SURF_CLR(surface->flags, MODE); 14739413783Smrg surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE); 14839413783Smrg } else 14939413783Smrg surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_LINEAR, MODE); 15039413783Smrg 15139413783Smrg if (info->ChipFamily >= CHIP_FAMILY_CEDAR) { 15239413783Smrg surface->bankw = (tiling_flags >> RADEON_TILING_EG_BANKW_SHIFT) & 15339413783Smrg RADEON_TILING_EG_BANKW_MASK; 15439413783Smrg surface->bankh = (tiling_flags >> RADEON_TILING_EG_BANKH_SHIFT) & 15539413783Smrg RADEON_TILING_EG_BANKH_MASK; 15639413783Smrg surface->tile_split = eg_tile_split_opp((tiling_flags >> RADEON_TILING_EG_TILE_SPLIT_SHIFT) & 15739413783Smrg RADEON_TILING_EG_TILE_SPLIT_MASK); 15839413783Smrg if (surface->flags & RADEON_SURF_SBUFFER) { 15939413783Smrg surface->stencil_tile_split = 16039413783Smrg (tiling_flags >> RADEON_TILING_EG_STENCIL_TILE_SPLIT_SHIFT) & 16139413783Smrg RADEON_TILING_EG_STENCIL_TILE_SPLIT_MASK; 16239413783Smrg } 16339413783Smrg surface->mtilea = (tiling_flags >> RADEON_TILING_EG_MACRO_TILE_ASPECT_SHIFT) & 16439413783Smrg RADEON_TILING_EG_MACRO_TILE_ASPECT_MASK; 16539413783Smrg } 16639413783Smrg 16739413783Smrg if (radeon_surface_best(info->surf_man, surface)) 16839413783Smrg return FALSE; 16939413783Smrg 17039413783Smrg if (radeon_surface_init(info->surf_man, surface)) 17139413783Smrg return FALSE; 17239413783Smrg 17339413783Smrg return TRUE; 17439413783Smrg} 17539413783Smrg 176de2362d3Smrg/* Calculate appropriate tiling and pitch for a pixmap and allocate a BO that 177de2362d3Smrg * can hold it. 178de2362d3Smrg */ 17939413783Smrgstruct radeon_buffer * 180de2362d3Smrgradeon_alloc_pixmap_bo(ScrnInfoPtr pScrn, int width, int height, int depth, 181de2362d3Smrg int usage_hint, int bitsPerPixel, int *new_pitch, 182de2362d3Smrg struct radeon_surface *new_surface, uint32_t *new_tiling) 183de2362d3Smrg{ 184de2362d3Smrg RADEONInfoPtr info = RADEONPTR(pScrn); 185de2362d3Smrg int pitch, base_align; 186de2362d3Smrg uint32_t size, heighta; 187de2362d3Smrg int cpp = bitsPerPixel / 8; 1880d16fef4Smrg uint32_t tiling = 0, flags = 0; 189de2362d3Smrg struct radeon_surface surface; 19039413783Smrg struct radeon_buffer *bo; 191de2362d3Smrg int domain = RADEON_GEM_DOMAIN_VRAM; 19239413783Smrg 19339413783Smrg#ifdef USE_GLAMOR 19439413783Smrg if (info->use_glamor && 19539413783Smrg !(usage_hint == CREATE_PIXMAP_USAGE_BACKING_PIXMAP && 19639413783Smrg info->shadow_primary)) { 19739413783Smrg uint32_t bo_use = GBM_BO_USE_RENDERING; 19839413783Smrg uint32_t gbm_format = radeon_get_gbm_format(depth, bitsPerPixel); 19939413783Smrg 20039413783Smrg if (gbm_format == ~0U) 20139413783Smrg return NULL; 20239413783Smrg 20339413783Smrg bo = calloc(1, sizeof(struct radeon_buffer)); 20439413783Smrg if (!bo) 20539413783Smrg return NULL; 20639413783Smrg 20739413783Smrg bo->ref_count = 1; 20839413783Smrg 20939413783Smrg if (bitsPerPixel == pScrn->bitsPerPixel) 21039413783Smrg bo_use |= GBM_BO_USE_SCANOUT; 21139413783Smrg 21239413783Smrg if ((usage_hint == CREATE_PIXMAP_USAGE_BACKING_PIXMAP && 21339413783Smrg info->shadow_primary) || 21439413783Smrg (usage_hint & 0xffff) == CREATE_PIXMAP_USAGE_SHARED) 21539413783Smrg bo_use |= GBM_BO_USE_LINEAR; 21639413783Smrg 21739413783Smrg bo->bo.gbm = gbm_bo_create(info->gbm, width, height, gbm_format, bo_use); 21839413783Smrg if (!bo->bo.gbm) { 21939413783Smrg free(bo); 22039413783Smrg return NULL; 22139413783Smrg } 22239413783Smrg 22339413783Smrg bo->flags |= RADEON_BO_FLAGS_GBM; 22439413783Smrg 22539413783Smrg if (new_pitch) 22639413783Smrg *new_pitch = gbm_bo_get_stride(bo->bo.gbm); 22739413783Smrg 22839413783Smrg return bo; 22939413783Smrg } 23039413783Smrg#endif 23139413783Smrg 232de2362d3Smrg if (usage_hint) { 233de2362d3Smrg if (info->allowColorTiling) { 234de2362d3Smrg if (usage_hint & RADEON_CREATE_PIXMAP_TILING_MACRO) 235de2362d3Smrg tiling |= RADEON_TILING_MACRO; 236de2362d3Smrg if (usage_hint & RADEON_CREATE_PIXMAP_TILING_MICRO) 237de2362d3Smrg tiling |= RADEON_TILING_MICRO; 238de2362d3Smrg } 239de2362d3Smrg if (usage_hint & RADEON_CREATE_PIXMAP_DEPTH) 240de2362d3Smrg tiling |= RADEON_TILING_MACRO | RADEON_TILING_MICRO; 241de2362d3Smrg 2420d16fef4Smrg if ((usage_hint == CREATE_PIXMAP_USAGE_BACKING_PIXMAP && 2438bf5c682Smrg info->shadow_primary) || 2448bf5c682Smrg (usage_hint & 0xffff) == CREATE_PIXMAP_USAGE_SHARED) { 245de2362d3Smrg tiling = 0; 246de2362d3Smrg domain = RADEON_GEM_DOMAIN_GTT; 247de2362d3Smrg } 248de2362d3Smrg } 249de2362d3Smrg 250de2362d3Smrg /* Small pixmaps must not be macrotiled on R300, hw cannot sample them 251de2362d3Smrg * correctly because samplers automatically switch to macrolinear. */ 252de2362d3Smrg if (info->ChipFamily >= CHIP_FAMILY_R300 && 253de2362d3Smrg info->ChipFamily <= CHIP_FAMILY_RS740 && 254de2362d3Smrg (tiling & RADEON_TILING_MACRO) && 255de2362d3Smrg !RADEONMacroSwitch(width, height, bitsPerPixel, tiling, 256de2362d3Smrg info->ChipFamily >= CHIP_FAMILY_RV350)) { 257de2362d3Smrg tiling &= ~RADEON_TILING_MACRO; 258de2362d3Smrg } 259de2362d3Smrg 260de2362d3Smrg heighta = RADEON_ALIGN(height, drmmode_get_height_align(pScrn, tiling)); 261de2362d3Smrg pitch = RADEON_ALIGN(width, drmmode_get_pitch_align(pScrn, cpp, tiling)) * cpp; 262de2362d3Smrg base_align = drmmode_get_base_align(pScrn, cpp, tiling); 263de2362d3Smrg size = RADEON_ALIGN(heighta * pitch, RADEON_GPU_PAGE_SIZE); 26439413783Smrg 26539413783Smrg if (width && info->surf_man) { 26639413783Smrg if (!radeon_surface_initialize(info, &surface, width, height, cpp, 26739413783Smrg tiling, usage_hint)) 26839413783Smrg return NULL; 26939413783Smrg 27039413783Smrg size = surface.bo_size; 27139413783Smrg base_align = surface.bo_alignment; 27239413783Smrg pitch = surface.level[0].pitch_bytes; 27339413783Smrg tiling = 0; 27439413783Smrg switch (surface.level[0].mode) { 27539413783Smrg case RADEON_SURF_MODE_2D: 27639413783Smrg tiling |= RADEON_TILING_MACRO; 27739413783Smrg tiling |= surface.bankw << RADEON_TILING_EG_BANKW_SHIFT; 27839413783Smrg tiling |= surface.bankh << RADEON_TILING_EG_BANKH_SHIFT; 27939413783Smrg tiling |= surface.mtilea << RADEON_TILING_EG_MACRO_TILE_ASPECT_SHIFT; 28039413783Smrg if (surface.tile_split) 28139413783Smrg tiling |= eg_tile_split(surface.tile_split) << RADEON_TILING_EG_TILE_SPLIT_SHIFT; 28239413783Smrg if (surface.flags & RADEON_SURF_SBUFFER) 28339413783Smrg tiling |= eg_tile_split(surface.stencil_tile_split) << RADEON_TILING_EG_STENCIL_TILE_SPLIT_SHIFT; 28439413783Smrg break; 28539413783Smrg case RADEON_SURF_MODE_1D: 28639413783Smrg tiling |= RADEON_TILING_MICRO; 28739413783Smrg break; 28839413783Smrg default: 28939413783Smrg break; 290de2362d3Smrg } 291de2362d3Smrg 29239413783Smrg if (new_surface) 29339413783Smrg *new_surface = surface; 29439413783Smrg } 29539413783Smrg 2960d16fef4Smrg if (tiling) 2970d16fef4Smrg flags |= RADEON_GEM_NO_CPU_ACCESS; 2980d16fef4Smrg 29939413783Smrg bo = calloc(1, sizeof(struct radeon_buffer)); 30039413783Smrg if (!bo) 30139413783Smrg return NULL; 30239413783Smrg 30339413783Smrg bo->ref_count = 1; 30439413783Smrg bo->bo.radeon = radeon_bo_open(info->bufmgr, 0, size, base_align, 30539413783Smrg domain, flags); 306de2362d3Smrg 30739413783Smrg if (bo && tiling && radeon_bo_set_tiling(bo->bo.radeon, tiling, pitch) == 0) 308de2362d3Smrg *new_tiling = tiling; 309de2362d3Smrg 310de2362d3Smrg *new_pitch = pitch; 311de2362d3Smrg return bo; 312de2362d3Smrg} 313de2362d3Smrg 31439413783Smrg 31539413783Smrg/* Flush and wait for the BO to become idle */ 31639413783Smrgvoid 31739413783Smrgradeon_finish(ScrnInfoPtr scrn, struct radeon_buffer *bo) 31839413783Smrg{ 31939413783Smrg RADEONInfoPtr info = RADEONPTR(scrn); 32039413783Smrg 32139413783Smrg if (info->use_glamor) { 32239413783Smrg radeon_glamor_finish(scrn); 32339413783Smrg return; 32439413783Smrg } 32539413783Smrg 32639413783Smrg radeon_cs_flush_indirect(scrn); 32739413783Smrg radeon_bo_wait(bo->bo.radeon); 32839413783Smrg} 32939413783Smrg 33039413783Smrg 3318bf5c682Smrg/* Clear the pixmap contents to black */ 3328bf5c682Smrgvoid 3338bf5c682Smrgradeon_pixmap_clear(PixmapPtr pixmap) 3348bf5c682Smrg{ 3358bf5c682Smrg ScreenPtr screen = pixmap->drawable.pScreen; 3368bf5c682Smrg RADEONInfoPtr info = RADEONPTR(xf86ScreenToScrn(screen)); 3378bf5c682Smrg GCPtr gc = GetScratchGC(pixmap->drawable.depth, screen); 3388bf5c682Smrg Bool force = info->accel_state->force; 3398bf5c682Smrg xRectangle rect; 3408bf5c682Smrg 3418bf5c682Smrg info->accel_state->force = TRUE; 3428bf5c682Smrg ValidateGC(&pixmap->drawable, gc); 3438bf5c682Smrg rect.x = 0; 3448bf5c682Smrg rect.y = 0; 3458bf5c682Smrg rect.width = pixmap->drawable.width; 3468bf5c682Smrg rect.height = pixmap->drawable.height; 3478bf5c682Smrg gc->ops->PolyFillRect(&pixmap->drawable, gc, 1, &rect); 3488bf5c682Smrg FreeScratchGC(gc); 3498bf5c682Smrg info->accel_state->force = force; 3508bf5c682Smrg} 3518bf5c682Smrg 3520d16fef4Smrg/* Get GEM handle for the pixmap */ 3530d16fef4SmrgBool radeon_get_pixmap_handle(PixmapPtr pixmap, uint32_t *handle) 3540d16fef4Smrg{ 35539413783Smrg struct radeon_buffer *bo = radeon_get_pixmap_bo(pixmap); 3560d16fef4Smrg#ifdef USE_GLAMOR 3570d16fef4Smrg ScreenPtr screen = pixmap->drawable.pScreen; 3588bf5c682Smrg ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 3598bf5c682Smrg RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn); 3608bf5c682Smrg RADEONInfoPtr info = RADEONPTR(scrn); 3610d16fef4Smrg#endif 3620d16fef4Smrg 36339413783Smrg if (bo && !(bo->flags & RADEON_BO_FLAGS_GBM)) { 36439413783Smrg *handle = bo->bo.radeon->handle; 3650d16fef4Smrg return TRUE; 3660d16fef4Smrg } 3670d16fef4Smrg 3680d16fef4Smrg#ifdef USE_GLAMOR 3690d16fef4Smrg if (info->use_glamor) { 3700d16fef4Smrg struct radeon_pixmap *priv = radeon_get_pixmap_private(pixmap); 3710d16fef4Smrg CARD16 stride; 3720d16fef4Smrg CARD32 size; 3730d16fef4Smrg int fd, r; 3740d16fef4Smrg 3750d16fef4Smrg if (!priv) { 3760d16fef4Smrg priv = calloc(1, sizeof(*priv)); 3770d16fef4Smrg radeon_set_pixmap_private(pixmap, priv); 3780d16fef4Smrg } 3790d16fef4Smrg 3800d16fef4Smrg if (priv->handle_valid) { 3810d16fef4Smrg *handle = priv->handle; 3820d16fef4Smrg return TRUE; 3830d16fef4Smrg } 3840d16fef4Smrg 3850d16fef4Smrg fd = glamor_fd_from_pixmap(screen, pixmap, &stride, &size); 3860d16fef4Smrg if (fd < 0) 3870d16fef4Smrg return FALSE; 3880d16fef4Smrg 3898bf5c682Smrg r = drmPrimeFDToHandle(pRADEONEnt->fd, fd, &priv->handle); 3900d16fef4Smrg close(fd); 3910d16fef4Smrg if (r == 0) { 3920d16fef4Smrg struct drm_radeon_gem_set_tiling args = { .handle = priv->handle }; 3930d16fef4Smrg 3940d16fef4Smrg priv->handle_valid = TRUE; 3950d16fef4Smrg *handle = priv->handle; 3960d16fef4Smrg 3978bf5c682Smrg if (drmCommandWriteRead(pRADEONEnt->fd, 3980d16fef4Smrg DRM_RADEON_GEM_GET_TILING, &args, 3990d16fef4Smrg sizeof(args)) == 0) 4000d16fef4Smrg priv->tiling_flags = args.tiling_flags; 4010d16fef4Smrg 4020d16fef4Smrg return TRUE; 4030d16fef4Smrg } 4040d16fef4Smrg } 4050d16fef4Smrg#endif 4060d16fef4Smrg 4070d16fef4Smrg return FALSE; 4080d16fef4Smrg} 4090d16fef4Smrg 4100d16fef4Smrguint32_t radeon_get_pixmap_tiling_flags(PixmapPtr pPix) 4110d16fef4Smrg{ 4120d16fef4Smrg#ifdef USE_GLAMOR 4130d16fef4Smrg RADEONInfoPtr info = RADEONPTR(xf86ScreenToScrn(pPix->drawable.pScreen)); 4140d16fef4Smrg 4150d16fef4Smrg if (info->use_glamor) { 4160d16fef4Smrg struct radeon_pixmap *priv = radeon_get_pixmap_private(pPix); 4170d16fef4Smrg 4180d16fef4Smrg if (!priv || (!priv->bo && !priv->handle_valid)) { 4190d16fef4Smrg uint32_t handle; 4200d16fef4Smrg 4210d16fef4Smrg radeon_get_pixmap_handle(pPix, &handle); 4220d16fef4Smrg priv = radeon_get_pixmap_private(pPix); 4230d16fef4Smrg } 4240d16fef4Smrg 4250d16fef4Smrg return priv ? priv->tiling_flags : 0; 4260d16fef4Smrg } else 4270d16fef4Smrg#endif 4280d16fef4Smrg { 4290d16fef4Smrg struct radeon_exa_pixmap_priv *driver_priv; 4300d16fef4Smrg driver_priv = exaGetPixmapDriverPrivate(pPix); 4310d16fef4Smrg return driver_priv ? driver_priv->tiling_flags : 0; 4320d16fef4Smrg } 4330d16fef4Smrg} 4340d16fef4Smrg 435de2362d3Smrg 436de2362d3SmrgBool radeon_share_pixmap_backing(struct radeon_bo *bo, void **handle_p) 437de2362d3Smrg{ 438de2362d3Smrg int handle; 439de2362d3Smrg 440de2362d3Smrg if (radeon_gem_prime_share_bo(bo, &handle) != 0) 441de2362d3Smrg return FALSE; 442de2362d3Smrg 443de2362d3Smrg *handle_p = (void *)(long)handle; 444de2362d3Smrg return TRUE; 445de2362d3Smrg} 446de2362d3Smrg 447de2362d3SmrgBool radeon_set_shared_pixmap_backing(PixmapPtr ppix, void *fd_handle, 448de2362d3Smrg struct radeon_surface *surface) 449de2362d3Smrg{ 450de2362d3Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(ppix->drawable.pScreen); 451de2362d3Smrg RADEONInfoPtr info = RADEONPTR(pScrn); 45239413783Smrg struct radeon_buffer *bo; 453de2362d3Smrg int ihandle = (int)(long)fd_handle; 454de2362d3Smrg uint32_t size = ppix->devKind * ppix->drawable.height; 4557314432eSmrg Bool ret = FALSE; 456de2362d3Smrg 45739413783Smrg if (ihandle == -1) 45839413783Smrg return radeon_set_pixmap_bo(ppix, NULL); 45939413783Smrg 46039413783Smrg bo = (struct radeon_buffer *)calloc(1, sizeof(struct radeon_buffer)); 461de2362d3Smrg if (!bo) 46239413783Smrg goto error; 463de2362d3Smrg 46439413783Smrg#ifdef USE_GLAMOR 46539413783Smrg if (info->use_glamor) { 46639413783Smrg struct gbm_import_fd_data data; 46739413783Smrg uint32_t bo_use = GBM_BO_USE_RENDERING; 468de2362d3Smrg 46939413783Smrg data.format = radeon_get_gbm_format(ppix->drawable.depth, 47039413783Smrg ppix->drawable.bitsPerPixel); 47139413783Smrg if (data.format == ~0U) 47239413783Smrg goto error; 47339413783Smrg 47439413783Smrg bo->ref_count = 1; 47539413783Smrg 47639413783Smrg data.fd = ihandle; 47739413783Smrg data.width = ppix->drawable.width; 47839413783Smrg data.height = ppix->drawable.height; 47939413783Smrg data.stride = ppix->devKind; 48039413783Smrg 48139413783Smrg if (ppix->drawable.bitsPerPixel == pScrn->bitsPerPixel) 48239413783Smrg bo_use |= GBM_BO_USE_SCANOUT; 48339413783Smrg 48439413783Smrg bo->bo.gbm = gbm_bo_import(info->gbm, GBM_BO_IMPORT_FD, &data, bo_use); 48539413783Smrg if (!bo->bo.gbm) 48639413783Smrg goto error; 48739413783Smrg 48839413783Smrg bo->flags |= RADEON_BO_FLAGS_GBM; 48939413783Smrg 49039413783Smrg if (!radeon_glamor_create_textured_pixmap(ppix, bo)) { 49139413783Smrg radeon_buffer_unref(&bo); 49239413783Smrg return FALSE; 49339413783Smrg } 49439413783Smrg 49539413783Smrg ret = radeon_set_pixmap_bo(ppix, bo); 49639413783Smrg /* radeon_set_pixmap_bo increments ref_count if it succeeds */ 49739413783Smrg radeon_buffer_unref(&bo); 49839413783Smrg return ret; 49939413783Smrg } 50039413783Smrg#endif 50139413783Smrg 50239413783Smrg bo->bo.radeon = radeon_gem_bo_open_prime(info->bufmgr, ihandle, size); 50339413783Smrg if (!bo) 50439413783Smrg goto error; 50539413783Smrg 50639413783Smrg bo->ref_count = 1; 5077314432eSmrg ret = radeon_set_pixmap_bo(ppix, bo); 5087314432eSmrg if (!ret) 5097314432eSmrg goto error; 5100d16fef4Smrg 51139413783Smrg if (surface) { 51239413783Smrg struct radeon_exa_pixmap_priv *driver_priv; 5130d16fef4Smrg uint32_t tiling_flags; 5140d16fef4Smrg 51539413783Smrg driver_priv = exaGetPixmapDriverPrivate(ppix); 51639413783Smrg tiling_flags = driver_priv->tiling_flags; 517de2362d3Smrg 51839413783Smrg if (!radeon_surface_initialize(info, surface, ppix->drawable.width, 51939413783Smrg ppix->drawable.height, 52039413783Smrg ppix->drawable.bitsPerPixel / 8, 52139413783Smrg tiling_flags, 0)) { 5227314432eSmrg ret = FALSE; 5237314432eSmrg goto error; 524de2362d3Smrg } 52539413783Smrg 526de2362d3Smrg /* we have to post hack the surface to reflect the actual size 527de2362d3Smrg of the shared pixmap */ 528de2362d3Smrg surface->level[0].pitch_bytes = ppix->devKind; 529de2362d3Smrg surface->level[0].nblk_x = ppix->devKind / surface->bpe; 530de2362d3Smrg } 531de2362d3Smrg 5327314432eSmrg error: 533de2362d3Smrg close(ihandle); 534de2362d3Smrg /* we have a reference from the alloc and one from set pixmap bo, 535de2362d3Smrg drop one */ 53639413783Smrg radeon_buffer_unref(&bo); 5377314432eSmrg return ret; 538de2362d3Smrg} 539