Ejemplo n.º 1
0
static void surf_winsys_to_drm(struct radeon_surface *surf_drm,
                               const struct pipe_resource *tex,
                               unsigned flags, unsigned bpe,
                               enum radeon_surf_mode mode,
                               const struct radeon_surf *surf_ws)
{
    int i;

    memset(surf_drm, 0, sizeof(*surf_drm));

    surf_drm->npix_x = tex->width0;
    surf_drm->npix_y = tex->height0;
    surf_drm->npix_z = tex->depth0;
    surf_drm->blk_w = util_format_get_blockwidth(tex->format);
    surf_drm->blk_h = util_format_get_blockheight(tex->format);
    surf_drm->blk_d = 1;
    surf_drm->array_size = 1;
    surf_drm->last_level = tex->last_level;
    surf_drm->bpe = bpe;
    surf_drm->nsamples = tex->nr_samples ? tex->nr_samples : 1;

    surf_drm->flags = flags;
    surf_drm->flags = RADEON_SURF_CLR(surf_drm->flags, TYPE);
    surf_drm->flags = RADEON_SURF_CLR(surf_drm->flags, MODE);
    surf_drm->flags |= RADEON_SURF_SET(mode, MODE) |
                       RADEON_SURF_HAS_SBUFFER_MIPTREE |
                       RADEON_SURF_HAS_TILE_MODE_INDEX;

    switch (tex->target) {
    case PIPE_TEXTURE_1D:
            surf_drm->flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_1D, TYPE);
            break;
    case PIPE_TEXTURE_RECT:
    case PIPE_TEXTURE_2D:
            surf_drm->flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_2D, TYPE);
            break;
    case PIPE_TEXTURE_3D:
            surf_drm->flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_3D, TYPE);
            break;
    case PIPE_TEXTURE_1D_ARRAY:
            surf_drm->flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_1D_ARRAY, TYPE);
            surf_drm->array_size = tex->array_size;
            break;
    case PIPE_TEXTURE_CUBE_ARRAY: /* cube array layout like 2d array */
            assert(tex->array_size % 6 == 0);
            /* fall through */
    case PIPE_TEXTURE_2D_ARRAY:
            surf_drm->flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_2D_ARRAY, TYPE);
            surf_drm->array_size = tex->array_size;
            break;
    case PIPE_TEXTURE_CUBE:
            surf_drm->flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_CUBEMAP, TYPE);
            break;
    case PIPE_BUFFER:
    default:
            assert(0);
    }

    surf_drm->bo_size = surf_ws->surf_size;
    surf_drm->bo_alignment = surf_ws->surf_alignment;

    surf_drm->bankw = surf_ws->u.legacy.bankw;
    surf_drm->bankh = surf_ws->u.legacy.bankh;
    surf_drm->mtilea = surf_ws->u.legacy.mtilea;
    surf_drm->tile_split = surf_ws->u.legacy.tile_split;

    for (i = 0; i <= surf_drm->last_level; i++) {
        surf_level_winsys_to_drm(&surf_drm->level[i], &surf_ws->u.legacy.level[i],
                                 bpe * surf_drm->nsamples);

        surf_drm->tiling_index[i] = surf_ws->u.legacy.tiling_index[i];
    }

    if (flags & RADEON_SURF_SBUFFER) {
        surf_drm->stencil_tile_split = surf_ws->u.legacy.stencil_tile_split;

        for (i = 0; i <= surf_drm->last_level; i++) {
            surf_level_winsys_to_drm(&surf_drm->stencil_level[i],
                                     &surf_ws->u.legacy.stencil_level[i],
                                     surf_drm->nsamples);
            surf_drm->stencil_tiling_index[i] = surf_ws->u.legacy.stencil_tiling_index[i];
        }
    }
}
Ejemplo n.º 2
0
/* The number of samples can be specified independently of the texture. */
void r600_texture_get_fmask_info(struct r600_common_screen *rscreen,
				 struct r600_texture *rtex,
				 unsigned nr_samples,
				 struct r600_fmask_info *out)
{
	/* FMASK is allocated like an ordinary texture. */
	struct radeon_surf fmask = rtex->surface;

