From 2f33b5b56e9221f2613b34cd1a1a9d82d5ed4303 Mon Sep 17 00:00:00 2001
From: Ben Skeggs <skeggsb@gmail.com>
Date: Sun, 18 Nov 2007 17:08:06 +1100
Subject: nouveau: Very rough cut at gallium winsys + nv40 pipe driver.

---
 src/mesa/pipe/nv40/nv40_vbo.c | 222 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 222 insertions(+)
 create mode 100644 src/mesa/pipe/nv40/nv40_vbo.c

(limited to 'src/mesa/pipe/nv40/nv40_vbo.c')

diff --git a/src/mesa/pipe/nv40/nv40_vbo.c b/src/mesa/pipe/nv40/nv40_vbo.c
new file mode 100644
index 0000000000..aa930476b6
--- /dev/null
+++ b/src/mesa/pipe/nv40/nv40_vbo.c
@@ -0,0 +1,222 @@
+#include "pipe/p_context.h"
+#include "pipe/p_state.h"
+#include "pipe/p_util.h"
+
+#include "nv40_context.h"
+#include "nv40_dma.h"
+#include "nv40_state.h"
+#include "nvgl_pipe.h"
+
+boolean
+nv40_draw_arrays(struct pipe_context *pipe, unsigned mode, unsigned start,
+		 unsigned count)
+{
+	struct nv40_context *nv40 = (struct nv40_context *)pipe;
+	unsigned nr;
+
+	if (nv40->dirty)
+		nv40_emit_hw_state(nv40);
+
+	BEGIN_RING(curie, NV40TCL_BEGIN_END, 1);
+	OUT_RING  (nvgl_primitive(mode));
+
+	nr = (count & 0xff);
+	if (nr) {
+		BEGIN_RING(curie, NV40TCL_VB_VERTEX_BATCH, 1);
+		OUT_RING  (((nr - 1) << 24) | start);
+		start += nr;
+	}
+
+	/*XXX: large arrays (nr>2047) will blow up */
+	nr = count >> 8;
+	if (nr) {
+		assert (nr <= 2047);
+
+		BEGIN_RING_NI(curie, NV40TCL_VB_VERTEX_BATCH, nr);
+		while (nr--) {
+			OUT_RING(((0x100 - 1) << 24) | start);
+			start += 0x100;
+		}
+	}
+
+	BEGIN_RING(curie, NV40TCL_BEGIN_END, 1);
+	OUT_RING  (0);
+
+	pipe->flush(pipe, PIPE_FLUSH_WAIT);
+	return TRUE;
+}
+
+static INLINE void
+nv40_draw_elements_u08(struct nv40_context *nv40, void *ib,
+		       unsigned start, unsigned count)
+{
+	uint8_t *elts = (uint8_t *)ib + start;
+	int push, i;
+
+	if (count & 1) {
+		BEGIN_RING(curie, NV40TCL_VB_ELEMENT_U32, 1);
+		OUT_RING  (elts[0]);
+		elts++; count--;
+	}
+
+	while (count) {
+		push = MIN2(count, 2046);
+
+		BEGIN_RING_NI(curie, NV40TCL_VB_ELEMENT_U16, push);
+		for (i = 0; i < push; i+=2)
+			OUT_RING((elts[i+1] << 16) | elts[i]);
+
+		count -= push;
+		elts  += push;
+	}
+}
+
+static INLINE void
+nv40_draw_elements_u16(struct nv40_context *nv40, void *ib,
+		       unsigned start, unsigned count)
+{
+	uint16_t *elts = (uint16_t *)ib + start;
+	int push, i;
+
+	if (count & 1) {
+		BEGIN_RING(curie, NV40TCL_VB_ELEMENT_U32, 1);
+		OUT_RING  (elts[0]);
+		elts++; count--;
+	}
+
+	while (count) {
+		push = MIN2(count, 2046);
+
+		BEGIN_RING_NI(curie, NV40TCL_VB_ELEMENT_U16, push);
+		for (i = 0; i < push; i+=2)
+			OUT_RING((elts[i+1] << 16) | elts[i]);
+
+		count -= push;
+		elts  += push;
+	}
+}
+
+static INLINE void
+nv40_draw_elements_u32(struct nv40_context *nv40, void *ib,
+		       unsigned start, unsigned count)
+{
+	uint32_t *elts = (uint32_t *)ib + start;
+	int push;
+
+	while (count) {
+		push = MIN2(count, 2047);
+
+		BEGIN_RING_NI(curie, NV40TCL_VB_ELEMENT_U32, push);
+		OUT_RINGp    (elts, push);
+
+		count -= push;
+		elts  += push;
+	}
+}
+
+boolean
+nv40_draw_elements(struct pipe_context *pipe,
+		   struct pipe_buffer_handle *indexBuffer, unsigned indexSize,
+		   unsigned mode, unsigned start, unsigned count)
+{
+	struct nv40_context *nv40 = (struct nv40_context *)pipe;
+	void *ib;
+
+	if (nv40->dirty)
+		nv40_emit_hw_state(nv40);
+
+	ib = pipe->winsys->buffer_map(pipe->winsys, indexBuffer,
+				      PIPE_BUFFER_FLAG_READ);
+	if (!ib) {
+		NOUVEAU_ERR("Couldn't map index buffer!!\n");
+		return FALSE;
+	}
+
+	BEGIN_RING(curie, NV40TCL_BEGIN_END, 1);
+	OUT_RING  (nvgl_primitive(mode));
+
+	switch (indexSize) {
+	case 1:
+		nv40_draw_elements_u08(nv40, ib, start, count);
+		break;
+	case 2:
+		nv40_draw_elements_u16(nv40, ib, start, count);
+		break;
+	case 4:
+		nv40_draw_elements_u32(nv40, ib, start, count);
+		break;
+	default:
+		NOUVEAU_ERR("unsupported elt size %d\n", indexSize);
+		break;
+	}
+
+	BEGIN_RING(curie, NV40TCL_BEGIN_END, 1);
+	OUT_RING  (0);
+
+	pipe->winsys->buffer_unmap(pipe->winsys, ib);
+	pipe->flush(pipe, PIPE_FLUSH_WAIT);
+	return TRUE;
+}
+
+static INLINE int
+nv40_vbo_format_to_ncomp(uint format)
+{
+	switch (format) {
+	case PIPE_FORMAT_R32G32B32A32_FLOAT: return 4;
+	case PIPE_FORMAT_R32G32B32_FLOAT: return 3;
+	case PIPE_FORMAT_R32G32_FLOAT: return 2;
+	case PIPE_FORMAT_R32_FLOAT: return 1;
+	default:
+	       NOUVEAU_ERR("AII, unknown vbo format %d\n", format);
+	       return 1;
+	}
+}
+
+void
+nv40_vbo_arrays_update(struct nv40_context *nv40)
+{
+	struct nouveau_winsys *nvws = nv40->nvws;
+	struct nv40_vertex_program *vp = nv40->vertprog.vp;
+	uint32_t inputs, vtxfmt[16];
+	int hw, num_hw;
+
+	inputs = vp->ir;
+	for (hw = 0; hw < 16 && inputs; hw++) {
+		if (inputs & (1 << hw)) {
+			num_hw = hw;
+			inputs &= ~(1 << hw);
+		}
+	}
+	num_hw++;
+
+	inputs = vp->ir;
+	BEGIN_RING(curie, NV40TCL_VTXBUF_ADDRESS(0), num_hw);
+	for (hw = 0; hw < num_hw; hw++) {
+		struct pipe_vertex_element *ve;
+		struct pipe_vertex_buffer *vb;
+
+		if (!(inputs & (1 << hw))) {
+			OUT_RING(0);
+			vtxfmt[hw] = NV40TCL_VTXFMT_TYPE_FLOAT;
+			continue;
+		}
+
+		ve = &nv40->vtxelt[hw];
+		vb = &nv40->vtxbuf[ve->vertex_buffer_index];
+
+		OUT_RELOC(vb->buffer, vb->buffer_offset + ve->src_offset,
+			  NOUVEAU_BO_GART | NOUVEAU_BO_VRAM | NOUVEAU_BO_LOW |
+			  NOUVEAU_BO_OR | NOUVEAU_BO_RD, 0,
+			  NV40TCL_VTXBUF_ADDRESS_DMA1);
+		vtxfmt[hw] = ((vb->pitch << NV40TCL_VTXFMT_STRIDE_SHIFT) |
+			      (nv40_vbo_format_to_ncomp(ve->src_format) <<
+			       NV40TCL_VTXFMT_SIZE_SHIFT) |
+			      NV40TCL_VTXFMT_TYPE_FLOAT);
+	}
+
+	BEGIN_RING(curie, 0x1710, 1);
+	OUT_RING  (0); /* vtx cache flush */
+	BEGIN_RING(curie, NV40TCL_VTXFMT(0), num_hw);
+	OUT_RINGp (vtxfmt, num_hw);
+}
+
-- 
cgit v1.2.3