radeon_bo_helper.c revision b338b52f
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 42f2b8d91dSmrg case 15: 43f2b8d91dSmrg return GBM_FORMAT_ARGB1555; 4439413783Smrg case 16: 4539413783Smrg return GBM_FORMAT_RGB565; 4639413783Smrg case 32: 4739413783Smrg return GBM_FORMAT_ARGB8888; 4839413783Smrg case 30: 4939413783Smrg return GBM_FORMAT_XRGB2101010; 5039413783Smrg case 24: 5139413783Smrg if (bitsPerPixel == 32) 5239413783Smrg return GBM_FORMAT_XRGB8888; 5339413783Smrg /* fall through */ 5439413783Smrg default: 5539413783Smrg ErrorF("%s: Unsupported depth/bpp %d/%d\n", __func__, depth, 5639413783Smrg bitsPerPixel); 5739413783Smrg return ~0U; 5839413783Smrg } 5939413783Smrg} 6039413783Smrg 6139413783Smrg#endif /* USE_GLAMOR */ 6239413783Smrg 6339413783Smrg 64de2362d3Smrgstatic const unsigned MicroBlockTable[5][3][2] = { 65de2362d3Smrg /*linear tiled square-tiled */ 66de2362d3Smrg {{32, 1}, {8, 4}, {0, 0}}, /* 8 bits per pixel */ 67de2362d3Smrg {{16, 1}, {8, 2}, {4, 4}}, /* 16 bits per pixel */ 68de2362d3Smrg {{ 8, 1}, {4, 2}, {0, 0}}, /* 32 bits per pixel */ 69de2362d3Smrg {{ 4, 1}, {0, 0}, {2, 2}}, /* 64 bits per pixel */ 70de2362d3Smrg {{ 2, 1}, {0, 0}, {0, 0}} /* 128 bits per pixel */ 71de2362d3Smrg}; 72de2362d3Smrg 73de2362d3Smrg/* Return true if macrotiling can be enabled */ 74de2362d3Smrgstatic Bool RADEONMacroSwitch(int width, int height, int bpp, 75de2362d3Smrg uint32_t flags, Bool rv350_mode) 76de2362d3Smrg{ 77de2362d3Smrg unsigned tilew, tileh, microtiled, logbpp; 78de2362d3Smrg 79de2362d3Smrg logbpp = RADEONLog2(bpp / 8); 80de2362d3Smrg if (logbpp > 4) 81de2362d3Smrg return 0; 82de2362d3Smrg 83de2362d3Smrg microtiled = !!(flags & RADEON_TILING_MICRO); 84de2362d3Smrg tilew = MicroBlockTable[logbpp][microtiled][0] * 8; 85de2362d3Smrg tileh = MicroBlockTable[logbpp][microtiled][1] * 8; 86de2362d3Smrg 87de2362d3Smrg /* See TX_FILTER1_n.MACRO_SWITCH. */ 88de2362d3Smrg if (rv350_mode) { 89de2362d3Smrg return width >= tilew && height >= tileh; 90de2362d3Smrg } else { 91de2362d3Smrg return width > tilew && height > tileh; 92de2362d3Smrg } 93de2362d3Smrg} 94de2362d3Smrg 9539413783Smrgstatic unsigned eg_tile_split_opp(unsigned tile_split) 9639413783Smrg{ 9739413783Smrg switch (tile_split) { 9839413783Smrg case 0: tile_split = 64; break; 9939413783Smrg case 1: tile_split = 128; break; 10039413783Smrg case 2: tile_split = 256; break; 10139413783Smrg case 3: tile_split = 512; break; 10239413783Smrg default: 10339413783Smrg case 4: tile_split = 1024; break; 10439413783Smrg case 5: tile_split = 2048; break; 10539413783Smrg case 6: tile_split = 4096; break; 10639413783Smrg } 10739413783Smrg return tile_split; 10839413783Smrg} 10939413783Smrg 11039413783SmrgBool 11139413783Smrgradeon_surface_initialize(RADEONInfoPtr info, struct radeon_surface *surface, 11239413783Smrg int width, int height, int cpp, uint32_t tiling_flags, 11339413783Smrg int usage_hint) 11439413783Smrg{ 11539413783Smrg memset(surface, 0, sizeof(struct radeon_surface)); 11639413783Smrg 11739413783Smrg surface->npix_x = width; 11839413783Smrg /* need to align height to 8 for old kernel */ 11939413783Smrg surface->npix_y = RADEON_ALIGN(height, 8); 12039413783Smrg surface->npix_z = 1; 12139413783Smrg surface->blk_w = 1; 12239413783Smrg surface->blk_h = 1; 12339413783Smrg surface->blk_d = 1; 12439413783Smrg surface->array_size = 1; 12539413783Smrg surface->last_level = 0; 12639413783Smrg surface->bpe = cpp; 12739413783Smrg surface->nsamples = 1; 12839413783Smrg if (height < 128) { 12939413783Smrg /* disable 2d tiling for small surface to work around 13039413783Smrg * the fact that ddx align height to 8 pixel for old 13139413783Smrg * obscure reason i can't remember 13239413783Smrg */ 13339413783Smrg tiling_flags &= ~RADEON_TILING_MACRO; 13439413783Smrg } 13539413783Smrg 13639413783Smrg surface->flags = RADEON_SURF_SCANOUT | RADEON_SURF_HAS_TILE_MODE_INDEX | 13739413783Smrg RADEON_SURF_SET(RADEON_SURF_TYPE_2D, TYPE); 13839413783Smrg 13939413783Smrg if (usage_hint & RADEON_CREATE_PIXMAP_SZBUFFER) { 14039413783Smrg surface->flags |= RADEON_SURF_ZBUFFER; 14139413783Smrg surface->flags |= RADEON_SURF_SBUFFER; 14239413783Smrg } 14339413783Smrg 14439413783Smrg if ((tiling_flags & RADEON_TILING_MACRO)) { 14539413783Smrg surface->flags = RADEON_SURF_CLR(surface->flags, MODE); 14639413783Smrg surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE); 14739413783Smrg } else if ((tiling_flags & RADEON_TILING_MICRO)) { 14839413783Smrg surface->flags = RADEON_SURF_CLR(surface->flags, MODE); 14939413783Smrg surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE); 15039413783Smrg } else 15139413783Smrg surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_LINEAR, MODE); 15239413783Smrg 15339413783Smrg if (info->ChipFamily >= CHIP_FAMILY_CEDAR) { 15439413783Smrg surface->bankw = (tiling_flags >> RADEON_TILING_EG_BANKW_SHIFT) & 15539413783Smrg RADEON_TILING_EG_BANKW_MASK; 15639413783Smrg surface->bankh = (tiling_flags >> RADEON_TILING_EG_BANKH_SHIFT) & 15739413783Smrg RADEON_TILING_EG_BANKH_MASK; 15839413783Smrg surface->tile_split = eg_tile_split_opp((tiling_flags >> RADEON_TILING_EG_TILE_SPLIT_SHIFT) & 15939413783Smrg RADEON_TILING_EG_TILE_SPLIT_MASK); 16039413783Smrg if (surface->flags & RADEON_SURF_SBUFFER) { 16139413783Smrg surface->stencil_tile_split = 16239413783Smrg (tiling_flags >> RADEON_TILING_EG_STENCIL_TILE_SPLIT_SHIFT) & 16339413783Smrg RADEON_TILING_EG_STENCIL_TILE_SPLIT_MASK; 16439413783Smrg } 16539413783Smrg surface->mtilea = (tiling_flags >> RADEON_TILING_EG_MACRO_TILE_ASPECT_SHIFT) & 16639413783Smrg RADEON_TILING_EG_MACRO_TILE_ASPECT_MASK; 16739413783Smrg } 16839413783Smrg 16939413783Smrg if (radeon_surface_best(info->surf_man, surface)) 17039413783Smrg return FALSE; 17139413783Smrg 17239413783Smrg if (radeon_surface_init(info->surf_man, surface)) 17339413783Smrg return FALSE; 17439413783Smrg 17539413783Smrg return TRUE; 17639413783Smrg} 17739413783Smrg 178de2362d3Smrg/* Calculate appropriate tiling and pitch for a pixmap and allocate a BO that 179de2362d3Smrg * can hold it. 180de2362d3Smrg */ 18139413783Smrgstruct radeon_buffer * 182de2362d3Smrgradeon_alloc_pixmap_bo(ScrnInfoPtr pScrn, int width, int height, int depth, 183de2362d3Smrg int usage_hint, int bitsPerPixel, int *new_pitch, 184de2362d3Smrg struct radeon_surface *new_surface, uint32_t *new_tiling) 185de2362d3Smrg{ 186de2362d3Smrg RADEONInfoPtr info = RADEONPTR(pScrn); 187de2362d3Smrg int pitch, base_align; 188de2362d3Smrg uint32_t size, heighta; 189de2362d3Smrg int cpp = bitsPerPixel / 8; 1900d16fef4Smrg uint32_t tiling = 0, flags = 0; 191de2362d3Smrg struct radeon_surface surface; 19239413783Smrg struct radeon_buffer *bo; 193de2362d3Smrg int domain = RADEON_GEM_DOMAIN_VRAM; 19439413783Smrg 19539413783Smrg#ifdef USE_GLAMOR 19639413783Smrg if (info->use_glamor && 19739413783Smrg !(usage_hint == CREATE_PIXMAP_USAGE_BACKING_PIXMAP && 19839413783Smrg info->shadow_primary)) { 19939413783Smrg uint32_t bo_use = GBM_BO_USE_RENDERING; 20039413783Smrg uint32_t gbm_format = radeon_get_gbm_format(depth, bitsPerPixel); 20139413783Smrg 20239413783Smrg if (gbm_format == ~0U) 20339413783Smrg return NULL; 20439413783Smrg 20539413783Smrg bo = calloc(1, sizeof(struct radeon_buffer)); 20639413783Smrg if (!bo) 20739413783Smrg return NULL; 20839413783Smrg 20939413783Smrg bo->ref_count = 1; 21039413783Smrg 21139413783Smrg if (bitsPerPixel == pScrn->bitsPerPixel) 21239413783Smrg bo_use |= GBM_BO_USE_SCANOUT; 21339413783Smrg 214569958d0Smrg#ifdef GBM_BO_USE_LINEAR 21539413783Smrg if ((usage_hint == CREATE_PIXMAP_USAGE_BACKING_PIXMAP && 21639413783Smrg info->shadow_primary) || 21739413783Smrg (usage_hint & 0xffff) == CREATE_PIXMAP_USAGE_SHARED) 21839413783Smrg bo_use |= GBM_BO_USE_LINEAR; 219569958d0Smrg#endif 22039413783Smrg 22139413783Smrg bo->bo.gbm = gbm_bo_create(info->gbm, width, height, gbm_format, bo_use); 22239413783Smrg if (!bo->bo.gbm) { 22339413783Smrg free(bo); 22439413783Smrg return NULL; 22539413783Smrg } 22639413783Smrg 22739413783Smrg bo->flags |= RADEON_BO_FLAGS_GBM; 22839413783Smrg 22939413783Smrg if (new_pitch) 23039413783Smrg *new_pitch = gbm_bo_get_stride(bo->bo.gbm); 23139413783Smrg 23239413783Smrg return bo; 23339413783Smrg } 23439413783Smrg#endif 23539413783Smrg 236de2362d3Smrg if (usage_hint) { 237de2362d3Smrg if (info->allowColorTiling) { 238de2362d3Smrg if (usage_hint & RADEON_CREATE_PIXMAP_TILING_MACRO) 239de2362d3Smrg tiling |= RADEON_TILING_MACRO; 240de2362d3Smrg if (usage_hint & RADEON_CREATE_PIXMAP_TILING_MICRO) 241de2362d3Smrg tiling |= RADEON_TILING_MICRO; 242de2362d3Smrg } 243de2362d3Smrg if (usage_hint & RADEON_CREATE_PIXMAP_DEPTH) 244de2362d3Smrg tiling |= RADEON_TILING_MACRO | RADEON_TILING_MICRO; 245de2362d3Smrg 2460d16fef4Smrg if ((usage_hint == CREATE_PIXMAP_USAGE_BACKING_PIXMAP && 2478bf5c682Smrg info->shadow_primary) || 2488bf5c682Smrg (usage_hint & 0xffff) == CREATE_PIXMAP_USAGE_SHARED) { 249de2362d3Smrg tiling = 0; 250de2362d3Smrg domain = RADEON_GEM_DOMAIN_GTT; 251de2362d3Smrg } 252de2362d3Smrg } 253de2362d3Smrg 254de2362d3Smrg /* Small pixmaps must not be macrotiled on R300, hw cannot sample them 255de2362d3Smrg * correctly because samplers automatically switch to macrolinear. */ 256de2362d3Smrg if (info->ChipFamily >= CHIP_FAMILY_R300 && 257de2362d3Smrg info->ChipFamily <= CHIP_FAMILY_RS740 && 258de2362d3Smrg (tiling & RADEON_TILING_MACRO) && 259de2362d3Smrg !RADEONMacroSwitch(width, height, bitsPerPixel, tiling, 260de2362d3Smrg info->ChipFamily >= CHIP_FAMILY_RV350)) { 261de2362d3Smrg tiling &= ~RADEON_TILING_MACRO; 262de2362d3Smrg } 263de2362d3Smrg 264de2362d3Smrg heighta = RADEON_ALIGN(height, drmmode_get_height_align(pScrn, tiling)); 265de2362d3Smrg pitch = RADEON_ALIGN(width, drmmode_get_pitch_align(pScrn, cpp, tiling)) * cpp; 266de2362d3Smrg base_align = drmmode_get_base_align(pScrn, cpp, tiling); 267de2362d3Smrg size = RADEON_ALIGN(heighta * pitch, RADEON_GPU_PAGE_SIZE); 26839413783Smrg 26939413783Smrg if (width && info->surf_man) { 27039413783Smrg if (!radeon_surface_initialize(info, &surface, width, height, cpp, 27139413783Smrg tiling, usage_hint)) 27239413783Smrg return NULL; 27339413783Smrg 27439413783Smrg size = surface.bo_size; 27539413783Smrg base_align = surface.bo_alignment; 27639413783Smrg pitch = surface.level[0].pitch_bytes; 27739413783Smrg tiling = 0; 27839413783Smrg switch (surface.level[0].mode) { 27939413783Smrg case RADEON_SURF_MODE_2D: 28039413783Smrg tiling |= RADEON_TILING_MACRO; 28139413783Smrg tiling |= surface.bankw << RADEON_TILING_EG_BANKW_SHIFT; 28239413783Smrg tiling |= surface.bankh << RADEON_TILING_EG_BANKH_SHIFT; 28339413783Smrg tiling |= surface.mtilea << RADEON_TILING_EG_MACRO_TILE_ASPECT_SHIFT; 28439413783Smrg if (surface.tile_split) 28539413783Smrg tiling |= eg_tile_split(surface.tile_split) << RADEON_TILING_EG_TILE_SPLIT_SHIFT; 28639413783Smrg if (surface.flags & RADEON_SURF_SBUFFER) 28739413783Smrg tiling |= eg_tile_split(surface.stencil_tile_split) << RADEON_TILING_EG_STENCIL_TILE_SPLIT_SHIFT; 28839413783Smrg break; 28939413783Smrg case RADEON_SURF_MODE_1D: 29039413783Smrg tiling |= RADEON_TILING_MICRO; 29139413783Smrg break; 29239413783Smrg default: 29339413783Smrg break; 294de2362d3Smrg } 295de2362d3Smrg 29639413783Smrg if (new_surface) 29739413783Smrg *new_surface = surface; 29839413783Smrg } 29939413783Smrg 3000d16fef4Smrg if (tiling) 3010d16fef4Smrg flags |= RADEON_GEM_NO_CPU_ACCESS; 3020d16fef4Smrg 30339413783Smrg bo = calloc(1, sizeof(struct radeon_buffer)); 30439413783Smrg if (!bo) 30539413783Smrg return NULL; 30639413783Smrg 30739413783Smrg bo->ref_count = 1; 30839413783Smrg bo->bo.radeon = radeon_bo_open(info->bufmgr, 0, size, base_align, 30939413783Smrg domain, flags); 310de2362d3Smrg 311b338b52fSmrg if (bo->bo.radeon && tiling && radeon_bo_set_tiling(bo->bo.radeon, tiling, pitch) == 0) 312de2362d3Smrg *new_tiling = tiling; 313de2362d3Smrg 314de2362d3Smrg *new_pitch = pitch; 315de2362d3Smrg return bo; 316de2362d3Smrg} 317de2362d3Smrg 31839413783Smrg 31939413783Smrg/* Flush and wait for the BO to become idle */ 32039413783Smrgvoid 32139413783Smrgradeon_finish(ScrnInfoPtr scrn, struct radeon_buffer *bo) 32239413783Smrg{ 32339413783Smrg RADEONInfoPtr info = RADEONPTR(scrn); 32439413783Smrg 32539413783Smrg if (info->use_glamor) { 32639413783Smrg radeon_glamor_finish(scrn); 32739413783Smrg return; 32839413783Smrg } 32939413783Smrg 33039413783Smrg radeon_cs_flush_indirect(scrn); 33139413783Smrg radeon_bo_wait(bo->bo.radeon); 33239413783Smrg} 33339413783Smrg 33439413783Smrg 3358bf5c682Smrg/* Clear the pixmap contents to black */ 3368bf5c682Smrgvoid 3378bf5c682Smrgradeon_pixmap_clear(PixmapPtr pixmap) 3388bf5c682Smrg{ 3398bf5c682Smrg ScreenPtr screen = pixmap->drawable.pScreen; 3408bf5c682Smrg RADEONInfoPtr info = RADEONPTR(xf86ScreenToScrn(screen)); 3418bf5c682Smrg GCPtr gc = GetScratchGC(pixmap->drawable.depth, screen); 3428bf5c682Smrg Bool force = info->accel_state->force; 3438bf5c682Smrg xRectangle rect; 3448bf5c682Smrg 3458bf5c682Smrg info->accel_state->force = TRUE; 3468bf5c682Smrg ValidateGC(&pixmap->drawable, gc); 3478bf5c682Smrg rect.x = 0; 3488bf5c682Smrg rect.y = 0; 3498bf5c682Smrg rect.width = pixmap->drawable.width; 3508bf5c682Smrg rect.height = pixmap->drawable.height; 3518bf5c682Smrg gc->ops->PolyFillRect(&pixmap->drawable, gc, 1, &rect); 3528bf5c682Smrg FreeScratchGC(gc); 3538bf5c682Smrg info->accel_state->force = force; 3548bf5c682Smrg} 3558bf5c682Smrg 3560d16fef4Smrg/* Get GEM handle for the pixmap */ 3570d16fef4SmrgBool radeon_get_pixmap_handle(PixmapPtr pixmap, uint32_t *handle) 3580d16fef4Smrg{ 35939413783Smrg struct radeon_buffer *bo = radeon_get_pixmap_bo(pixmap); 3600d16fef4Smrg#ifdef USE_GLAMOR 3610d16fef4Smrg ScreenPtr screen = pixmap->drawable.pScreen; 3628bf5c682Smrg ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 3638bf5c682Smrg RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn); 3648bf5c682Smrg RADEONInfoPtr info = RADEONPTR(scrn); 3650d16fef4Smrg#endif 3660d16fef4Smrg 36739413783Smrg if (bo && !(bo->flags & RADEON_BO_FLAGS_GBM)) { 36839413783Smrg *handle = bo->bo.radeon->handle; 3690d16fef4Smrg return TRUE; 3700d16fef4Smrg } 3710d16fef4Smrg 3720d16fef4Smrg#ifdef USE_GLAMOR 3730d16fef4Smrg if (info->use_glamor) { 3740d16fef4Smrg struct radeon_pixmap *priv = radeon_get_pixmap_private(pixmap); 3750d16fef4Smrg CARD16 stride; 3760d16fef4Smrg CARD32 size; 3770d16fef4Smrg int fd, r; 3780d16fef4Smrg 3790d16fef4Smrg if (!priv) { 3800d16fef4Smrg priv = calloc(1, sizeof(*priv)); 3810d16fef4Smrg radeon_set_pixmap_private(pixmap, priv); 3820d16fef4Smrg } 3830d16fef4Smrg 3840d16fef4Smrg if (priv->handle_valid) { 3850d16fef4Smrg *handle = priv->handle; 3860d16fef4Smrg return TRUE; 3870d16fef4Smrg } 3880d16fef4Smrg 3890d16fef4Smrg fd = glamor_fd_from_pixmap(screen, pixmap, &stride, &size); 3900d16fef4Smrg if (fd < 0) 3910d16fef4Smrg return FALSE; 3920d16fef4Smrg 3938bf5c682Smrg r = drmPrimeFDToHandle(pRADEONEnt->fd, fd, &priv->handle); 3940d16fef4Smrg close(fd); 3950d16fef4Smrg if (r == 0) { 3960d16fef4Smrg struct drm_radeon_gem_set_tiling args = { .handle = priv->handle }; 3970d16fef4Smrg 3980d16fef4Smrg priv->handle_valid = TRUE; 3990d16fef4Smrg *handle = priv->handle; 4000d16fef4Smrg 4018bf5c682Smrg if (drmCommandWriteRead(pRADEONEnt->fd, 4020d16fef4Smrg DRM_RADEON_GEM_GET_TILING, &args, 4030d16fef4Smrg sizeof(args)) == 0) 4040d16fef4Smrg priv->tiling_flags = args.tiling_flags; 4050d16fef4Smrg 4060d16fef4Smrg return TRUE; 4070d16fef4Smrg } 4080d16fef4Smrg } 4090d16fef4Smrg#endif 4100d16fef4Smrg 4110d16fef4Smrg return FALSE; 4120d16fef4Smrg} 4130d16fef4Smrg 4140d16fef4Smrguint32_t radeon_get_pixmap_tiling_flags(PixmapPtr pPix) 4150d16fef4Smrg{ 4160d16fef4Smrg#ifdef USE_GLAMOR 4170d16fef4Smrg RADEONInfoPtr info = RADEONPTR(xf86ScreenToScrn(pPix->drawable.pScreen)); 4180d16fef4Smrg 4190d16fef4Smrg if (info->use_glamor) { 4200d16fef4Smrg struct radeon_pixmap *priv = radeon_get_pixmap_private(pPix); 4210d16fef4Smrg 4220d16fef4Smrg if (!priv || (!priv->bo && !priv->handle_valid)) { 4230d16fef4Smrg uint32_t handle; 4240d16fef4Smrg 4250d16fef4Smrg radeon_get_pixmap_handle(pPix, &handle); 4260d16fef4Smrg priv = radeon_get_pixmap_private(pPix); 4270d16fef4Smrg } 4280d16fef4Smrg 4290d16fef4Smrg return priv ? priv->tiling_flags : 0; 4300d16fef4Smrg } else 4310d16fef4Smrg#endif 4320d16fef4Smrg { 4330d16fef4Smrg struct radeon_exa_pixmap_priv *driver_priv; 4340d16fef4Smrg driver_priv = exaGetPixmapDriverPrivate(pPix); 4350d16fef4Smrg return driver_priv ? driver_priv->tiling_flags : 0; 4360d16fef4Smrg } 4370d16fef4Smrg} 4380d16fef4Smrg 439de2362d3Smrg 440de2362d3SmrgBool radeon_share_pixmap_backing(struct radeon_bo *bo, void **handle_p) 441de2362d3Smrg{ 442de2362d3Smrg int handle; 443de2362d3Smrg 444de2362d3Smrg if (radeon_gem_prime_share_bo(bo, &handle) != 0) 445de2362d3Smrg return FALSE; 446de2362d3Smrg 447de2362d3Smrg *handle_p = (void *)(long)handle; 448de2362d3Smrg return TRUE; 449de2362d3Smrg} 450de2362d3Smrg 451de2362d3SmrgBool radeon_set_shared_pixmap_backing(PixmapPtr ppix, void *fd_handle, 452de2362d3Smrg struct radeon_surface *surface) 453de2362d3Smrg{ 454de2362d3Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(ppix->drawable.pScreen); 455de2362d3Smrg RADEONInfoPtr info = RADEONPTR(pScrn); 45639413783Smrg struct radeon_buffer *bo; 457de2362d3Smrg int ihandle = (int)(long)fd_handle; 458de2362d3Smrg uint32_t size = ppix->devKind * ppix->drawable.height; 4597314432eSmrg Bool ret = FALSE; 460de2362d3Smrg 46139413783Smrg if (ihandle == -1) 46239413783Smrg return radeon_set_pixmap_bo(ppix, NULL); 46339413783Smrg 46439413783Smrg bo = (struct radeon_buffer *)calloc(1, sizeof(struct radeon_buffer)); 465de2362d3Smrg if (!bo) 46639413783Smrg goto error; 467de2362d3Smrg 46839413783Smrg#ifdef USE_GLAMOR 46939413783Smrg if (info->use_glamor) { 47039413783Smrg struct gbm_import_fd_data data; 47139413783Smrg uint32_t bo_use = GBM_BO_USE_RENDERING; 472de2362d3Smrg 47339413783Smrg data.format = radeon_get_gbm_format(ppix->drawable.depth, 47439413783Smrg ppix->drawable.bitsPerPixel); 47539413783Smrg if (data.format == ~0U) 47639413783Smrg goto error; 47739413783Smrg 47839413783Smrg bo->ref_count = 1; 47939413783Smrg 48039413783Smrg data.fd = ihandle; 48139413783Smrg data.width = ppix->drawable.width; 48239413783Smrg data.height = ppix->drawable.height; 48339413783Smrg data.stride = ppix->devKind; 48439413783Smrg 48539413783Smrg if (ppix->drawable.bitsPerPixel == pScrn->bitsPerPixel) 48639413783Smrg bo_use |= GBM_BO_USE_SCANOUT; 48739413783Smrg 48839413783Smrg bo->bo.gbm = gbm_bo_import(info->gbm, GBM_BO_IMPORT_FD, &data, bo_use); 48939413783Smrg if (!bo->bo.gbm) 49039413783Smrg goto error; 49139413783Smrg 49239413783Smrg bo->flags |= RADEON_BO_FLAGS_GBM; 49339413783Smrg 49439413783Smrg if (!radeon_glamor_create_textured_pixmap(ppix, bo)) { 49539413783Smrg radeon_buffer_unref(&bo); 49639413783Smrg return FALSE; 49739413783Smrg } 49839413783Smrg 49939413783Smrg ret = radeon_set_pixmap_bo(ppix, bo); 50039413783Smrg /* radeon_set_pixmap_bo increments ref_count if it succeeds */ 50139413783Smrg radeon_buffer_unref(&bo); 50239413783Smrg return ret; 50339413783Smrg } 50439413783Smrg#endif 50539413783Smrg 50639413783Smrg bo->bo.radeon = radeon_gem_bo_open_prime(info->bufmgr, ihandle, size); 507b338b52fSmrg if (!bo->bo.radeon) 50839413783Smrg goto error; 50939413783Smrg 51039413783Smrg bo->ref_count = 1; 5117314432eSmrg ret = radeon_set_pixmap_bo(ppix, bo); 5127314432eSmrg if (!ret) 5137314432eSmrg goto error; 5140d16fef4Smrg 51539413783Smrg if (surface) { 51639413783Smrg struct radeon_exa_pixmap_priv *driver_priv; 5170d16fef4Smrg uint32_t tiling_flags; 5180d16fef4Smrg 51939413783Smrg driver_priv = exaGetPixmapDriverPrivate(ppix); 52039413783Smrg tiling_flags = driver_priv->tiling_flags; 521de2362d3Smrg 52239413783Smrg if (!radeon_surface_initialize(info, surface, ppix->drawable.width, 52339413783Smrg ppix->drawable.height, 52439413783Smrg ppix->drawable.bitsPerPixel / 8, 52539413783Smrg tiling_flags, 0)) { 5267314432eSmrg ret = FALSE; 5277314432eSmrg goto error; 528de2362d3Smrg } 52939413783Smrg 530de2362d3Smrg /* we have to post hack the surface to reflect the actual size 531de2362d3Smrg of the shared pixmap */ 532de2362d3Smrg surface->level[0].pitch_bytes = ppix->devKind; 533de2362d3Smrg surface->level[0].nblk_x = ppix->devKind / surface->bpe; 534de2362d3Smrg } 535de2362d3Smrg 5367314432eSmrg error: 537de2362d3Smrg close(ihandle); 538de2362d3Smrg /* we have a reference from the alloc and one from set pixmap bo, 539de2362d3Smrg drop one */ 54039413783Smrg radeon_buffer_unref(&bo); 5417314432eSmrg return ret; 542de2362d3Smrg} 543