	memset(out, 0, sizeof(*out));

	fmask.bo_alignment = 0;
	fmask.bo_size = 0;
	fmask.nsamples = 1;
	fmask.flags |= RADEON_SURF_FMASK;

	/* Force 2D tiling if it wasn't set. This may occur when creating
	 * FMASK for MSAA resolve on R6xx. On R6xx, the single-sample
	 * destination buffer must have an FMASK too. */
	fmask.flags = RADEON_SURF_CLR(fmask.flags, MODE);
	fmask.flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);

	if (rscreen->chip_class >= SI) {
		fmask.flags |= RADEON_SURF_HAS_TILE_MODE_INDEX;
	}

	switch (nr_samples) {
	case 2:
	case 4:
		fmask.bpe = 1;
		if (rscreen->chip_class <= CAYMAN) {
			fmask.bankh = 4;
		}
		break;
	case 8:
		fmask.bpe = 4;
		break;
	default:
		R600_ERR("Invalid sample count for FMASK allocation.\n");
		return;
	}

	/* Overallocate FMASK on R600-R700 to fix colorbuffer corruption.
	 * This can be fixed by writing a separate FMASK allocator specifically
	 * for R600-R700 asics. */
	if (rscreen->chip_class <= R700) {
		fmask.bpe *= 2;
	}

	if (rscreen->ws->surface_init(rscreen->ws, &fmask)) {
		R600_ERR("Got error in surface_init while allocating FMASK.\n");
		return;
	}

	assert(fmask.level[0].mode == RADEON_SURF_MODE_2D);

	out->slice_tile_max = (fmask.level[0].nblk_x * fmask.level[0].nblk_y) / 64;
	if (out->slice_tile_max)
		out->slice_tile_max -= 1;

	out->tile_mode_index = fmask.tiling_index[0];
	out->pitch = fmask.level[0].nblk_x;
	out->bank_height = fmask.bankh;
	out->alignment = MAX2(256, fmask.bo_alignment);
	out->size = fmask.bo_size;
}
Ejemplo n.º 3
0
/* Calculate appropriate tiling and pitch for a pixmap and allocate a BO that
 * can hold it.
 */
struct radeon_bo*
radeon_alloc_pixmap_bo(ScrnInfoPtr pScrn, int width, int height, int depth,
		       int usage_hint, int bitsPerPixel, int *new_pitch,
		       struct radeon_surface *new_surface, uint32_t *new_tiling)
{
    RADEONInfoPtr info = RADEONPTR(pScrn);
    int pitch, base_align;
    uint32_t size, heighta;
    int cpp = bitsPerPixel / 8;
    uint32_t tiling = 0;
    struct radeon_surface surface;
    struct radeon_bo *bo;
    int domain = RADEON_GEM_DOMAIN_VRAM;
    if (usage_hint) {
	if (info->allowColorTiling) {
	    if (usage_hint & RADEON_CREATE_PIXMAP_TILING_MACRO)
		tiling |= RADEON_TILING_MACRO;
	    if (usage_hint & RADEON_CREATE_PIXMAP_TILING_MICRO)
                tiling |= RADEON_TILING_MICRO;
	}
	if (usage_hint & RADEON_CREATE_PIXMAP_DEPTH)
		tiling |= RADEON_TILING_MACRO | RADEON_TILING_MICRO;

#ifdef CREATE_PIXMAP_USAGE_SHARED
	if ((usage_hint & 0xffff) == CREATE_PIXMAP_USAGE_SHARED) {
		tiling = 0;
		domain = RADEON_GEM_DOMAIN_GTT;
	}
#endif
    }

