예제 #1
0
boolean
nv30_draw_arrays(struct pipe_context *pipe,
		 unsigned mode, unsigned start, unsigned count)
{
	struct nv30_context *nv30 = nv30_context(pipe);
	struct nouveau_channel *chan = nv30->screen->base.channel;
	unsigned restart = 0;

	nv30_vbo_set_idxbuf(nv30, NULL, 0);
	if (FORCE_SWTNL || !nv30_state_validate(nv30)) {
		/*return nv30_draw_elements_swtnl(pipe, NULL, 0,
						mode, start, count);*/
		return FALSE;
	}

	while (count) {
		unsigned vc, nr;

		nv30_state_emit(nv30);

		vc = nouveau_vbuf_split(chan->pushbuf->remaining, 6, 256,
					mode, start, count, &restart);
		if (!vc) {
			FIRE_RING(NULL);
			continue;
		}

		BEGIN_RING(rankine, NV34TCL_VERTEX_BEGIN_END, 1);
		OUT_RING  (nvgl_primitive(mode));

		nr = (vc & 0xff);
		if (nr) {
			BEGIN_RING(rankine, NV34TCL_VB_VERTEX_BATCH, 1);
			OUT_RING  (((nr - 1) << 24) | start);
			start += nr;
		}

		nr = vc >> 8;
		while (nr) {
			unsigned push = nr > 2047 ? 2047 : nr;

			nr -= push;

			BEGIN_RING_NI(rankine, NV34TCL_VB_VERTEX_BATCH, push);
			while (push--) {
				OUT_RING(((0x100 - 1) << 24) | start);
				start += 0x100;
			}
		}

		BEGIN_RING(rankine, NV34TCL_VERTEX_BEGIN_END, 1);
		OUT_RING  (0);

		count -= vc;
		start = restart;
	}

	pipe->flush(pipe, 0, NULL);
	return TRUE;
}
예제 #2
0
파일: nv40_vbo.c 프로젝트: toastpp/toastpp
static boolean
nv40_draw_elements_vbo(struct pipe_context *pipe,
		       unsigned mode, unsigned start, unsigned count)
{
	struct nv40_context *nv40 = nv40_context(pipe);
	struct nouveau_channel *chan = nv40->nvws->channel;
	unsigned restart;

	while (count) {
		unsigned nr, vc;

		nv40_state_emit(nv40);

		vc = nouveau_vbuf_split(chan->pushbuf->remaining, 6, 256,
					mode, start, count, &restart);
		if (!vc) {
			FIRE_RING(NULL);
			continue;
		}
		
		BEGIN_RING(curie, NV40TCL_BEGIN_END, 1);
		OUT_RING  (nvgl_primitive(mode));

		nr = (vc & 0xff);
		if (nr) {
			BEGIN_RING(curie, NV40TCL_VB_INDEX_BATCH, 1);
			OUT_RING  (((nr - 1) << 24) | start);
			start += nr;
		}

		nr = vc >> 8;
		while (nr) {
			unsigned push = nr > 2047 ? 2047 : nr;

			nr -= push;

			BEGIN_RING_NI(curie, NV40TCL_VB_INDEX_BATCH, push);
			while (push--) {
				OUT_RING(((0x100 - 1) << 24) | start);
				start += 0x100;
			}
		}

		BEGIN_RING(curie, NV40TCL_BEGIN_END, 1);
		OUT_RING  (0);

		count -= vc;
		start = restart;
	}

	return TRUE;
}
예제 #3
0
파일: nv40_vbo.c 프로젝트: toastpp/toastpp
static INLINE void
nv40_draw_elements_u16(struct nv40_context *nv40, void *ib,
		       unsigned mode, unsigned start, unsigned count)
{
	struct nouveau_channel *chan = nv40->nvws->channel;

	while (count) {
		uint16_t *elts = (uint16_t *)ib + start;
		unsigned vc, push, restart;

		nv40_state_emit(nv40);

		vc = nouveau_vbuf_split(chan->pushbuf->remaining, 6, 2,
					mode, start, count, &restart);
		if (vc == 0) {
			FIRE_RING(NULL);
			continue;
		}
		count -= vc;

		BEGIN_RING(curie, NV40TCL_BEGIN_END, 1);
		OUT_RING  (nvgl_primitive(mode));

		if (vc & 1) {
			BEGIN_RING(curie, NV40TCL_VB_ELEMENT_U32, 1);
			OUT_RING  (elts[0]);
			elts++; vc--;
		}

		while (vc) {
			unsigned i;

			push = MIN2(vc, 2047 * 2);

			BEGIN_RING_NI(curie, NV40TCL_VB_ELEMENT_U16, push >> 1);
			for (i = 0; i < push; i+=2)
				OUT_RING((elts[i+1] << 16) | elts[i]);

			vc -= push;
			elts += push;
		}

		BEGIN_RING(curie, NV40TCL_BEGIN_END, 1);
		OUT_RING  (0);

		start = restart;
	}
}
예제 #4
0
파일: nv40_vbo.c 프로젝트: toastpp/toastpp
static INLINE void
nv40_draw_elements_u32(struct nv40_context *nv40, void *ib,
		       unsigned mode, unsigned start, unsigned count)
{
	struct nouveau_channel *chan = nv40->nvws->channel;

	while (count) {
		uint32_t *elts = (uint32_t *)ib + start;
		unsigned vc, push, restart;

		nv40_state_emit(nv40);

		vc = nouveau_vbuf_split(chan->pushbuf->remaining, 5, 1,
					mode, start, count, &restart);
		if (vc == 0) {
			FIRE_RING(NULL);
			continue;
		}
		count -= vc;

		BEGIN_RING(curie, NV40TCL_BEGIN_END, 1);
		OUT_RING  (nvgl_primitive(mode));

		while (vc) {
			push = MIN2(vc, 2047);

			BEGIN_RING_NI(curie, NV40TCL_VB_ELEMENT_U32, push);
			OUT_RINGp    (elts, push);

			vc -= push;
			elts += push;
		}

		BEGIN_RING(curie, NV40TCL_BEGIN_END, 1);
		OUT_RING  (0);

		start = restart;
	}
}
예제 #5
0
void
nvfx_push_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
{
	struct nvfx_context *nvfx = nvfx_context(pipe);
	struct nouveau_channel *chan = nvfx->screen->base.channel;
	struct push_context ctx;
	struct util_split_prim s;
	unsigned instances_left = info->instance_count;
	int vtx_value;
	unsigned hw_mode = nvgl_primitive(info->mode);
	int i;
	struct
	{
		uint8_t* map;
		unsigned step;
	} per_instance[16];
	unsigned p_overhead = 64 /* magic fix */
			+ 4 /* begin/end */
			+ 4; /* potential edgeflag enable/disable */

	ctx.chan = nvfx->screen->base.channel;
	ctx.translate = nvfx->vtxelt->translate;
	ctx.idxbuf = NULL;
	ctx.vertex_length = nvfx->vtxelt->vertex_length;
	ctx.max_vertices_per_packet = nvfx->vtxelt->max_vertices_per_packet;
	ctx.edgeflag = 0.5f;
	// TODO: figure out if we really want to handle this, and do so in that case
	ctx.edgeflag_attr = 0xff; // nvfx->vertprog->cfg.edgeflag_in;

	if(!nvfx->use_vertex_buffers)
	{
		for(i = 0; i < nvfx->vtxelt->num_per_vertex_buffer_infos; ++i)
		{
			struct nvfx_per_vertex_buffer_info* vbi = &nvfx->vtxelt->per_vertex_buffer_info[i];
			struct pipe_vertex_buffer *vb = &nvfx->vtxbuf[vbi->vertex_buffer_index];
			uint8_t* data = nvfx_buffer(vb->buffer)->data + vb->buffer_offset;
			if(info->indexed)
				data += info->index_bias * vb->stride;
			ctx.translate->set_buffer(ctx.translate, i, data, vb->stride, ~0);
		}

		if(ctx.edgeflag_attr < 16)
			vtx_value = -(ctx.vertex_length + 3);  /* vertex data and edgeflag header and value */
		else
		{
			p_overhead += 1; /* initial vertex_data header */
			vtx_value = -ctx.vertex_length;  /* vertex data and edgeflag header and value */
		}

		if (info->indexed) {
			// XXX: this case and is broken and probably need a new VTX_ATTR push path
			if (nvfx->idxbuf.index_size == 1)
				s.emit = emit_vertices_lookup8;
			else if (nvfx->idxbuf.index_size == 2)
				s.emit = emit_vertices_lookup16;
			else
				s.emit = emit_vertices_lookup32;
		} else
			s.emit = emit_vertices;
	}
	else
	{
		if(!info->indexed || nvfx->use_index_buffer)
		{
			s.emit = info->indexed ? emit_ib_ranges : emit_vb_ranges;
			p_overhead += 3;
			vtx_value = 0;
		}
		else if (nvfx->idxbuf.index_size == 4)
		{
			s.emit = emit_elt32;
			p_overhead += 1;
			vtx_value = 8;
		}
		else
		{
			s.emit = (nvfx->idxbuf.index_size == 2) ? emit_elt16 : emit_elt8;
			p_overhead += 3;
			vtx_value = 7;
		}
	}

	ctx.idxbias = info->index_bias;
	if(nvfx->use_vertex_buffers)
		ctx.idxbias -= nvfx->base_vertex;

	/* map index buffer, if present */
	if (info->indexed && !nvfx->use_index_buffer)
		ctx.idxbuf = nvfx_buffer(nvfx->idxbuf.buffer)->data + nvfx->idxbuf.offset;

	s.priv = &ctx;
	s.edge = emit_edgeflag;

	for (i = 0; i < nvfx->vtxelt->num_per_instance; ++i)
	{
		struct nvfx_per_instance_element *ve = &nvfx->vtxelt->per_instance[i];
		struct pipe_vertex_buffer *vb = &nvfx->vtxbuf[ve->base.vertex_buffer_index];
		float v[4];
		per_instance[i].step = info->start_instance % ve->instance_divisor;
		per_instance[i].map = nvfx_buffer(vb->buffer)->data + vb->buffer_offset + ve->base.src_offset;

		nvfx->vtxelt->per_instance[i].base.fetch_rgba_float(v, per_instance[i].map, 0, 0);

		WAIT_RING(chan, 5);
		nvfx_emit_vtx_attr(chan, nvfx->vtxelt->per_instance[i].base.idx, v, nvfx->vtxelt->per_instance[i].base.ncomp);
	}

	/* per-instance loop */
	while (instances_left--) {
		int max_verts;
		boolean done;

		util_split_prim_init(&s, info->mode, info->start, info->count);
		nvfx_state_emit(nvfx);
		for(;;) {
			max_verts  = AVAIL_RING(chan);
			max_verts -= p_overhead;

			/* if vtx_value < 0, each vertex is -vtx_value words long
			 * otherwise, each vertex is 2^(vtx_value) / 255 words long (this is an approximation)
			 */
			if(vtx_value < 0)
			{
				max_verts /= -vtx_value;
				max_verts -= (max_verts >> 10); /* vertex data headers */
			}
			else
			{
				if(max_verts >= (1 << 23)) /* avoid overflow here */
					max_verts = (1 << 23);
				max_verts = (max_verts * 255) >> vtx_value;
			}

			//printf("avail %u max_verts %u\n", AVAIL_RING(chan), max_verts);

			if(max_verts >= 16)
			{
				/* XXX: any command a lot of times seems to (mostly) fix corruption that would otherwise happen */
				/* this seems to cause issues on nv3x, and also be unneeded there */
				if(nvfx->is_nv4x)
				{
					int i;
					for(i = 0; i < 32; ++i)
					{
						OUT_RING(chan, RING_3D(0x1dac, 1));
						OUT_RING(chan, 0);
					}
				}

				OUT_RING(chan, RING_3D(NV30_3D_VERTEX_BEGIN_END, 1));
				OUT_RING(chan, hw_mode);
				done = util_split_prim_next(&s, max_verts);
				OUT_RING(chan, RING_3D(NV30_3D_VERTEX_BEGIN_END, 1));
				OUT_RING(chan, 0);

				if(done)
					break;
			}

			FIRE_RING(chan);
			nvfx_state_emit(nvfx);
		}