From: Luca Barbieri Date: Sun, 21 Feb 2010 10:12:08 +0000 (+0100) Subject: nv30, nv40: unify nv[34]0_vbo.c X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=6e1d0fc5eba8cda4f4c8f3188f53fec6d2d2e9c3;p=mesa.git nv30, nv40: unify nv[34]0_vbo.c The files are identical, except for swtnl support which is commented out on nv30 and restart being initialized on nv30 to avoid a compiler warning. --- diff --git a/src/gallium/drivers/nv30/Makefile b/src/gallium/drivers/nv30/Makefile index 791b0040bb8..6ec93ee3465 100644 --- a/src/gallium/drivers/nv30/Makefile +++ b/src/gallium/drivers/nv30/Makefile @@ -8,7 +8,6 @@ C_SOURCES = \ nv30_fragtex.c \ nv30_screen.c \ nv30_state.c \ - nv30_vbo.c \ nv30_vertprog.c LIBRARY_INCLUDES = -I$(TOP)/src/gallium/drivers/nvfx diff --git a/src/gallium/drivers/nv30/nv30_context.c b/src/gallium/drivers/nv30/nv30_context.c index 671a1939e8d..730f4588785 100644 --- a/src/gallium/drivers/nv30/nv30_context.c +++ b/src/gallium/drivers/nv30/nv30_context.c @@ -60,8 +60,8 @@ nv30_create(struct pipe_screen *pscreen, void *priv) nvfx->pipe.screen = pscreen; nvfx->pipe.priv = priv; nvfx->pipe.destroy = nv30_destroy; - nvfx->pipe.draw_arrays = nv30_draw_arrays; - nvfx->pipe.draw_elements = nv30_draw_elements; + nvfx->pipe.draw_arrays = nvfx_draw_arrays; + nvfx->pipe.draw_elements = nvfx_draw_elements; nvfx->pipe.clear = nvfx_clear; nvfx->pipe.flush = nv30_flush; diff --git a/src/gallium/drivers/nv30/nv30_context.h b/src/gallium/drivers/nv30/nv30_context.h index ebdd5455ca8..de879d504fc 100644 --- a/src/gallium/drivers/nv30/nv30_context.h +++ b/src/gallium/drivers/nv30/nv30_context.h @@ -15,16 +15,6 @@ extern void nv30_fragtex_bind(struct nvfx_context *); /* nv30_state.c and friends */ extern struct nvfx_state_entry nv30_state_vertprog; extern struct nvfx_state_entry nv30_state_fragtex; -extern struct nvfx_state_entry nv30_state_vbo; - -/* nv30_vbo.c */ -extern void nv30_draw_arrays(struct pipe_context *, unsigned mode, - unsigned start, unsigned count); -extern void nv30_draw_elements(struct pipe_context *pipe, - struct pipe_buffer *indexBuffer, - unsigned indexSize, - unsigned mode, unsigned start, - unsigned count); /* nvfx_context.c */ struct pipe_context * diff --git a/src/gallium/drivers/nv30/nv30_vbo.c b/src/gallium/drivers/nv30/nv30_vbo.c deleted file mode 100644 index 2b4401e5330..00000000000 --- a/src/gallium/drivers/nv30/nv30_vbo.c +++ /dev/null @@ -1,562 +0,0 @@ -#include "pipe/p_context.h" -#include "pipe/p_state.h" -#include "util/u_inlines.h" -#include "util/u_format.h" - -#include "nv30_context.h" -#include "nvfx_state.h" - -#include "nouveau/nouveau_channel.h" -#include "nouveau/nouveau_pushbuf.h" -#include "nouveau/nouveau_util.h" - -#define FORCE_SWTNL 0 - -static INLINE int -nv30_vbo_format_to_hw(enum pipe_format pipe, unsigned *fmt, unsigned *ncomp) -{ - switch (pipe) { - case PIPE_FORMAT_R32_FLOAT: - case PIPE_FORMAT_R32G32_FLOAT: - case PIPE_FORMAT_R32G32B32_FLOAT: - case PIPE_FORMAT_R32G32B32A32_FLOAT: - *fmt = NV34TCL_VTXFMT_TYPE_FLOAT; - break; - case PIPE_FORMAT_R8_UNORM: - case PIPE_FORMAT_R8G8_UNORM: - case PIPE_FORMAT_R8G8B8_UNORM: - case PIPE_FORMAT_R8G8B8A8_UNORM: - *fmt = NV34TCL_VTXFMT_TYPE_UBYTE; - break; - case PIPE_FORMAT_R16_SSCALED: - case PIPE_FORMAT_R16G16_SSCALED: - case PIPE_FORMAT_R16G16B16_SSCALED: - case PIPE_FORMAT_R16G16B16A16_SSCALED: - *fmt = NV34TCL_VTXFMT_TYPE_USHORT; - break; - default: - NOUVEAU_ERR("Unknown format %s\n", util_format_name(pipe)); - return 1; - } - - switch (pipe) { - case PIPE_FORMAT_R8_UNORM: - case PIPE_FORMAT_R32_FLOAT: - case PIPE_FORMAT_R16_SSCALED: - *ncomp = 1; - break; - case PIPE_FORMAT_R8G8_UNORM: - case PIPE_FORMAT_R32G32_FLOAT: - case PIPE_FORMAT_R16G16_SSCALED: - *ncomp = 2; - break; - case PIPE_FORMAT_R8G8B8_UNORM: - case PIPE_FORMAT_R32G32B32_FLOAT: - case PIPE_FORMAT_R16G16B16_SSCALED: - *ncomp = 3; - break; - case PIPE_FORMAT_R8G8B8A8_UNORM: - case PIPE_FORMAT_R32G32B32A32_FLOAT: - case PIPE_FORMAT_R16G16B16A16_SSCALED: - *ncomp = 4; - break; - default: - NOUVEAU_ERR("Unknown format %s\n", util_format_name(pipe)); - return 1; - } - - return 0; -} - -static boolean -nv30_vbo_set_idxbuf(struct nvfx_context *nvfx, struct pipe_buffer *ib, - unsigned ib_size) -{ - struct pipe_screen *pscreen = &nvfx->screen->base.base; - unsigned type; - - if (!ib) { - nvfx->idxbuf = NULL; - nvfx->idxbuf_format = 0xdeadbeef; - return FALSE; - } - - if (!pscreen->get_param(pscreen, NOUVEAU_CAP_HW_IDXBUF) || ib_size == 1) - return FALSE; - - switch (ib_size) { - case 2: - type = NV34TCL_IDXBUF_FORMAT_TYPE_U16; - break; - case 4: - type = NV34TCL_IDXBUF_FORMAT_TYPE_U32; - break; - default: - return FALSE; - } - - if (ib != nvfx->idxbuf || - type != nvfx->idxbuf_format) { - nvfx->dirty |= NVFX_NEW_ARRAYS; - nvfx->idxbuf = ib; - nvfx->idxbuf_format = type; - } - - return TRUE; -} - -static boolean -nv30_vbo_static_attrib(struct nvfx_context *nvfx, struct nouveau_stateobj *so, - int attrib, struct pipe_vertex_element *ve, - struct pipe_vertex_buffer *vb) -{ - struct pipe_screen *pscreen = nvfx->pipe.screen; - struct nouveau_grobj *eng3d = nvfx->screen->eng3d; - unsigned type, ncomp; - void *map; - - if (nv30_vbo_format_to_hw(ve->src_format, &type, &ncomp)) - return FALSE; - - map = pipe_buffer_map(pscreen, vb->buffer, PIPE_BUFFER_USAGE_CPU_READ); - map += vb->buffer_offset + ve->src_offset; - - switch (type) { - case NV34TCL_VTXFMT_TYPE_FLOAT: - { - float *v = map; - - switch (ncomp) { - case 4: - so_method(so, eng3d, NV34TCL_VTX_ATTR_4F_X(attrib), 4); - so_data (so, fui(v[0])); - so_data (so, fui(v[1])); - so_data (so, fui(v[2])); - so_data (so, fui(v[3])); - break; - case 3: - so_method(so, eng3d, NV34TCL_VTX_ATTR_3F_X(attrib), 3); - so_data (so, fui(v[0])); - so_data (so, fui(v[1])); - so_data (so, fui(v[2])); - break; - case 2: - so_method(so, eng3d, NV34TCL_VTX_ATTR_2F_X(attrib), 2); - so_data (so, fui(v[0])); - so_data (so, fui(v[1])); - break; - case 1: - so_method(so, eng3d, NV34TCL_VTX_ATTR_1F(attrib), 1); - so_data (so, fui(v[0])); - break; - default: - pipe_buffer_unmap(pscreen, vb->buffer); - return FALSE; - } - } - break; - default: - pipe_buffer_unmap(pscreen, vb->buffer); - return FALSE; - } - - pipe_buffer_unmap(pscreen, vb->buffer); - return TRUE; -} - -void -nv30_draw_arrays(struct pipe_context *pipe, - unsigned mode, unsigned start, unsigned count) -{ - struct nvfx_context *nvfx = nvfx_context(pipe); - struct nvfx_screen *screen = nvfx->screen; - struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *eng3d = screen->eng3d; - unsigned restart = 0; - - nv30_vbo_set_idxbuf(nvfx, NULL, 0); - if (FORCE_SWTNL || !nvfx_state_validate(nvfx)) { - /*return nv30_draw_elements_swtnl(pipe, NULL, 0, - mode, start, count);*/ - return; - } - - while (count) { - unsigned vc, nr; - - nvfx_state_emit(nvfx); - - vc = nouveau_vbuf_split(AVAIL_RING(chan), 6, 256, - mode, start, count, &restart); - if (!vc) { - FIRE_RING(chan); - continue; - } - - BEGIN_RING(chan, eng3d, NV34TCL_VERTEX_BEGIN_END, 1); - OUT_RING (chan, nvgl_primitive(mode)); - - nr = (vc & 0xff); - if (nr) { - BEGIN_RING(chan, eng3d, NV34TCL_VB_VERTEX_BATCH, 1); - OUT_RING (chan, ((nr - 1) << 24) | start); - start += nr; - } - - nr = vc >> 8; - while (nr) { - unsigned push = nr > 2047 ? 2047 : nr; - - nr -= push; - - BEGIN_RING_NI(chan, eng3d, NV34TCL_VB_VERTEX_BATCH, push); - while (push--) { - OUT_RING(chan, ((0x100 - 1) << 24) | start); - start += 0x100; - } - } - - BEGIN_RING(chan, eng3d, NV34TCL_VERTEX_BEGIN_END, 1); - OUT_RING (chan, 0); - - count -= vc; - start = restart; - } - - pipe->flush(pipe, 0, NULL); -} - -static INLINE void -nv30_draw_elements_u08(struct nvfx_context *nvfx, void *ib, - unsigned mode, unsigned start, unsigned count) -{ - struct nvfx_screen *screen = nvfx->screen; - struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *eng3d = screen->eng3d; - - while (count) { - uint8_t *elts = (uint8_t *)ib + start; - unsigned vc, push, restart = 0; - - nvfx_state_emit(nvfx); - - vc = nouveau_vbuf_split(AVAIL_RING(chan), 6, 2, - mode, start, count, &restart); - if (vc == 0) { - FIRE_RING(chan); - continue; - } - count -= vc; - - BEGIN_RING(chan, eng3d, NV34TCL_VERTEX_BEGIN_END, 1); - OUT_RING (chan, nvgl_primitive(mode)); - - if (vc & 1) { - BEGIN_RING(chan, eng3d, NV34TCL_VB_ELEMENT_U32, 1); - OUT_RING (chan, elts[0]); - elts++; vc--; - } - - while (vc) { - unsigned i; - - push = MIN2(vc, 2047 * 2); - - BEGIN_RING_NI(chan, eng3d, NV34TCL_VB_ELEMENT_U16, push >> 1); - for (i = 0; i < push; i+=2) - OUT_RING(chan, (elts[i+1] << 16) | elts[i]); - - vc -= push; - elts += push; - } - - BEGIN_RING(chan, eng3d, NV34TCL_VERTEX_BEGIN_END, 1); - OUT_RING (chan, 0); - - start = restart; - } -} - -static INLINE void -nv30_draw_elements_u16(struct nvfx_context *nvfx, void *ib, - unsigned mode, unsigned start, unsigned count) -{ - struct nvfx_screen *screen = nvfx->screen; - struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *eng3d = screen->eng3d; - - while (count) { - uint16_t *elts = (uint16_t *)ib + start; - unsigned vc, push, restart = 0; - - nvfx_state_emit(nvfx); - - vc = nouveau_vbuf_split(AVAIL_RING(chan), 6, 2, - mode, start, count, &restart); - if (vc == 0) { - FIRE_RING(chan); - continue; - } - count -= vc; - - BEGIN_RING(chan, eng3d, NV34TCL_VERTEX_BEGIN_END, 1); - OUT_RING (chan, nvgl_primitive(mode)); - - if (vc & 1) { - BEGIN_RING(chan, eng3d, NV34TCL_VB_ELEMENT_U32, 1); - OUT_RING (chan, elts[0]); - elts++; vc--; - } - - while (vc) { - unsigned i; - - push = MIN2(vc, 2047 * 2); - - BEGIN_RING_NI(chan, eng3d, NV34TCL_VB_ELEMENT_U16, push >> 1); - for (i = 0; i < push; i+=2) - OUT_RING(chan, (elts[i+1] << 16) | elts[i]); - - vc -= push; - elts += push; - } - - BEGIN_RING(chan, eng3d, NV34TCL_VERTEX_BEGIN_END, 1); - OUT_RING (chan, 0); - - start = restart; - } -} - -static INLINE void -nv30_draw_elements_u32(struct nvfx_context *nvfx, void *ib, - unsigned mode, unsigned start, unsigned count) -{ - struct nvfx_screen *screen = nvfx->screen; - struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *eng3d = screen->eng3d; - - while (count) { - uint32_t *elts = (uint32_t *)ib + start; - unsigned vc, push, restart = 0; - - nvfx_state_emit(nvfx); - - vc = nouveau_vbuf_split(AVAIL_RING(chan), 5, 1, - mode, start, count, &restart); - if (vc == 0) { - FIRE_RING(chan); - continue; - } - count -= vc; - - BEGIN_RING(chan, eng3d, NV34TCL_VERTEX_BEGIN_END, 1); - OUT_RING (chan, nvgl_primitive(mode)); - - while (vc) { - push = MIN2(vc, 2047); - - BEGIN_RING_NI(chan, eng3d, NV34TCL_VB_ELEMENT_U32, push); - OUT_RINGp (chan, elts, push); - - vc -= push; - elts += push; - } - - BEGIN_RING(chan, eng3d, NV34TCL_VERTEX_BEGIN_END, 1); - OUT_RING (chan, 0); - - start = restart; - } -} - -static void -nv30_draw_elements_inline(struct pipe_context *pipe, - struct pipe_buffer *ib, unsigned ib_size, - unsigned mode, unsigned start, unsigned count) -{ - struct nvfx_context *nvfx = nvfx_context(pipe); - struct pipe_screen *pscreen = pipe->screen; - void *map; - - map = pipe_buffer_map(pscreen, ib, PIPE_BUFFER_USAGE_CPU_READ); - if (!ib) { - NOUVEAU_ERR("failed mapping ib\n"); - return; - } - - switch (ib_size) { - case 1: - nv30_draw_elements_u08(nvfx, map, mode, start, count); - break; - case 2: - nv30_draw_elements_u16(nvfx, map, mode, start, count); - break; - case 4: - nv30_draw_elements_u32(nvfx, map, mode, start, count); - break; - default: - NOUVEAU_ERR("invalid idxbuf fmt %d\n", ib_size); - break; - } - - pipe_buffer_unmap(pscreen, ib); -} - -static void -nv30_draw_elements_vbo(struct pipe_context *pipe, - unsigned mode, unsigned start, unsigned count) -{ - struct nvfx_context *nvfx = nvfx_context(pipe); - struct nvfx_screen *screen = nvfx->screen; - struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *eng3d = screen->eng3d; - unsigned restart = 0; - - while (count) { - unsigned nr, vc; - - nvfx_state_emit(nvfx); - - vc = nouveau_vbuf_split(AVAIL_RING(chan), 6, 256, - mode, start, count, &restart); - if (!vc) { - FIRE_RING(chan); - continue; - } - - BEGIN_RING(chan, eng3d, NV34TCL_VERTEX_BEGIN_END, 1); - OUT_RING (chan, nvgl_primitive(mode)); - - nr = (vc & 0xff); - if (nr) { - BEGIN_RING(chan, eng3d, NV34TCL_VB_INDEX_BATCH, 1); - OUT_RING (chan, ((nr - 1) << 24) | start); - start += nr; - } - - nr = vc >> 8; - while (nr) { - unsigned push = nr > 2047 ? 2047 : nr; - - nr -= push; - - BEGIN_RING_NI(chan, eng3d, NV34TCL_VB_INDEX_BATCH, push); - while (push--) { - OUT_RING(chan, ((0x100 - 1) << 24) | start); - start += 0x100; - } - } - - BEGIN_RING(chan, eng3d, NV34TCL_VERTEX_BEGIN_END, 1); - OUT_RING (chan, 0); - - count -= vc; - start = restart; - } -} - -void -nv30_draw_elements(struct pipe_context *pipe, - struct pipe_buffer *indexBuffer, unsigned indexSize, - unsigned mode, unsigned start, unsigned count) -{ - struct nvfx_context *nvfx = nvfx_context(pipe); - boolean idxbuf; - - idxbuf = nv30_vbo_set_idxbuf(nvfx, indexBuffer, indexSize); - if (FORCE_SWTNL || !nvfx_state_validate(nvfx)) { - /*return nv30_draw_elements_swtnl(pipe, NULL, 0, - mode, start, count);*/ - return; - } - - if (idxbuf) { - nv30_draw_elements_vbo(pipe, mode, start, count); - } else { - nv30_draw_elements_inline(pipe, indexBuffer, indexSize, - mode, start, count); - } - - pipe->flush(pipe, 0, NULL); -} - -static boolean -nv30_vbo_validate(struct nvfx_context *nvfx) -{ - struct nouveau_stateobj *vtxbuf, *vtxfmt, *sattr = NULL; - struct nouveau_grobj *eng3d = nvfx->screen->eng3d; - struct pipe_buffer *ib = nvfx->idxbuf; - unsigned ib_format = nvfx->idxbuf_format; - unsigned vb_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD; - int hw; - - vtxbuf = so_new(3, 17, 18); - so_method(vtxbuf, eng3d, NV34TCL_VTXBUF_ADDRESS(0), nvfx->vtxelt->num_elements); - vtxfmt = so_new(1, 16, 0); - so_method(vtxfmt, eng3d, NV34TCL_VTXFMT(0), nvfx->vtxelt->num_elements); - - for (hw = 0; hw < nvfx->vtxelt->num_elements; hw++) { - struct pipe_vertex_element *ve; - struct pipe_vertex_buffer *vb; - unsigned type, ncomp; - - ve = &nvfx->vtxelt->pipe[hw]; - vb = &nvfx->vtxbuf[ve->vertex_buffer_index]; - - if (!vb->stride) { - if (!sattr) - sattr = so_new(16, 16 * 4, 0); - - if (nv30_vbo_static_attrib(nvfx, sattr, hw, ve, vb)) { - so_data(vtxbuf, 0); - so_data(vtxfmt, NV34TCL_VTXFMT_TYPE_FLOAT); - continue; - } - } - - if (nv30_vbo_format_to_hw(ve->src_format, &type, &ncomp)) { - /*nvfx->fallback_swtnl |= NVFX_NEW_ARRAYS;*/ - so_ref(NULL, &vtxbuf); - so_ref(NULL, &vtxfmt); - return FALSE; - } - - so_reloc(vtxbuf, nouveau_bo(vb->buffer), vb->buffer_offset + - ve->src_offset, vb_flags | NOUVEAU_BO_LOW | - NOUVEAU_BO_OR, 0, NV34TCL_VTXBUF_ADDRESS_DMA1); - so_data (vtxfmt, ((vb->stride << NV34TCL_VTXFMT_STRIDE_SHIFT) | - (ncomp << NV34TCL_VTXFMT_SIZE_SHIFT) | type)); - } - - if (ib) { - struct nouveau_bo *bo = nouveau_bo(ib); - - so_method(vtxbuf, eng3d, NV34TCL_IDXBUF_ADDRESS, 2); - so_reloc (vtxbuf, bo, 0, vb_flags | NOUVEAU_BO_LOW, 0, 0); - so_reloc (vtxbuf, bo, ib_format, vb_flags | NOUVEAU_BO_OR, - 0, NV34TCL_IDXBUF_FORMAT_DMA1); - } - - so_method(vtxbuf, eng3d, 0x1710, 1); - so_data (vtxbuf, 0); - - so_ref(vtxbuf, &nvfx->state.hw[NVFX_STATE_VTXBUF]); - so_ref(NULL, &vtxbuf); - nvfx->state.dirty |= (1ULL << NVFX_STATE_VTXBUF); - so_ref(vtxfmt, &nvfx->state.hw[NVFX_STATE_VTXFMT]); - so_ref(NULL, &vtxfmt); - nvfx->state.dirty |= (1ULL << NVFX_STATE_VTXFMT); - so_ref(sattr, &nvfx->state.hw[NVFX_STATE_VTXATTR]); - so_ref(NULL, &sattr); - nvfx->state.dirty |= (1ULL << NVFX_STATE_VTXATTR); - return FALSE; -} - -struct nvfx_state_entry nv30_state_vbo = { - .validate = nv30_vbo_validate, - .dirty = { - .pipe = NVFX_NEW_ARRAYS, - .hw = 0, - } -}; diff --git a/src/gallium/drivers/nv40/Makefile b/src/gallium/drivers/nv40/Makefile index 7529e33a741..69085069060 100644 --- a/src/gallium/drivers/nv40/Makefile +++ b/src/gallium/drivers/nv40/Makefile @@ -8,7 +8,6 @@ C_SOURCES = \ nv40_fragtex.c \ nv40_screen.c \ nv40_state.c \ - nv40_vbo.c \ nv40_vertprog.c LIBRARY_INCLUDES = -I$(TOP)/src/gallium/drivers/nvfx diff --git a/src/gallium/drivers/nv40/nv40_context.c b/src/gallium/drivers/nv40/nv40_context.c index eb831317720..85c1355b4fa 100644 --- a/src/gallium/drivers/nv40/nv40_context.c +++ b/src/gallium/drivers/nv40/nv40_context.c @@ -60,8 +60,8 @@ nv40_create(struct pipe_screen *pscreen, void *priv) nvfx->pipe.priv = priv; nvfx->pipe.screen = pscreen; nvfx->pipe.destroy = nv40_destroy; - nvfx->pipe.draw_arrays = nv40_draw_arrays; - nvfx->pipe.draw_elements = nv40_draw_elements; + nvfx->pipe.draw_arrays = nvfx_draw_arrays; + nvfx->pipe.draw_elements = nvfx_draw_elements; nvfx->pipe.clear = nvfx_clear; nvfx->pipe.flush = nv40_flush; diff --git a/src/gallium/drivers/nv40/nv40_context.h b/src/gallium/drivers/nv40/nv40_context.h index a8aba0c0cab..cebf21d00c0 100644 --- a/src/gallium/drivers/nv40/nv40_context.h +++ b/src/gallium/drivers/nv40/nv40_context.h @@ -15,16 +15,6 @@ extern void nv40_fragtex_bind(struct nvfx_context *); /* nv40_state.c and friends */ extern struct nvfx_state_entry nv40_state_vertprog; extern struct nvfx_state_entry nv40_state_fragtex; -extern struct nvfx_state_entry nv40_state_vbo; - -/* nv40_vbo.c */ -extern void nv40_draw_arrays(struct pipe_context *, unsigned mode, - unsigned start, unsigned count); -extern void nv40_draw_elements(struct pipe_context *pipe, - struct pipe_buffer *indexBuffer, - unsigned indexSize, - unsigned mode, unsigned start, - unsigned count); /* nvfx_context.c */ struct pipe_context * diff --git a/src/gallium/drivers/nv40/nv40_vbo.c b/src/gallium/drivers/nv40/nv40_vbo.c deleted file mode 100644 index 196a12b1f6b..00000000000 --- a/src/gallium/drivers/nv40/nv40_vbo.c +++ /dev/null @@ -1,565 +0,0 @@ -#include "pipe/p_context.h" -#include "pipe/p_state.h" -#include "util/u_inlines.h" -#include "util/u_format.h" - -#include "nv40_context.h" -#include "nvfx_state.h" - -#include "nouveau/nouveau_channel.h" -#include "nouveau/nouveau_pushbuf.h" -#include "nouveau/nouveau_util.h" - -#define FORCE_SWTNL 0 - -static INLINE int -nv40_vbo_format_to_hw(enum pipe_format pipe, unsigned *fmt, unsigned *ncomp) -{ - switch (pipe) { - case PIPE_FORMAT_R32_FLOAT: - case PIPE_FORMAT_R32G32_FLOAT: - case PIPE_FORMAT_R32G32B32_FLOAT: - case PIPE_FORMAT_R32G32B32A32_FLOAT: - *fmt = NV34TCL_VTXFMT_TYPE_FLOAT; - break; - case PIPE_FORMAT_R8_UNORM: - case PIPE_FORMAT_R8G8_UNORM: - case PIPE_FORMAT_R8G8B8_UNORM: - case PIPE_FORMAT_R8G8B8A8_UNORM: - *fmt = NV34TCL_VTXFMT_TYPE_UBYTE; - break; - case PIPE_FORMAT_R16_SSCALED: - case PIPE_FORMAT_R16G16_SSCALED: - case PIPE_FORMAT_R16G16B16_SSCALED: - case PIPE_FORMAT_R16G16B16A16_SSCALED: - *fmt = NV34TCL_VTXFMT_TYPE_USHORT; - break; - default: - NOUVEAU_ERR("Unknown format %s\n", util_format_name(pipe)); - return 1; - } - - switch (pipe) { - case PIPE_FORMAT_R8_UNORM: - case PIPE_FORMAT_R32_FLOAT: - case PIPE_FORMAT_R16_SSCALED: - *ncomp = 1; - break; - case PIPE_FORMAT_R8G8_UNORM: - case PIPE_FORMAT_R32G32_FLOAT: - case PIPE_FORMAT_R16G16_SSCALED: - *ncomp = 2; - break; - case PIPE_FORMAT_R8G8B8_UNORM: - case PIPE_FORMAT_R32G32B32_FLOAT: - case PIPE_FORMAT_R16G16B16_SSCALED: - *ncomp = 3; - break; - case PIPE_FORMAT_R8G8B8A8_UNORM: - case PIPE_FORMAT_R32G32B32A32_FLOAT: - case PIPE_FORMAT_R16G16B16A16_SSCALED: - *ncomp = 4; - break; - default: - NOUVEAU_ERR("Unknown format %s\n", util_format_name(pipe)); - return 1; - } - - return 0; -} - -static boolean -nv40_vbo_set_idxbuf(struct nvfx_context *nvfx, struct pipe_buffer *ib, - unsigned ib_size) -{ - struct pipe_screen *pscreen = &nvfx->screen->base.base; - unsigned type; - - if (!ib) { - nvfx->idxbuf = NULL; - nvfx->idxbuf_format = 0xdeadbeef; - return FALSE; - } - - if (!pscreen->get_param(pscreen, NOUVEAU_CAP_HW_IDXBUF) || ib_size == 1) - return FALSE; - - switch (ib_size) { - case 2: - type = NV34TCL_IDXBUF_FORMAT_TYPE_U16; - break; - case 4: - type = NV34TCL_IDXBUF_FORMAT_TYPE_U32; - break; - default: - return FALSE; - } - - if (ib != nvfx->idxbuf || - type != nvfx->idxbuf_format) { - nvfx->dirty |= NVFX_NEW_ARRAYS; - nvfx->idxbuf = ib; - nvfx->idxbuf_format = type; - } - - return TRUE; -} - -static boolean -nv40_vbo_static_attrib(struct nvfx_context *nvfx, struct nouveau_stateobj *so, - int attrib, struct pipe_vertex_element *ve, - struct pipe_vertex_buffer *vb) -{ - struct pipe_screen *pscreen = nvfx->pipe.screen; - struct nouveau_grobj *eng3d = nvfx->screen->eng3d; - unsigned type, ncomp; - void *map; - - if (nv40_vbo_format_to_hw(ve->src_format, &type, &ncomp)) - return FALSE; - - map = pipe_buffer_map(pscreen, vb->buffer, PIPE_BUFFER_USAGE_CPU_READ); - map += vb->buffer_offset + ve->src_offset; - - switch (type) { - case NV34TCL_VTXFMT_TYPE_FLOAT: - { - float *v = map; - - switch (ncomp) { - case 4: - so_method(so, eng3d, NV34TCL_VTX_ATTR_4F_X(attrib), 4); - so_data (so, fui(v[0])); - so_data (so, fui(v[1])); - so_data (so, fui(v[2])); - so_data (so, fui(v[3])); - break; - case 3: - so_method(so, eng3d, NV34TCL_VTX_ATTR_3F_X(attrib), 3); - so_data (so, fui(v[0])); - so_data (so, fui(v[1])); - so_data (so, fui(v[2])); - break; - case 2: - so_method(so, eng3d, NV34TCL_VTX_ATTR_2F_X(attrib), 2); - so_data (so, fui(v[0])); - so_data (so, fui(v[1])); - break; - case 1: - so_method(so, eng3d, NV34TCL_VTX_ATTR_1F(attrib), 1); - so_data (so, fui(v[0])); - break; - default: - pipe_buffer_unmap(pscreen, vb->buffer); - return FALSE; - } - } - break; - default: - pipe_buffer_unmap(pscreen, vb->buffer); - return FALSE; - } - - pipe_buffer_unmap(pscreen, vb->buffer); - - return TRUE; -} - -void -nv40_draw_arrays(struct pipe_context *pipe, - unsigned mode, unsigned start, unsigned count) -{ - struct nvfx_context *nvfx = nvfx_context(pipe); - struct nvfx_screen *screen = nvfx->screen; - struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *eng3d = screen->eng3d; - unsigned restart; - - nv40_vbo_set_idxbuf(nvfx, NULL, 0); - if (FORCE_SWTNL || !nvfx_state_validate(nvfx)) { - nvfx_draw_elements_swtnl(pipe, NULL, 0, - mode, start, count); - return; - } - - while (count) { - unsigned vc, nr; - - nvfx_state_emit(nvfx); - - vc = nouveau_vbuf_split(AVAIL_RING(chan), 6, 256, - mode, start, count, &restart); - if (!vc) { - FIRE_RING(chan); - continue; - } - - BEGIN_RING(chan, eng3d, NV34TCL_VERTEX_BEGIN_END, 1); - OUT_RING (chan, nvgl_primitive(mode)); - - nr = (vc & 0xff); - if (nr) { - BEGIN_RING(chan, eng3d, NV34TCL_VB_VERTEX_BATCH, 1); - OUT_RING (chan, ((nr - 1) << 24) | start); - start += nr; - } - - nr = vc >> 8; - while (nr) { - unsigned push = nr > 2047 ? 2047 : nr; - - nr -= push; - - BEGIN_RING_NI(chan, eng3d, NV34TCL_VB_VERTEX_BATCH, push); - while (push--) { - OUT_RING(chan, ((0x100 - 1) << 24) | start); - start += 0x100; - } - } - - BEGIN_RING(chan, eng3d, NV34TCL_VERTEX_BEGIN_END, 1); - OUT_RING (chan, 0); - - count -= vc; - start = restart; - } - - pipe->flush(pipe, 0, NULL); -} - -static INLINE void -nv40_draw_elements_u08(struct nvfx_context *nvfx, void *ib, - unsigned mode, unsigned start, unsigned count) -{ - struct nvfx_screen *screen = nvfx->screen; - struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *eng3d = screen->eng3d; - - while (count) { - uint8_t *elts = (uint8_t *)ib + start; - unsigned vc, push, restart; - - nvfx_state_emit(nvfx); - - vc = nouveau_vbuf_split(AVAIL_RING(chan), 6, 2, - mode, start, count, &restart); - if (vc == 0) { - FIRE_RING(chan); - continue; - } - count -= vc; - - BEGIN_RING(chan, eng3d, NV34TCL_VERTEX_BEGIN_END, 1); - OUT_RING (chan, nvgl_primitive(mode)); - - if (vc & 1) { - BEGIN_RING(chan, eng3d, NV34TCL_VB_ELEMENT_U32, 1); - OUT_RING (chan, elts[0]); - elts++; vc--; - } - - while (vc) { - unsigned i; - - push = MIN2(vc, 2047 * 2); - - BEGIN_RING_NI(chan, eng3d, NV34TCL_VB_ELEMENT_U16, push >> 1); - for (i = 0; i < push; i+=2) - OUT_RING(chan, (elts[i+1] << 16) | elts[i]); - - vc -= push; - elts += push; - } - - BEGIN_RING(chan, eng3d, NV34TCL_VERTEX_BEGIN_END, 1); - OUT_RING (chan, 0); - - start = restart; - } -} - -static INLINE void -nv40_draw_elements_u16(struct nvfx_context *nvfx, void *ib, - unsigned mode, unsigned start, unsigned count) -{ - struct nvfx_screen *screen = nvfx->screen; - struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *eng3d = screen->eng3d; - - while (count) { - uint16_t *elts = (uint16_t *)ib + start; - unsigned vc, push, restart; - - nvfx_state_emit(nvfx); - - vc = nouveau_vbuf_split(AVAIL_RING(chan), 6, 2, - mode, start, count, &restart); - if (vc == 0) { - FIRE_RING(chan); - continue; - } - count -= vc; - - BEGIN_RING(chan, eng3d, NV34TCL_VERTEX_BEGIN_END, 1); - OUT_RING (chan, nvgl_primitive(mode)); - - if (vc & 1) { - BEGIN_RING(chan, eng3d, NV34TCL_VB_ELEMENT_U32, 1); - OUT_RING (chan, elts[0]); - elts++; vc--; - } - - while (vc) { - unsigned i; - - push = MIN2(vc, 2047 * 2); - - BEGIN_RING_NI(chan, eng3d, NV34TCL_VB_ELEMENT_U16, push >> 1); - for (i = 0; i < push; i+=2) - OUT_RING(chan, (elts[i+1] << 16) | elts[i]); - - vc -= push; - elts += push; - } - - BEGIN_RING(chan, eng3d, NV34TCL_VERTEX_BEGIN_END, 1); - OUT_RING (chan, 0); - - start = restart; - } -} - -static INLINE void -nv40_draw_elements_u32(struct nvfx_context *nvfx, void *ib, - unsigned mode, unsigned start, unsigned count) -{ - struct nvfx_screen *screen = nvfx->screen; - struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *eng3d = screen->eng3d; - - while (count) { - uint32_t *elts = (uint32_t *)ib + start; - unsigned vc, push, restart; - - nvfx_state_emit(nvfx); - - vc = nouveau_vbuf_split(AVAIL_RING(chan), 5, 1, - mode, start, count, &restart); - if (vc == 0) { - FIRE_RING(chan); - continue; - } - count -= vc; - - BEGIN_RING(chan, eng3d, NV34TCL_VERTEX_BEGIN_END, 1); - OUT_RING (chan, nvgl_primitive(mode)); - - while (vc) { - push = MIN2(vc, 2047); - - BEGIN_RING_NI(chan, eng3d, NV34TCL_VB_ELEMENT_U32, push); - OUT_RINGp (chan, elts, push); - - vc -= push; - elts += push; - } - - BEGIN_RING(chan, eng3d, NV34TCL_VERTEX_BEGIN_END, 1); - OUT_RING (chan, 0); - - start = restart; - } -} - -static void -nv40_draw_elements_inline(struct pipe_context *pipe, - struct pipe_buffer *ib, unsigned ib_size, - unsigned mode, unsigned start, unsigned count) -{ - struct nvfx_context *nvfx = nvfx_context(pipe); - struct pipe_screen *pscreen = pipe->screen; - void *map; - - map = pipe_buffer_map(pscreen, ib, PIPE_BUFFER_USAGE_CPU_READ); - if (!ib) { - NOUVEAU_ERR("failed mapping ib\n"); - return; - } - - switch (ib_size) { - case 1: - nv40_draw_elements_u08(nvfx, map, mode, start, count); - break; - case 2: - nv40_draw_elements_u16(nvfx, map, mode, start, count); - break; - case 4: - nv40_draw_elements_u32(nvfx, map, mode, start, count); - break; - default: - NOUVEAU_ERR("invalid idxbuf fmt %d\n", ib_size); - break; - } - - pipe_buffer_unmap(pscreen, ib); -} - -static void -nv40_draw_elements_vbo(struct pipe_context *pipe, - unsigned mode, unsigned start, unsigned count) -{ - struct nvfx_context *nvfx = nvfx_context(pipe); - struct nvfx_screen *screen = nvfx->screen; - struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *eng3d = screen->eng3d; - unsigned restart; - - while (count) { - unsigned nr, vc; - - nvfx_state_emit(nvfx); - - vc = nouveau_vbuf_split(AVAIL_RING(chan), 6, 256, - mode, start, count, &restart); - if (!vc) { - FIRE_RING(chan); - continue; - } - - BEGIN_RING(chan, eng3d, NV34TCL_VERTEX_BEGIN_END, 1); - OUT_RING (chan, nvgl_primitive(mode)); - - nr = (vc & 0xff); - if (nr) { - BEGIN_RING(chan, eng3d, NV34TCL_VB_INDEX_BATCH, 1); - OUT_RING (chan, ((nr - 1) << 24) | start); - start += nr; - } - - nr = vc >> 8; - while (nr) { - unsigned push = nr > 2047 ? 2047 : nr; - - nr -= push; - - BEGIN_RING_NI(chan, eng3d, NV34TCL_VB_INDEX_BATCH, push); - while (push--) { - OUT_RING(chan, ((0x100 - 1) << 24) | start); - start += 0x100; - } - } - - BEGIN_RING(chan, eng3d, NV34TCL_VERTEX_BEGIN_END, 1); - OUT_RING (chan, 0); - - count -= vc; - start = restart; - } -} - -void -nv40_draw_elements(struct pipe_context *pipe, - struct pipe_buffer *indexBuffer, unsigned indexSize, - unsigned mode, unsigned start, unsigned count) -{ - struct nvfx_context *nvfx = nvfx_context(pipe); - boolean idxbuf; - - idxbuf = nv40_vbo_set_idxbuf(nvfx, indexBuffer, indexSize); - if (FORCE_SWTNL || !nvfx_state_validate(nvfx)) { - nvfx_draw_elements_swtnl(pipe, NULL, 0, - mode, start, count); - return; - } - - if (idxbuf) { - nv40_draw_elements_vbo(pipe, mode, start, count); - } else { - nv40_draw_elements_inline(pipe, indexBuffer, indexSize, - mode, start, count); - } - - pipe->flush(pipe, 0, NULL); -} - -static boolean -nv40_vbo_validate(struct nvfx_context *nvfx) -{ - struct nouveau_stateobj *vtxbuf, *vtxfmt, *sattr = NULL; - struct nouveau_grobj *eng3d = nvfx->screen->eng3d; - struct pipe_buffer *ib = nvfx->idxbuf; - unsigned ib_format = nvfx->idxbuf_format; - unsigned vb_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD; - int hw; - - vtxbuf = so_new(3, 17, 18); - so_method(vtxbuf, eng3d, NV34TCL_VTXBUF_ADDRESS(0), nvfx->vtxelt->num_elements); - vtxfmt = so_new(1, 16, 0); - so_method(vtxfmt, eng3d, NV34TCL_VTXFMT(0), nvfx->vtxelt->num_elements); - - for (hw = 0; hw < nvfx->vtxelt->num_elements; hw++) { - struct pipe_vertex_element *ve; - struct pipe_vertex_buffer *vb; - unsigned type, ncomp; - - ve = &nvfx->vtxelt->pipe[hw]; - vb = &nvfx->vtxbuf[ve->vertex_buffer_index]; - - if (!vb->stride) { - if (!sattr) - sattr = so_new(16, 16 * 4, 0); - - if (nv40_vbo_static_attrib(nvfx, sattr, hw, ve, vb)) { - so_data(vtxbuf, 0); - so_data(vtxfmt, NV34TCL_VTXFMT_TYPE_FLOAT); - continue; - } - } - - if (nv40_vbo_format_to_hw(ve->src_format, &type, &ncomp)) { - nvfx->fallback_swtnl |= NVFX_NEW_ARRAYS; - so_ref(NULL, &vtxbuf); - so_ref(NULL, &vtxfmt); - return FALSE; - } - - so_reloc(vtxbuf, nouveau_bo(vb->buffer), - vb->buffer_offset + ve->src_offset, - vb_flags | NOUVEAU_BO_LOW | NOUVEAU_BO_OR, - 0, NV34TCL_VTXBUF_ADDRESS_DMA1); - so_data (vtxfmt, ((vb->stride << NV34TCL_VTXFMT_STRIDE_SHIFT) | - (ncomp << NV34TCL_VTXFMT_SIZE_SHIFT) | type)); - } - - if (ib) { - struct nouveau_bo *bo = nouveau_bo(ib); - - so_method(vtxbuf, eng3d, NV34TCL_IDXBUF_ADDRESS, 2); - so_reloc (vtxbuf, bo, 0, vb_flags | NOUVEAU_BO_LOW, 0, 0); - so_reloc (vtxbuf, bo, ib_format, vb_flags | NOUVEAU_BO_OR, - 0, NV34TCL_IDXBUF_FORMAT_DMA1); - } - - so_method(vtxbuf, eng3d, 0x1710, 1); - so_data (vtxbuf, 0); - - so_ref(vtxbuf, &nvfx->state.hw[NVFX_STATE_VTXBUF]); - so_ref(NULL, &vtxbuf); - nvfx->state.dirty |= (1ULL << NVFX_STATE_VTXBUF); - so_ref(vtxfmt, &nvfx->state.hw[NVFX_STATE_VTXFMT]); - so_ref(NULL, &vtxfmt); - nvfx->state.dirty |= (1ULL << NVFX_STATE_VTXFMT); - so_ref(sattr, &nvfx->state.hw[NVFX_STATE_VTXATTR]); - so_ref(NULL, &sattr); - nvfx->state.dirty |= (1ULL << NVFX_STATE_VTXATTR); - return FALSE; -} - -struct nvfx_state_entry nv40_state_vbo = { - .validate = nv40_vbo_validate, - .dirty = { - .pipe = NVFX_NEW_ARRAYS, - .hw = 0, - } -}; - diff --git a/src/gallium/drivers/nvfx/Makefile b/src/gallium/drivers/nvfx/Makefile index a23d024f118..d1304ccea0d 100644 --- a/src/gallium/drivers/nvfx/Makefile +++ b/src/gallium/drivers/nvfx/Makefile @@ -18,6 +18,7 @@ C_SOURCES = \ nvfx_state_viewport.c \ nvfx_state_zsa.c \ nvfx_surface.c \ - nvfx_transfer.c + nvfx_transfer.c \ + nvfx_vbo.c include ../../Makefile.template diff --git a/src/gallium/drivers/nvfx/nvfx_context.h b/src/gallium/drivers/nvfx/nvfx_context.h index 75008f8dddc..8f121fe3af2 100644 --- a/src/gallium/drivers/nvfx/nvfx_context.h +++ b/src/gallium/drivers/nvfx/nvfx_context.h @@ -189,6 +189,7 @@ extern struct nvfx_state_entry nvfx_state_rasterizer; extern struct nvfx_state_entry nvfx_state_scissor; extern struct nvfx_state_entry nvfx_state_sr; extern struct nvfx_state_entry nvfx_state_stipple; +extern struct nvfx_state_entry nvfx_state_vbo; extern struct nvfx_state_entry nvfx_state_viewport; extern struct nvfx_state_entry nvfx_state_vtxfmt; extern struct nvfx_state_entry nvfx_state_zsa; @@ -220,4 +221,13 @@ extern void nvfx_state_emit(struct nvfx_context *nvfx); /* nvfx_transfer.c */ extern void nvfx_init_transfer_functions(struct nvfx_context *nvfx); +/* nvfx_vbo.c */ +extern void nvfx_draw_arrays(struct pipe_context *, unsigned mode, + unsigned start, unsigned count); +extern void nvfx_draw_elements(struct pipe_context *pipe, + struct pipe_buffer *indexBuffer, + unsigned indexSize, + unsigned mode, unsigned start, + unsigned count); + #endif diff --git a/src/gallium/drivers/nvfx/nvfx_state_emit.c b/src/gallium/drivers/nvfx/nvfx_state_emit.c index 9961dacce4c..88b86f9fb50 100644 --- a/src/gallium/drivers/nvfx/nvfx_state_emit.c +++ b/src/gallium/drivers/nvfx/nvfx_state_emit.c @@ -3,10 +3,6 @@ #include "nvfx_state.h" #include "draw/draw_context.h" -/* temporary, will be removed in next patch */ -#define nv30_state_vtxfmt nvfx_state_vtxfmt -#define nv40_state_vtxfmt nvfx_state_vtxfmt - #define RENDER_STATES(name, nvxx, vbo) \ static struct nvfx_state_entry *name##_render_states[] = { \ &nvfx_state_framebuffer, \ @@ -21,7 +17,7 @@ static struct nvfx_state_entry *name##_render_states[] = { \ &nvfx_state_zsa, \ &nvfx_state_sr, \ &nvfx_state_viewport, \ - &nvxx##_state_##vbo, \ + &nvfx_state_##vbo, \ NULL \ } diff --git a/src/gallium/drivers/nvfx/nvfx_vbo.c b/src/gallium/drivers/nvfx/nvfx_vbo.c new file mode 100644 index 00000000000..9d501ef1da9 --- /dev/null +++ b/src/gallium/drivers/nvfx/nvfx_vbo.c @@ -0,0 +1,563 @@ +#include "pipe/p_context.h" +#include "pipe/p_state.h" +#include "util/u_inlines.h" +#include "util/u_format.h" + +#include "nvfx_context.h" +#include "nvfx_state.h" + +#include "nouveau/nouveau_channel.h" +#include "nouveau/nouveau_pushbuf.h" +#include "nouveau/nouveau_util.h" + +#define FORCE_SWTNL 0 + +static INLINE int +nvfx_vbo_format_to_hw(enum pipe_format pipe, unsigned *fmt, unsigned *ncomp) +{ + switch (pipe) { + case PIPE_FORMAT_R32_FLOAT: + case PIPE_FORMAT_R32G32_FLOAT: + case PIPE_FORMAT_R32G32B32_FLOAT: + case PIPE_FORMAT_R32G32B32A32_FLOAT: + *fmt = NV34TCL_VTXFMT_TYPE_FLOAT; + break; + case PIPE_FORMAT_R8_UNORM: + case PIPE_FORMAT_R8G8_UNORM: + case PIPE_FORMAT_R8G8B8_UNORM: + case PIPE_FORMAT_R8G8B8A8_UNORM: + *fmt = NV34TCL_VTXFMT_TYPE_UBYTE; + break; + case PIPE_FORMAT_R16_SSCALED: + case PIPE_FORMAT_R16G16_SSCALED: + case PIPE_FORMAT_R16G16B16_SSCALED: + case PIPE_FORMAT_R16G16B16A16_SSCALED: + *fmt = NV34TCL_VTXFMT_TYPE_USHORT; + break; + default: + NOUVEAU_ERR("Unknown format %s\n", util_format_name(pipe)); + return 1; + } + + switch (pipe) { + case PIPE_FORMAT_R8_UNORM: + case PIPE_FORMAT_R32_FLOAT: + case PIPE_FORMAT_R16_SSCALED: + *ncomp = 1; + break; + case PIPE_FORMAT_R8G8_UNORM: + case PIPE_FORMAT_R32G32_FLOAT: + case PIPE_FORMAT_R16G16_SSCALED: + *ncomp = 2; + break; + case PIPE_FORMAT_R8G8B8_UNORM: + case PIPE_FORMAT_R32G32B32_FLOAT: + case PIPE_FORMAT_R16G16B16_SSCALED: + *ncomp = 3; + break; + case PIPE_FORMAT_R8G8B8A8_UNORM: + case PIPE_FORMAT_R32G32B32A32_FLOAT: + case PIPE_FORMAT_R16G16B16A16_SSCALED: + *ncomp = 4; + break; + default: + NOUVEAU_ERR("Unknown format %s\n", util_format_name(pipe)); + return 1; + } + + return 0; +} + +static boolean +nvfx_vbo_set_idxbuf(struct nvfx_context *nvfx, struct pipe_buffer *ib, + unsigned ib_size) +{ + struct pipe_screen *pscreen = &nvfx->screen->base.base; + unsigned type; + + if (!ib) { + nvfx->idxbuf = NULL; + nvfx->idxbuf_format = 0xdeadbeef; + return FALSE; + } + + if (!pscreen->get_param(pscreen, NOUVEAU_CAP_HW_IDXBUF) || ib_size == 1) + return FALSE; + + switch (ib_size) { + case 2: + type = NV34TCL_IDXBUF_FORMAT_TYPE_U16; + break; + case 4: + type = NV34TCL_IDXBUF_FORMAT_TYPE_U32; + break; + default: + return FALSE; + } + + if (ib != nvfx->idxbuf || + type != nvfx->idxbuf_format) { + nvfx->dirty |= NVFX_NEW_ARRAYS; + nvfx->idxbuf = ib; + nvfx->idxbuf_format = type; + } + + return TRUE; +} + +static boolean +nvfx_vbo_static_attrib(struct nvfx_context *nvfx, struct nouveau_stateobj *so, + int attrib, struct pipe_vertex_element *ve, + struct pipe_vertex_buffer *vb) +{ + struct pipe_screen *pscreen = nvfx->pipe.screen; + struct nouveau_grobj *eng3d = nvfx->screen->eng3d; + unsigned type, ncomp; + void *map; + + if (nvfx_vbo_format_to_hw(ve->src_format, &type, &ncomp)) + return FALSE; + + map = pipe_buffer_map(pscreen, vb->buffer, PIPE_BUFFER_USAGE_CPU_READ); + map += vb->buffer_offset + ve->src_offset; + + switch (type) { + case NV34TCL_VTXFMT_TYPE_FLOAT: + { + float *v = map; + + switch (ncomp) { + case 4: + so_method(so, eng3d, NV34TCL_VTX_ATTR_4F_X(attrib), 4); + so_data (so, fui(v[0])); + so_data (so, fui(v[1])); + so_data (so, fui(v[2])); + so_data (so, fui(v[3])); + break; + case 3: + so_method(so, eng3d, NV34TCL_VTX_ATTR_3F_X(attrib), 3); + so_data (so, fui(v[0])); + so_data (so, fui(v[1])); + so_data (so, fui(v[2])); + break; + case 2: + so_method(so, eng3d, NV34TCL_VTX_ATTR_2F_X(attrib), 2); + so_data (so, fui(v[0])); + so_data (so, fui(v[1])); + break; + case 1: + so_method(so, eng3d, NV34TCL_VTX_ATTR_1F(attrib), 1); + so_data (so, fui(v[0])); + break; + default: + pipe_buffer_unmap(pscreen, vb->buffer); + return FALSE; + } + } + break; + default: + pipe_buffer_unmap(pscreen, vb->buffer); + return FALSE; + } + + pipe_buffer_unmap(pscreen, vb->buffer); + return TRUE; +} + +void +nvfx_draw_arrays(struct pipe_context *pipe, + unsigned mode, unsigned start, unsigned count) +{ + struct nvfx_context *nvfx = nvfx_context(pipe); + struct nvfx_screen *screen = nvfx->screen; + struct nouveau_channel *chan = screen->base.channel; + struct nouveau_grobj *eng3d = screen->eng3d; + unsigned restart = 0; + + nvfx_vbo_set_idxbuf(nvfx, NULL, 0); + if (FORCE_SWTNL || !nvfx_state_validate(nvfx)) { + nvfx_draw_elements_swtnl(pipe, NULL, 0, + mode, start, count); + return; + } + + while (count) { + unsigned vc, nr; + + nvfx_state_emit(nvfx); + + vc = nouveau_vbuf_split(AVAIL_RING(chan), 6, 256, + mode, start, count, &restart); + if (!vc) { + FIRE_RING(chan); + continue; + } + + BEGIN_RING(chan, eng3d, NV34TCL_VERTEX_BEGIN_END, 1); + OUT_RING (chan, nvgl_primitive(mode)); + + nr = (vc & 0xff); + if (nr) { + BEGIN_RING(chan, eng3d, NV34TCL_VB_VERTEX_BATCH, 1); + OUT_RING (chan, ((nr - 1) << 24) | start); + start += nr; + } + + nr = vc >> 8; + while (nr) { + unsigned push = nr > 2047 ? 2047 : nr; + + nr -= push; + + BEGIN_RING_NI(chan, eng3d, NV34TCL_VB_VERTEX_BATCH, push); + while (push--) { + OUT_RING(chan, ((0x100 - 1) << 24) | start); + start += 0x100; + } + } + + BEGIN_RING(chan, eng3d, NV34TCL_VERTEX_BEGIN_END, 1); + OUT_RING (chan, 0); + + count -= vc; + start = restart; + } + + pipe->flush(pipe, 0, NULL); +} + +static INLINE void +nvfx_draw_elements_u08(struct nvfx_context *nvfx, void *ib, + unsigned mode, unsigned start, unsigned count) +{ + struct nvfx_screen *screen = nvfx->screen; + struct nouveau_channel *chan = screen->base.channel; + struct nouveau_grobj *eng3d = screen->eng3d; + + while (count) { + uint8_t *elts = (uint8_t *)ib + start; + unsigned vc, push, restart = 0; + + nvfx_state_emit(nvfx); + + vc = nouveau_vbuf_split(AVAIL_RING(chan), 6, 2, + mode, start, count, &restart); + if (vc == 0) { + FIRE_RING(chan); + continue; + } + count -= vc; + + BEGIN_RING(chan, eng3d, NV34TCL_VERTEX_BEGIN_END, 1); + OUT_RING (chan, nvgl_primitive(mode)); + + if (vc & 1) { + BEGIN_RING(chan, eng3d, NV34TCL_VB_ELEMENT_U32, 1); + OUT_RING (chan, elts[0]); + elts++; vc--; + } + + while (vc) { + unsigned i; + + push = MIN2(vc, 2047 * 2); + + BEGIN_RING_NI(chan, eng3d, NV34TCL_VB_ELEMENT_U16, push >> 1); + for (i = 0; i < push; i+=2) + OUT_RING(chan, (elts[i+1] << 16) | elts[i]); + + vc -= push; + elts += push; + } + + BEGIN_RING(chan, eng3d, NV34TCL_VERTEX_BEGIN_END, 1); + OUT_RING (chan, 0); + + start = restart; + } +} + +static INLINE void +nvfx_draw_elements_u16(struct nvfx_context *nvfx, void *ib, + unsigned mode, unsigned start, unsigned count) +{ + struct nvfx_screen *screen = nvfx->screen; + struct nouveau_channel *chan = screen->base.channel; + struct nouveau_grobj *eng3d = screen->eng3d; + + while (count) { + uint16_t *elts = (uint16_t *)ib + start; + unsigned vc, push, restart = 0; + + nvfx_state_emit(nvfx); + + vc = nouveau_vbuf_split(AVAIL_RING(chan), 6, 2, + mode, start, count, &restart); + if (vc == 0) { + FIRE_RING(chan); + continue; + } + count -= vc; + + BEGIN_RING(chan, eng3d, NV34TCL_VERTEX_BEGIN_END, 1); + OUT_RING (chan, nvgl_primitive(mode)); + + if (vc & 1) { + BEGIN_RING(chan, eng3d, NV34TCL_VB_ELEMENT_U32, 1); + OUT_RING (chan, elts[0]); + elts++; vc--; + } + + while (vc) { + unsigned i; + + push = MIN2(vc, 2047 * 2); + + BEGIN_RING_NI(chan, eng3d, NV34TCL_VB_ELEMENT_U16, push >> 1); + for (i = 0; i < push; i+=2) + OUT_RING(chan, (elts[i+1] << 16) | elts[i]); + + vc -= push; + elts += push; + } + + BEGIN_RING(chan, eng3d, NV34TCL_VERTEX_BEGIN_END, 1); + OUT_RING (chan, 0); + + start = restart; + } +} + +static INLINE void +nvfx_draw_elements_u32(struct nvfx_context *nvfx, void *ib, + unsigned mode, unsigned start, unsigned count) +{ + struct nvfx_screen *screen = nvfx->screen; + struct nouveau_channel *chan = screen->base.channel; + struct nouveau_grobj *eng3d = screen->eng3d; + + while (count) { + uint32_t *elts = (uint32_t *)ib + start; + unsigned vc, push, restart = 0; + + nvfx_state_emit(nvfx); + + vc = nouveau_vbuf_split(AVAIL_RING(chan), 5, 1, + mode, start, count, &restart); + if (vc == 0) { + FIRE_RING(chan); + continue; + } + count -= vc; + + BEGIN_RING(chan, eng3d, NV34TCL_VERTEX_BEGIN_END, 1); + OUT_RING (chan, nvgl_primitive(mode)); + + while (vc) { + push = MIN2(vc, 2047); + + BEGIN_RING_NI(chan, eng3d, NV34TCL_VB_ELEMENT_U32, push); + OUT_RINGp (chan, elts, push); + + vc -= push; + elts += push; + } + + BEGIN_RING(chan, eng3d, NV34TCL_VERTEX_BEGIN_END, 1); + OUT_RING (chan, 0); + + start = restart; + } +} + +static void +nvfx_draw_elements_inline(struct pipe_context *pipe, + struct pipe_buffer *ib, unsigned ib_size, + unsigned mode, unsigned start, unsigned count) +{ + struct nvfx_context *nvfx = nvfx_context(pipe); + struct pipe_screen *pscreen = pipe->screen; + void *map; + + map = pipe_buffer_map(pscreen, ib, PIPE_BUFFER_USAGE_CPU_READ); + if (!ib) { + NOUVEAU_ERR("failed mapping ib\n"); + return; + } + + switch (ib_size) { + case 1: + nvfx_draw_elements_u08(nvfx, map, mode, start, count); + break; + case 2: + nvfx_draw_elements_u16(nvfx, map, mode, start, count); + break; + case 4: + nvfx_draw_elements_u32(nvfx, map, mode, start, count); + break; + default: + NOUVEAU_ERR("invalid idxbuf fmt %d\n", ib_size); + break; + } + + pipe_buffer_unmap(pscreen, ib); +} + +static void +nvfx_draw_elements_vbo(struct pipe_context *pipe, + unsigned mode, unsigned start, unsigned count) +{ + struct nvfx_context *nvfx = nvfx_context(pipe); + struct nvfx_screen *screen = nvfx->screen; + struct nouveau_channel *chan = screen->base.channel; + struct nouveau_grobj *eng3d = screen->eng3d; + unsigned restart = 0; + + while (count) { + unsigned nr, vc; + + nvfx_state_emit(nvfx); + + vc = nouveau_vbuf_split(AVAIL_RING(chan), 6, 256, + mode, start, count, &restart); + if (!vc) { + FIRE_RING(chan); + continue; + } + + BEGIN_RING(chan, eng3d, NV34TCL_VERTEX_BEGIN_END, 1); + OUT_RING (chan, nvgl_primitive(mode)); + + nr = (vc & 0xff); + if (nr) { + BEGIN_RING(chan, eng3d, NV34TCL_VB_INDEX_BATCH, 1); + OUT_RING (chan, ((nr - 1) << 24) | start); + start += nr; + } + + nr = vc >> 8; + while (nr) { + unsigned push = nr > 2047 ? 2047 : nr; + + nr -= push; + + BEGIN_RING_NI(chan, eng3d, NV34TCL_VB_INDEX_BATCH, push); + while (push--) { + OUT_RING(chan, ((0x100 - 1) << 24) | start); + start += 0x100; + } + } + + BEGIN_RING(chan, eng3d, NV34TCL_VERTEX_BEGIN_END, 1); + OUT_RING (chan, 0); + + count -= vc; + start = restart; + } +} + +void +nvfx_draw_elements(struct pipe_context *pipe, + struct pipe_buffer *indexBuffer, unsigned indexSize, + unsigned mode, unsigned start, unsigned count) +{ + struct nvfx_context *nvfx = nvfx_context(pipe); + boolean idxbuf; + + idxbuf = nvfx_vbo_set_idxbuf(nvfx, indexBuffer, indexSize); + if (FORCE_SWTNL || !nvfx_state_validate(nvfx)) { + nvfx_draw_elements_swtnl(pipe, NULL, 0, + mode, start, count); + return; + } + + if (idxbuf) { + nvfx_draw_elements_vbo(pipe, mode, start, count); + } else { + nvfx_draw_elements_inline(pipe, indexBuffer, indexSize, + mode, start, count); + } + + pipe->flush(pipe, 0, NULL); +} + +static boolean +nvfx_vbo_validate(struct nvfx_context *nvfx) +{ + struct nouveau_stateobj *vtxbuf, *vtxfmt, *sattr = NULL; + struct nouveau_grobj *eng3d = nvfx->screen->eng3d; + struct pipe_buffer *ib = nvfx->idxbuf; + unsigned ib_format = nvfx->idxbuf_format; + unsigned vb_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD; + int hw; + + vtxbuf = so_new(3, 17, 18); + so_method(vtxbuf, eng3d, NV34TCL_VTXBUF_ADDRESS(0), nvfx->vtxelt->num_elements); + vtxfmt = so_new(1, 16, 0); + so_method(vtxfmt, eng3d, NV34TCL_VTXFMT(0), nvfx->vtxelt->num_elements); + + for (hw = 0; hw < nvfx->vtxelt->num_elements; hw++) { + struct pipe_vertex_element *ve; + struct pipe_vertex_buffer *vb; + unsigned type, ncomp; + + ve = &nvfx->vtxelt->pipe[hw]; + vb = &nvfx->vtxbuf[ve->vertex_buffer_index]; + + if (!vb->stride) { + if (!sattr) + sattr = so_new(16, 16 * 4, 0); + + if (nvfx_vbo_static_attrib(nvfx, sattr, hw, ve, vb)) { + so_data(vtxbuf, 0); + so_data(vtxfmt, NV34TCL_VTXFMT_TYPE_FLOAT); + continue; + } + } + + if (nvfx_vbo_format_to_hw(ve->src_format, &type, &ncomp)) { + nvfx->fallback_swtnl |= NVFX_NEW_ARRAYS; + so_ref(NULL, &vtxbuf); + so_ref(NULL, &vtxfmt); + return FALSE; + } + + so_reloc(vtxbuf, nouveau_bo(vb->buffer), + vb->buffer_offset + ve->src_offset, + vb_flags | NOUVEAU_BO_LOW | NOUVEAU_BO_OR, + 0, NV34TCL_VTXBUF_ADDRESS_DMA1); + so_data (vtxfmt, ((vb->stride << NV34TCL_VTXFMT_STRIDE_SHIFT) | + (ncomp << NV34TCL_VTXFMT_SIZE_SHIFT) | type)); + } + + if (ib) { + struct nouveau_bo *bo = nouveau_bo(ib); + + so_method(vtxbuf, eng3d, NV34TCL_IDXBUF_ADDRESS, 2); + so_reloc (vtxbuf, bo, 0, vb_flags | NOUVEAU_BO_LOW, 0, 0); + so_reloc (vtxbuf, bo, ib_format, vb_flags | NOUVEAU_BO_OR, + 0, NV34TCL_IDXBUF_FORMAT_DMA1); + } + + so_method(vtxbuf, eng3d, 0x1710, 1); + so_data (vtxbuf, 0); + + so_ref(vtxbuf, &nvfx->state.hw[NVFX_STATE_VTXBUF]); + so_ref(NULL, &vtxbuf); + nvfx->state.dirty |= (1ULL << NVFX_STATE_VTXBUF); + so_ref(vtxfmt, &nvfx->state.hw[NVFX_STATE_VTXFMT]); + so_ref(NULL, &vtxfmt); + nvfx->state.dirty |= (1ULL << NVFX_STATE_VTXFMT); + so_ref(sattr, &nvfx->state.hw[NVFX_STATE_VTXATTR]); + so_ref(NULL, &sattr); + nvfx->state.dirty |= (1ULL << NVFX_STATE_VTXATTR); + return FALSE; +} + +struct nvfx_state_entry nvfx_state_vbo = { + .validate = nvfx_vbo_validate, + .dirty = { + .pipe = NVFX_NEW_ARRAYS, + .hw = 0, + } +};