Example #1
0
static int
nv50_validate_textures(struct nv50_context *nv50, struct nouveau_stateobj *so,
		       unsigned p)
{
	struct nouveau_grobj *eng2d = nv50->screen->eng2d;
	struct nouveau_grobj *tesla = nv50->screen->tesla;
	unsigned unit, j;

	const unsigned rll = NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_LOW;
	const unsigned rlh = NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_HIGH
		| NOUVEAU_BO_OR;

	nv50_so_init_sifc(nv50, so, nv50->screen->tic, NOUVEAU_BO_VRAM,
			  p * (32 * 8 * 4), nv50->sampler_view_nr[p] * 8 * 4);

	for (unit = 0; unit < nv50->sampler_view_nr[p]; ++unit) {
		struct nv50_sampler_view *view =
			nv50_sampler_view(nv50->sampler_views[p][unit]);

		so_method(so, eng2d, NV50_2D_SIFC_DATA | (2 << 29), 8);
		if (view) {
			uint32_t tic2 = view->tic[2];
			struct nv50_miptree *mt =
				nv50_miptree(view->pipe.texture);

			tic2 &= ~NV50TIC_0_2_NORMALIZED_COORDS;
			if (nv50->sampler[p][unit]->normalized)
				tic2 |= NV50TIC_0_2_NORMALIZED_COORDS;
			view->tic[2] = tic2;

			so_data  (so, view->tic[0]);
			so_reloc (so, mt->base.bo, 0, rll, 0, 0);
			so_reloc (so, mt->base.bo, 0, rlh, tic2, tic2);
			so_datap (so, &view->tic[3], 5);

			/* Set TEX insn $t src binding $unit in program type p
			 * to TIC, TSC entry (32 * p + unit), mark valid (1).
			 */
			so_method(so, tesla, NV50TCL_BIND_TIC(p), 1);
			so_data  (so, ((32 * p + unit) << 9) | (unit << 1) | 1);
		} else {
			for (j = 0; j < 8; ++j)
				so_data(so, 0);
			so_method(so, tesla, NV50TCL_BIND_TIC(p), 1);
			so_data  (so, (unit << 1) | 0);
		}
	}

	for (; unit < nv50->state.sampler_view_nr[p]; unit++) {
		/* Make other bindings invalid. */
		so_method(so, tesla, NV50TCL_BIND_TIC(p), 1);
		so_data  (so, (unit << 1) | 0);
	}

	nv50->state.sampler_view_nr[p] = nv50->sampler_view_nr[p];
	return TRUE;
}
Example #2
0
static int
nv50_tex_construct(struct nv50_context *nv50, struct nouveau_stateobj *so,
		   struct nv50_miptree *mt, int unit, unsigned p)
{
	unsigned i;
	uint32_t mode;
	const struct util_format_description *desc;

	for (i = 0; i < NV50_TEX_FORMAT_LIST_SIZE; i++)
		if (nv50_tex_format_list[i].pf == mt->base.base.format)
			break;
	if (i == NV50_TEX_FORMAT_LIST_SIZE)
                return 1;

	if (nv50->sampler[p][unit]->normalized)
		mode = 0x50001000 | (1 << 31);
	else {
		mode = 0x50001000 | (7 << 14);
		assert(mt->base.base.target == PIPE_TEXTURE_2D);
	}

	mode |= ((mt->base.bo->tile_mode & 0x0f) << 22) |
		((mt->base.bo->tile_mode & 0xf0) << 21);

	desc = util_format_description(mt->base.base.format);
	assert(desc);

	if (desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB)
		mode |= 0x0400;

	switch (mt->base.base.target) {
	case PIPE_TEXTURE_1D:
		break;
	case PIPE_TEXTURE_2D:
		mode |= (1 << 14);
		break;
	case PIPE_TEXTURE_3D:
		mode |= (2 << 14);
		break;
	case PIPE_TEXTURE_CUBE:
		mode |= (3 << 14);
		break;
	default:
		assert(!"unsupported texture target");
		break;
	}

	so_data (so, nv50_tex_format_list[i].hw);
	so_reloc(so, mt->base.bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_LOW |
		 NOUVEAU_BO_RD, 0, 0);
	so_data (so, mode);
	so_data (so, 0x00300000);
	so_data (so, mt->base.base.width0 | (1 << 31));
	so_data (so, (mt->base.base.last_level << 28) |
		 (mt->base.base.depth0 << 16) | mt->base.base.height0);
	so_data (so, 0x03000000);
	so_data (so, mt->base.base.last_level << 4);

