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