    /* Small pixmaps must not be macrotiled on R300, hw cannot sample them
     * correctly because samplers automatically switch to macrolinear. */
    if (info->ChipFamily >= CHIP_FAMILY_R300 &&
        info->ChipFamily <= CHIP_FAMILY_RS740 &&
        (tiling & RADEON_TILING_MACRO) &&
        !RADEONMacroSwitch(width, height, bitsPerPixel, tiling,
                           info->ChipFamily >= CHIP_FAMILY_RV350)) {
        tiling &= ~RADEON_TILING_MACRO;
    }

    heighta = RADEON_ALIGN(height, drmmode_get_height_align(pScrn, tiling));
    pitch = RADEON_ALIGN(width, drmmode_get_pitch_align(pScrn, cpp, tiling)) * cpp;
    base_align = drmmode_get_base_align(pScrn, cpp, tiling);
    size = RADEON_ALIGN(heighta * pitch, RADEON_GPU_PAGE_SIZE);
    memset(&surface, 0, sizeof(struct radeon_surface));

    if (info->ChipFamily >= CHIP_FAMILY_R600 && info->surf_man) {
		if (width) {
			surface.npix_x = width;
			/* need to align height to 8 for old kernel */
			surface.npix_y = RADEON_ALIGN(height, 8);
			surface.npix_z = 1;
			surface.blk_w = 1;
			surface.blk_h = 1;
			surface.blk_d = 1;
			surface.array_size = 1;
			surface.last_level = 0;
			surface.bpe = cpp;
			surface.nsamples = 1;
			if (height < 128) {
				/* disable 2d tiling for small surface to work around
				 * the fact that ddx align height to 8 pixel for old
				 * obscure reason i can't remember
				 */
				tiling &= ~RADEON_TILING_MACRO;
			}
			surface.flags = RADEON_SURF_SCANOUT;
			/* we are requiring a recent enough libdrm version */
			surface.flags |= RADEON_SURF_HAS_TILE_MODE_INDEX;
			surface.flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_2D, TYPE);
			surface.flags |= RADEON_SURF_SET(RADEON_SURF_MODE_LINEAR, MODE);
			if ((tiling & RADEON_TILING_MICRO)) {
				surface.flags = RADEON_SURF_CLR(surface.flags, MODE);
				surface.flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
			}
			if ((tiling & RADEON_TILING_MACRO)) {
				surface.flags = RADEON_SURF_CLR(surface.flags, MODE);
				surface.flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
			}
			if (usage_hint & RADEON_CREATE_PIXMAP_SZBUFFER) {
				surface.flags |= RADEON_SURF_ZBUFFER;
				surface.flags |= RADEON_SURF_SBUFFER;
			}
			if (radeon_surface_best(info->surf_man, &surface)) {
				return NULL;
			}
			if (radeon_surface_init(info->surf_man, &surface)) {
				return NULL;
			}
			size = surface.bo_size;
			base_align = surface.bo_alignment;
			pitch = surface.level[0].pitch_bytes;
			tiling = 0;
			switch (surface.level[0].mode) {
			case RADEON_SURF_MODE_2D:
				tiling |= RADEON_TILING_MACRO;
				tiling |= surface.bankw << RADEON_TILING_EG_BANKW_SHIFT;
				tiling |= surface.bankh << RADEON_TILING_EG_BANKH_SHIFT;
				tiling |= surface.mtilea << RADEON_TILING_EG_MACRO_TILE_ASPECT_SHIFT;
				tiling |= eg_tile_split(surface.tile_split) << RADEON_TILING_EG_TILE_SPLIT_SHIFT;
				tiling |= eg_tile_split(surface.stencil_tile_split) << RADEON_TILING_EG_STENCIL_TILE_SPLIT_SHIFT;
				break;
			case RADEON_SURF_MODE_1D:
				tiling |= RADEON_TILING_MICRO;
				break;
			default:
				break;
			}
		}
	}

    bo = radeon_bo_open(info->bufmgr, 0, size, base_align,
			domain, 0);

    if (bo && tiling && radeon_bo_set_tiling(bo, tiling, pitch) == 0)
	*new_tiling = tiling;

    *new_surface = surface;
    *new_pitch = pitch;
    return bo;
}