	return 0;
}
Example #3
0
static boolean
nv40_vbo_validate(struct nv40_context *nv40)
{
	struct nouveau_stateobj *vtxbuf, *vtxfmt, *sattr = NULL;
	struct nouveau_grobj *curie = nv40->screen->curie;
	struct pipe_buffer *ib = nv40->idxbuf;
	unsigned ib_format = nv40->idxbuf_format;
	unsigned vb_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD;
	int hw;

	if (nv40->edgeflags) {
		nv40->fallback_swtnl |= NV40_NEW_ARRAYS;
		return FALSE;
	}

	vtxbuf = so_new(20, 18);
	so_method(vtxbuf, curie, NV40TCL_VTXBUF_ADDRESS(0), nv40->vtxelt_nr);
	vtxfmt = so_new(17, 0);
	so_method(vtxfmt, curie, NV40TCL_VTXFMT(0), nv40->vtxelt_nr);

	for (hw = 0; hw < nv40->vtxelt_nr; hw++) {
		struct pipe_vertex_element *ve;
		struct pipe_vertex_buffer *vb;
		unsigned type, ncomp;

		ve = &nv40->vtxelt[hw];
		vb = &nv40->vtxbuf[ve->vertex_buffer_index];

		if (!vb->stride) {
			if (!sattr)
				sattr = so_new(16 * 5, 0);

			if (nv40_vbo_static_attrib(nv40, sattr, hw, ve, vb)) {
				so_data(vtxbuf, 0);
				so_data(vtxfmt, NV40TCL_VTXFMT_TYPE_FLOAT);
				continue;
			}
		}

		if (nv40_vbo_format_to_hw(ve->src_format, &type, &ncomp)) {
			nv40->fallback_swtnl |= NV40_NEW_ARRAYS;
			so_ref(NULL, &vtxbuf);
			so_ref(NULL, &vtxfmt);
			return FALSE;
		}

		so_reloc(vtxbuf, vb->buffer, vb->buffer_offset + ve->src_offset,
			 vb_flags | NOUVEAU_BO_LOW | NOUVEAU_BO_OR,
			 0, NV40TCL_VTXBUF_ADDRESS_DMA1);
		so_data (vtxfmt, ((vb->stride << NV40TCL_VTXFMT_STRIDE_SHIFT) |
				  (ncomp << NV40TCL_VTXFMT_SIZE_SHIFT) | type));
	}

	if (ib) {
		so_method(vtxbuf, curie, NV40TCL_IDXBUF_ADDRESS, 2);
		so_reloc (vtxbuf, ib, 0, vb_flags | NOUVEAU_BO_LOW, 0, 0);
		so_reloc (vtxbuf, ib, ib_format, vb_flags | NOUVEAU_BO_OR,
			  0, NV40TCL_IDXBUF_FORMAT_DMA1);
	}

	so_method(vtxbuf, curie, 0x1710, 1);
	so_data  (vtxbuf, 0);

	so_ref(vtxbuf, &nv40->state.hw[NV40_STATE_VTXBUF]);
	so_ref(NULL, &vtxbuf);
	nv40->state.dirty |= (1ULL << NV40_STATE_VTXBUF);
	so_ref(vtxfmt, &nv40->state.hw[NV40_STATE_VTXFMT]);
	so_ref(NULL, &vtxfmt);
	nv40->state.dirty |= (1ULL << NV40_STATE_VTXFMT);
	so_ref(sattr, &nv40->state.hw[NV40_STATE_VTXATTR]);
	so_ref(NULL, &sattr);
	nv40->state.dirty |= (1ULL << NV40_STATE_VTXATTR);
	return FALSE;
}
Example #4
0
struct pipe_screen *
nv50_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev)
{
	struct nv50_screen *screen = CALLOC_STRUCT(nv50_screen);
	struct nouveau_channel *chan;
	struct pipe_screen *pscreen;
	struct nouveau_stateobj *so;
	unsigned chipset = dev->chipset;
	unsigned tesla_class = 0;
	int ret, i;

	if (!screen)
		return NULL;
	pscreen = &screen->base.base;

	ret = nouveau_screen_init(&screen->base, dev);
	if (ret) {
		nv50_screen_destroy(pscreen);
		return NULL;
	}
	chan = screen->base.channel;

	pscreen->winsys = ws;
	pscreen->destroy = nv50_screen_destroy;
	pscreen->get_param = nv50_screen_get_param;
	pscreen->get_paramf = nv50_screen_get_paramf;
	pscreen->is_format_supported = nv50_screen_is_format_supported;
	pscreen->context_create = nv50_create;
	screen->base.pre_pipebuffer_map_callback = nv50_pre_pipebuffer_map;

	nv50_screen_init_miptree_functions(pscreen);
	nv50_transfer_init_screen_functions(pscreen);

	/* DMA engine object */
	ret = nouveau_grobj_alloc(chan, 0xbeef5039,
		NV50_MEMORY_TO_MEMORY_FORMAT, &screen->m2mf);
	if (ret) {
		NOUVEAU_ERR("Error creating M2MF object: %d\n", ret);
		nv50_screen_destroy(pscreen);
		return NULL;
	}

	/* 2D object */
	ret = nouveau_grobj_alloc(chan, 0xbeef502d, NV50_2D, &screen->eng2d);
	if (ret) {
		NOUVEAU_ERR("Error creating 2D object: %d\n", ret);
		nv50_screen_destroy(pscreen);
		return NULL;
	}

	/* 3D object */
	switch (chipset & 0xf0) {
	case 0x50:
		tesla_class = NV50TCL;
		break;
	case 0x80:
	case 0x90:
		tesla_class = NV84TCL;
		break;
	case 0xa0:
		switch (chipset) {
		case 0xa0:
		case 0xaa:
		case 0xac:
			tesla_class = NVA0TCL;
			break;
		default:
			tesla_class = NVA8TCL;
			break;
		}
		break;
	default:
		NOUVEAU_ERR("Not a known NV50 chipset: NV%02x\n", chipset);
		nv50_screen_destroy(pscreen);
		return NULL;
	}

	ret = nouveau_grobj_alloc(chan, 0xbeef5097, tesla_class,
		&screen->tesla);
	if (ret) {
		NOUVEAU_ERR("Error creating 3D object: %d\n", ret);
		nv50_screen_destroy(pscreen);
		return NULL;
	}

	/* Sync notifier */
	ret = nouveau_notifier_alloc(chan, 0xbeef0301, 1, &screen->sync);
	if (ret) {
		NOUVEAU_ERR("Error creating notifier object: %d\n", ret);
		nv50_screen_destroy(pscreen);
		return NULL;
	}

	/* Static M2MF init */
	so = so_new(1, 3, 0);
	so_method(so, screen->m2mf, NV04_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 3);
	so_data  (so, screen->sync->handle);
	so_data  (so, chan->vram->handle);
	so_data  (so, chan->vram->handle);
	so_emit(chan, so);
	so_ref (NULL, &so);

	/* Static 2D init */
	so = so_new(4, 7, 0);
	so_method(so, screen->eng2d, NV50_2D_DMA_NOTIFY, 4);
	so_data  (so, screen->sync->handle);
	so_data  (so, chan->vram->handle);
	so_data  (so, chan->vram->handle);
	so_data  (so, chan->vram->handle);
	so_method(so, screen->eng2d, NV50_2D_OPERATION, 1);
	so_data  (so, NV50_2D_OPERATION_SRCCOPY);
	so_method(so, screen->eng2d, NV50_2D_CLIP_ENABLE, 1);
	so_data  (so, 0);
	so_method(so, screen->eng2d, 0x0888, 1);
	so_data  (so, 1);
	so_emit(chan, so);
	so_ref(NULL, &so);

	/* Static tesla init */
	so = so_new(47, 95, 24);

	so_method(so, screen->tesla, NV50TCL_COND_MODE, 1);
	so_data  (so, NV50TCL_COND_MODE_ALWAYS);
	so_method(so, screen->tesla, NV50TCL_DMA_NOTIFY, 1);
	so_data  (so, screen->sync->handle);
	so_method(so, screen->tesla, NV50TCL_DMA_ZETA, 11);
	for (i = 0; i < 11; i++)
		so_data(so, chan->vram->handle);
	so_method(so, screen->tesla, NV50TCL_DMA_COLOR(0),
				     NV50TCL_DMA_COLOR__SIZE);
	for (i = 0; i < NV50TCL_DMA_COLOR__SIZE; i++)
		so_data(so, chan->vram->handle);
	so_method(so, screen->tesla, NV50TCL_RT_CONTROL, 1);
	so_data  (so, 1);

	/* activate all 32 lanes (threads) in a warp */
	so_method(so, screen->tesla, NV50TCL_WARP_HALVES, 1);
	so_data  (so, 0x2);
	so_method(so, screen->tesla, 0x1400, 1);
	so_data  (so, 0xf);

	/* max TIC (bits 4:8) & TSC (ignored) bindings, per program type */
	for (i = 0; i < 3; ++i) {
		so_method(so, screen->tesla, NV50TCL_TEX_LIMITS(i), 1);
		so_data  (so, 0x54);
	}

	/* origin is top left (set to 1 for bottom left) */
	so_method(so, screen->tesla, NV50TCL_Y_ORIGIN_BOTTOM, 1);
	so_data  (so, 0);
	so_method(so, screen->tesla, NV50TCL_VP_REG_ALLOC_RESULT, 1);
	so_data  (so, 8);

	/* constant buffers for immediates and VP/FP parameters */
	ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 0, (32 * 4) * 4,
			     &screen->constbuf_misc[0]);
	if (ret) {
		nv50_screen_destroy(pscreen);
		return NULL;
	}

	for (i = 0; i < 3; i++) {
		ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 0, (256 * 4) * 4,
				     &screen->constbuf_parm[i]);
		if (ret) {
			nv50_screen_destroy(pscreen);
			return NULL;
		}
	}

	if (nouveau_resource_init(&screen->immd_heap[0], 0, 128) ||
	    nouveau_resource_init(&screen->parm_heap[0], 0, 512) ||
	    nouveau_resource_init(&screen->parm_heap[1], 0, 512))
	{
		NOUVEAU_ERR("Error initialising constant buffers.\n");
		nv50_screen_destroy(pscreen);
		return NULL;
	}

	/*
	// map constant buffers:
	//  B = buffer ID (maybe more than 1 byte)
	//  N = CB index used in shader instruction
	//  P = program type (0 = VP, 2 = GP, 3 = FP)
	so_method(so, screen->tesla, NV50TCL_SET_PROGRAM_CB, 1);
	so_data  (so, 0x000BBNP1);
	*/

	so_method(so, screen->tesla, NV50TCL_CB_DEF_ADDRESS_HIGH, 3);
	so_reloc (so, screen->constbuf_misc[0], 0, NOUVEAU_BO_VRAM |
		  NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0);
	so_reloc (so, screen->constbuf_misc[0], 0, NOUVEAU_BO_VRAM |
		  NOUVEAU_BO_RD | NOUVEAU_BO_LOW, 0, 0);
	so_data  (so, (NV50_CB_PMISC << 16) | 0x00000200);
	so_method(so, screen->tesla, NV50TCL_SET_PROGRAM_CB, 1);
	so_data  (so, 0x00000001 | (NV50_CB_PMISC << 12));
	so_method(so, screen->tesla, NV50TCL_SET_PROGRAM_CB, 1);
	so_data  (so, 0x00000021 | (NV50_CB_PMISC << 12));
	so_method(so, screen->tesla, NV50TCL_SET_PROGRAM_CB, 1);
	so_data  (so, 0x00000031 | (NV50_CB_PMISC << 12));

	/* bind auxiliary constbuf to immediate data bo */
	so_method(so, screen->tesla, NV50TCL_CB_DEF_ADDRESS_HIGH, 3);
	so_reloc (so, screen->constbuf_misc[0], (128 * 4) * 4,
		  NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0);
	so_reloc (so, screen->constbuf_misc[0], (128 * 4) * 4,
		  NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_LOW, 0, 0);
	so_data  (so, (NV50_CB_AUX << 16) | 0x00000200);
	so_method(so, screen->tesla, NV50TCL_SET_PROGRAM_CB, 1);
	so_data  (so, 0x00000201 | (NV50_CB_AUX << 12));
	so_method(so, screen->tesla, NV50TCL_SET_PROGRAM_CB, 1);
	so_data  (so, 0x00000221 | (NV50_CB_AUX << 12));

	so_method(so, screen->tesla, NV50TCL_CB_DEF_ADDRESS_HIGH, 3);
	so_reloc (so, screen->constbuf_parm[PIPE_SHADER_VERTEX], 0,
		  NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0);
	so_reloc (so, screen->constbuf_parm[PIPE_SHADER_VERTEX], 0,
		  NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_LOW, 0, 0);
	so_data  (so, (NV50_CB_PVP << 16) | 0x00000800);
	so_method(so, screen->tesla, NV50TCL_SET_PROGRAM_CB, 1);
	so_data  (so, 0x00000101 | (NV50_CB_PVP << 12));

	so_method(so, screen->tesla, NV50TCL_CB_DEF_ADDRESS_HIGH, 3);
	so_reloc (so, screen->constbuf_parm[PIPE_SHADER_GEOMETRY], 0,
		  NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0);
	so_reloc (so, screen->constbuf_parm[PIPE_SHADER_GEOMETRY], 0,
		  NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_LOW, 0, 0);
	so_data  (so, (NV50_CB_PGP << 16) | 0x00000800);
	so_method(so, screen->tesla, NV50TCL_SET_PROGRAM_CB, 1);
	so_data  (so, 0x00000121 | (NV50_CB_PGP << 12));

	so_method(so, screen->tesla, NV50TCL_CB_DEF_ADDRESS_HIGH, 3);
	so_reloc (so, screen->constbuf_parm[PIPE_SHADER_FRAGMENT], 0,
		  NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0);
	so_reloc (so, screen->constbuf_parm[PIPE_SHADER_FRAGMENT], 0,
		  NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_LOW, 0, 0);
	so_data  (so, (NV50_CB_PFP << 16) | 0x00000800);
	so_method(so, screen->tesla, NV50TCL_SET_PROGRAM_CB, 1);
	so_data  (so, 0x00000131 | (NV50_CB_PFP << 12));

	ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 0, PIPE_SHADER_TYPES*32*32,
			     &screen->tic);
	if (ret) {
		nv50_screen_destroy(pscreen);
		return NULL;
	}

	so_method(so, screen->tesla, NV50TCL_TIC_ADDRESS_HIGH, 3);
	so_reloc (so, screen->tic, 0, NOUVEAU_BO_VRAM |
		  NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0);
	so_reloc (so, screen->tic, 0, NOUVEAU_BO_VRAM |
		  NOUVEAU_BO_RD | NOUVEAU_BO_LOW, 0, 0);
	so_data  (so, PIPE_SHADER_TYPES * 32 - 1);

	ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 0, PIPE_SHADER_TYPES*32*32,
			     &screen->tsc);
	if (ret) {
		nv50_screen_destroy(pscreen);
		return NULL;
	}

	so_method(so, screen->tesla, NV50TCL_TSC_ADDRESS_HIGH, 3);
	so_reloc (so, screen->tsc, 0, NOUVEAU_BO_VRAM |
		  NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0);
	so_reloc (so, screen->tsc, 0, NOUVEAU_BO_VRAM |
		  NOUVEAU_BO_RD | NOUVEAU_BO_LOW, 0, 0);
	so_data  (so, 0x00000000); /* ignored if TSC_LINKED (0x1234) = 1 */


	/* Vertex array limits - max them out */
	for (i = 0; i < 16; i++) {
		so_method(so, screen->tesla, NV50TCL_VERTEX_ARRAY_LIMIT_HIGH(i), 2);
		so_data  (so, 0x000000ff);
		so_data  (so, 0xffffffff);
	}

	so_method(so, screen->tesla, NV50TCL_DEPTH_RANGE_NEAR(0), 2);
	so_data  (so, fui(0.0));
	so_data  (so, fui(1.0));

	/* no dynamic combination of TIC & TSC entries => only BIND_TIC used */
	so_method(so, screen->tesla, NV50TCL_LINKED_TSC, 1);
	so_data  (so, 1);

	/* activate first scissor rectangle */
	so_method(so, screen->tesla, NV50TCL_SCISSOR_ENABLE(0), 1);
	so_data  (so, 1);

	so_method(so, screen->tesla, NV50TCL_EDGEFLAG_ENABLE, 1);
	so_data  (so, 1); /* default edgeflag to TRUE */

	so_emit(chan, so);
	so_ref (so, &screen->static_init);
	so_ref (NULL, &so);
	nouveau_pushbuf_flush(chan, 0);

	return pscreen;
}