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