Пример #1
0
static void
setup_hierz_buffer(struct gl_context *ctx)
{
	struct nouveau_channel *chan = context_chan(ctx);
	struct nouveau_grobj *celsius = context_eng3d(ctx);
	struct nouveau_bo_context *bctx = context_bctx(ctx, HIERZ);
	struct gl_framebuffer *fb = ctx->DrawBuffer;
	struct nouveau_framebuffer *nfb = to_nouveau_framebuffer(fb);
	unsigned pitch = align(fb->Width, 128),
		height = align(fb->Height, 2),
		size = pitch * height;

	if (!nfb->hierz.bo || nfb->hierz.bo->size != size) {
		nouveau_bo_ref(NULL, &nfb->hierz.bo);
		nouveau_bo_new_tile(context_dev(ctx), NOUVEAU_BO_VRAM, 0, size,
				    0, NOUVEAU_BO_TILE_ZETA, &nfb->hierz.bo);
	}

	nouveau_bo_markl(bctx, celsius, NV17_3D_HIERZ_OFFSET,
			 nfb->hierz.bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR);

	WAIT_RING(chan, 9);
	BEGIN_RING(chan, celsius, NV17_3D_HIERZ_WINDOW_X, 4);
	OUT_RINGf(chan, - 1792);
	OUT_RINGf(chan, - 2304 + fb->Height);
	OUT_RINGf(chan, fb->_DepthMaxF / 2);
	OUT_RINGf(chan, 0);

	BEGIN_RING(chan, celsius, NV17_3D_HIERZ_PITCH, 1);
	OUT_RING(chan, pitch);

	BEGIN_RING(chan, celsius, NV17_3D_HIERZ_ENABLE, 1);
	OUT_RING(chan, 1);
}
Пример #2
0
struct nouveau_bo *
nouveau_screen_bo_new(struct pipe_screen *pscreen, unsigned alignment,
		      unsigned usage, unsigned bind, unsigned size)
{
	struct nouveau_device *dev = nouveau_screen(pscreen)->device;
	struct nouveau_bo *bo = NULL;
	uint32_t flags = NOUVEAU_BO_MAP, tile_mode = 0, tile_flags = 0;
	int ret;

	if (bind & PIPE_BIND_VERTEX_BUFFER)
		flags |= nouveau_screen(pscreen)->vertex_buffer_flags;
	else if (bind & PIPE_BIND_INDEX_BUFFER)
		flags |= nouveau_screen(pscreen)->index_buffer_flags;

	if (bind & (PIPE_BIND_RENDER_TARGET |
			PIPE_BIND_DEPTH_STENCIL |
			PIPE_BIND_SCANOUT |
			PIPE_BIND_DISPLAY_TARGET |
			PIPE_BIND_SAMPLER_VIEW))
	{
		/* TODO: this may be incorrect or suboptimal */
		if (!(bind & PIPE_BIND_SCANOUT))
			flags |= NOUVEAU_BO_GART;
		if (usage != PIPE_USAGE_DYNAMIC)
			flags |= NOUVEAU_BO_VRAM;

		if (dev->chipset == 0x50 || dev->chipset >= 0x80) {
			if (bind & PIPE_BIND_DEPTH_STENCIL)
				tile_flags = 0x2800;
			else
				tile_flags = 0x7000;
		}
	}

	ret = nouveau_bo_new_tile(dev, flags, alignment, size,
				  tile_mode, tile_flags, &bo);
	if (ret)
		return NULL;

	return bo;
}
Пример #3
0
Bool
nouveau_allocate_surface(ScrnInfoPtr scrn, int width, int height, int bpp,
			 int usage_hint, int *pitch, struct nouveau_bo **bo)
{
	NVPtr pNv = NVPTR(scrn);
	Bool scanout = (usage_hint & NOUVEAU_CREATE_PIXMAP_SCANOUT);
	Bool tiled = (usage_hint & NOUVEAU_CREATE_PIXMAP_TILED);
	int tile_mode = 0, tile_flags = 0;
	int flags = NOUVEAU_BO_MAP | (bpp >= 8 ? NOUVEAU_BO_VRAM : 0);
	int cpp = bpp / 8, ret;

	if (pNv->Architecture >= NV_ARCH_50) {
		if (scanout) {
			if (pNv->tiled_scanout) {
				tiled = TRUE;
				*pitch = NOUVEAU_ALIGN(width * cpp, 64);
			} else {
				*pitch = NOUVEAU_ALIGN(width * cpp, 256);
			}
		} else {
			if (bpp >= 8)
				tiled = TRUE;
			*pitch = NOUVEAU_ALIGN(width * cpp, 64);
		}
	} else {
		if (scanout && pNv->tiled_scanout)
			tiled = TRUE;
		*pitch = NOUVEAU_ALIGN(width * cpp, 64);
	}

	if (tiled) {
		if (pNv->Architecture >= NV_ARCH_C0) {
			if (height > 64)
				tile_mode = 0x40;
			else if (height > 32)
				tile_mode = 0x30;
			else if (height > 16)
				tile_mode = 0x20;
			else if (height > 8)
				tile_mode = 0x10;
			else
				tile_mode = 0x00;

			if (usage_hint & NOUVEAU_CREATE_PIXMAP_ZETA)
				tile_flags = (bpp == 16) ? 0x0100 : 0x1100; /* Z16 : Z24S8 */
			else
				tile_flags = 0xfe00;

			height = NOUVEAU_ALIGN(
				height, NVC0_TILE_HEIGHT(tile_mode));
		} else if (pNv->Architecture >= NV_ARCH_50) {
			if (height > 32)
				tile_mode = 4;
			else if (height > 16)
				tile_mode = 3;
			else if (height > 8)
				tile_mode = 2;
			else if (height > 4)
				tile_mode = 1;
			else
				tile_mode = 0;

			if (usage_hint & NOUVEAU_CREATE_PIXMAP_ZETA)
				tile_flags = (bpp == 16) ? 0x26c00 : 0x22800;
			else if (usage_hint & NOUVEAU_CREATE_PIXMAP_SCANOUT)
				tile_flags = (bpp == 16 ? 0x7000 : 0x7a00);
			else
				tile_flags = 0x7000;

			height = NOUVEAU_ALIGN(height, 1 << (tile_mode + 2));
		} else {
			int pitch_align = max(
				pNv->dev->chipset >= 0x40 ? 1024 : 256,
				round_down_pow2(*pitch / 4));

			tile_mode = *pitch =
				NOUVEAU_ALIGN(*pitch, pitch_align);
		}
	}

	if (bpp == 32)
		tile_flags |= NOUVEAU_BO_TILE_32BPP;
	else if (bpp == 16)
		tile_flags |= NOUVEAU_BO_TILE_16BPP;

	if (usage_hint & NOUVEAU_CREATE_PIXMAP_ZETA)
		tile_flags |= NOUVEAU_BO_TILE_ZETA;

	if (usage_hint & NOUVEAU_CREATE_PIXMAP_SCANOUT)
		tile_flags |= NOUVEAU_BO_TILE_SCANOUT;

	ret = nouveau_bo_new_tile(pNv->dev, flags, 0, *pitch * height,
				  tile_mode, tile_flags, bo);
	if (ret)
		return FALSE;

	return TRUE;
}
Пример #4
0
static struct pipe_texture *
nv50_miptree_create(struct pipe_screen *pscreen, const struct pipe_texture *tmp)
{
	struct nouveau_device *dev = nouveau_screen(pscreen)->device;
	struct nv50_miptree *mt = CALLOC_STRUCT(nv50_miptree);
	struct pipe_texture *pt = &mt->base.base;
	unsigned width = tmp->width0, height = tmp->height0;
	unsigned depth = tmp->depth0, image_alignment;
	uint32_t tile_flags;
	int ret, i, l;

	*pt = *tmp;
	pipe_reference_init(&pt->reference, 1);
	pt->screen = pscreen;

	switch (pt->format) {
	case PIPE_FORMAT_Z32_FLOAT:
		tile_flags = 0x4800;
		break;
	case PIPE_FORMAT_S8Z24_UNORM:
		tile_flags = 0x1800;
		break;
	case PIPE_FORMAT_Z16_UNORM:
		tile_flags = 0x6c00;
		break;
	case PIPE_FORMAT_Z24X8_UNORM:
	case PIPE_FORMAT_Z24S8_UNORM:
		tile_flags = 0x2800;
		break;
	case PIPE_FORMAT_R32G32B32A32_FLOAT:
	case PIPE_FORMAT_R32G32B32_FLOAT:
		tile_flags = 0x7400;
		break;
	default:
		if ((pt->tex_usage & PIPE_TEXTURE_USAGE_PRIMARY) &&
		    util_format_get_blocksizebits(pt->format) == 32)
			tile_flags = 0x7a00;
		else
			tile_flags = 0x7000;
		break;
	}

	/* XXX: texture arrays */
	mt->image_nr = (pt->target == PIPE_TEXTURE_CUBE) ? 6 : 1;

	for (l = 0; l <= pt->last_level; l++) {
		struct nv50_miptree_level *lvl = &mt->level[l];
		unsigned nblocksy = util_format_get_nblocksy(pt->format, height);

		lvl->image_offset = CALLOC(mt->image_nr, sizeof(int));
		lvl->pitch = align(util_format_get_stride(pt->format, width), 64);
		lvl->tile_mode = get_tile_mode(nblocksy, depth);

		width = u_minify(width, 1);
		height = u_minify(height, 1);
		depth = u_minify(depth, 1);
	}

	image_alignment  = get_tile_height(mt->level[0].tile_mode) * 64;
	image_alignment *= get_tile_depth(mt->level[0].tile_mode);

	/* NOTE the distinction between arrays of mip-mapped 2D textures and
	 * mip-mapped 3D textures. We can't use image_nr == depth for 3D mip.
	 */
	for (i = 0; i < mt->image_nr; i++) {
		for (l = 0; l <= pt->last_level; l++) {
			struct nv50_miptree_level *lvl = &mt->level[l];
			int size;
			unsigned tile_h = get_tile_height(lvl->tile_mode);
			unsigned tile_d = get_tile_depth(lvl->tile_mode);

			size  = lvl->pitch;
			size *= align(util_format_get_nblocksy(pt->format, u_minify(pt->height0, l)), tile_h);
			size *= align(u_minify(pt->depth0, l), tile_d);

			lvl->image_offset[i] = mt->total_size;

			mt->total_size += size;
		}
		mt->total_size = align(mt->total_size, image_alignment);
	}

	ret = nouveau_bo_new_tile(dev, NOUVEAU_BO_VRAM, 256, mt->total_size,
				  mt->level[0].tile_mode, tile_flags,
				  &mt->base.bo);
	if (ret) {
		for (l = 0; l <= pt->last_level; ++l)
			FREE(mt->level[l].image_offset);
		FREE(mt);
		return NULL;
	}

	return pt;
}