static void
nvfx_render_flush(struct draw_stage *stage, unsigned flags)
{
	struct nvfx_render_stage *rs = nvfx_render_stage(stage);
	struct nvfx_context *nvfx = rs->nvfx;
	struct nouveau_channel *chan = nvfx->screen->base.channel;

	if (rs->prim != NV30_3D_VERTEX_BEGIN_END_STOP) {
		assert(AVAIL_RING(chan) >= 2);
		OUT_RING(chan, RING_3D(NV30_3D_VERTEX_BEGIN_END, 1));
		OUT_RING(chan, NV30_3D_VERTEX_BEGIN_END_STOP);
		rs->prim = NV30_3D_VERTEX_BEGIN_END_STOP;
	}
}
Exemple #2
0
static void
nvfx_render_flush(struct draw_stage *stage, unsigned flags)
{
	struct nvfx_render_stage *rs = nvfx_render_stage(stage);
	struct nvfx_context *nvfx = rs->nvfx;
	struct nouveau_channel *chan = nvfx->screen->base.channel;
	struct nouveau_grobj *eng3d = nvfx->screen->eng3d;

	if (rs->prim != NV30_3D_VERTEX_BEGIN_END_STOP) {
		BEGIN_RING(chan, eng3d, NV30_3D_VERTEX_BEGIN_END, 1);
		OUT_RING(chan, NV30_3D_VERTEX_BEGIN_END_STOP);
		rs->prim = NV30_3D_VERTEX_BEGIN_END_STOP;
	}
}
static INLINE void
nvfx_render_prim(struct draw_stage *stage, struct prim_header *prim,
	       unsigned mode, unsigned count)
{
	struct nvfx_render_stage *rs = nvfx_render_stage(stage);
	struct nvfx_context *nvfx = rs->nvfx;

	struct nvfx_screen *screen = nvfx->screen;
	struct nouveau_channel *chan = screen->base.channel;
	boolean no_elements = nvfx->vertprog->draw_no_elements;
	unsigned num_attribs = nvfx->vertprog->draw_elements;

	/* we need to account the flush as well here even if it is done afterthis
	 * function
	 */
	if (AVAIL_RING(chan) < ((1 + count * num_attribs * 4) + 6 + 64)) {
		nvfx_render_flush(stage, 0);
		FIRE_RING(chan);
		nvfx_state_emit(nvfx);

		assert(AVAIL_RING(chan) >= ((1 + count * num_attribs * 4) + 6 + 64));
	}

	/* Switch primitive modes if necessary */
	if (rs->prim != mode) {
		if (rs->prim != NV30_3D_VERTEX_BEGIN_END_STOP) {
			OUT_RING(chan, RING_3D(NV30_3D_VERTEX_BEGIN_END, 1));
			OUT_RING(chan, NV30_3D_VERTEX_BEGIN_END_STOP);
		}

		/* 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, mode);
		rs->prim = mode;
	}

	OUT_RING(chan, RING_3D_NI(NV30_3D_VERTEX_DATA, num_attribs * 4 * count));
	if(no_elements) {
		OUT_RING(chan, 0);
		OUT_RING(chan, 0);
		OUT_RING(chan, 0);
		OUT_RING(chan, 0);
	} else {
		for (unsigned i = 0; i < count; ++i)
		{
			struct vertex_header* v = prim->v[i];
			/* TODO: disable divide where it's causing the problem, and remove this hack */
			OUT_RING(chan, fui(v->data[0][0] / v->data[0][3]));
			OUT_RING(chan, fui(v->data[0][1] / v->data[0][3]));
			OUT_RING(chan, fui(v->data[0][2] / v->data[0][3]));
			OUT_RING(chan, fui(1.0f / v->data[0][3]));
			OUT_RINGp(chan, &v->data[1][0], 4 * (num_attribs - 1));
		}
	}
}