summaryrefslogtreecommitdiff
path: root/src/mesa/drivers/dri/nouveau
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa/drivers/dri/nouveau')
-rw-r--r--src/mesa/drivers/dri/nouveau/Makefile50
-rw-r--r--src/mesa/drivers/dri/nouveau/nouveau_bufferobj.c272
-rw-r--r--src/mesa/drivers/dri/nouveau/nouveau_bufferobj.h27
-rw-r--r--src/mesa/drivers/dri/nouveau/nouveau_buffers.c434
-rw-r--r--src/mesa/drivers/dri/nouveau/nouveau_buffers.h48
-rw-r--r--src/mesa/drivers/dri/nouveau/nouveau_card.c17
-rw-r--r--src/mesa/drivers/dri/nouveau/nouveau_card.h49
-rw-r--r--src/mesa/drivers/dri/nouveau/nouveau_card_list.h230
-rw-r--r--src/mesa/drivers/dri/nouveau/nouveau_context.c366
-rw-r--r--src/mesa/drivers/dri/nouveau/nouveau_context.h227
-rw-r--r--src/mesa/drivers/dri/nouveau/nouveau_ctrlreg.h44
-rw-r--r--src/mesa/drivers/dri/nouveau/nouveau_dri.h28
-rw-r--r--src/mesa/drivers/dri/nouveau/nouveau_driver.c146
-rw-r--r--src/mesa/drivers/dri/nouveau/nouveau_driver.h42
-rw-r--r--src/mesa/drivers/dri/nouveau/nouveau_fifo.c137
-rw-r--r--src/mesa/drivers/dri/nouveau/nouveau_fifo.h156
-rw-r--r--src/mesa/drivers/dri/nouveau/nouveau_lock.c81
-rw-r--r--src/mesa/drivers/dri/nouveau/nouveau_lock.h69
-rw-r--r--src/mesa/drivers/dri/nouveau/nouveau_msg.h67
-rw-r--r--src/mesa/drivers/dri/nouveau/nouveau_object.c92
-rw-r--r--src/mesa/drivers/dri/nouveau/nouveau_object.h41
-rw-r--r--src/mesa/drivers/dri/nouveau/nouveau_reg.h1505
-rw-r--r--src/mesa/drivers/dri/nouveau/nouveau_screen.c376
-rw-r--r--src/mesa/drivers/dri/nouveau/nouveau_screen.h61
-rw-r--r--src/mesa/drivers/dri/nouveau/nouveau_shader.c798
-rw-r--r--src/mesa/drivers/dri/nouveau/nouveau_shader.h374
-rw-r--r--src/mesa/drivers/dri/nouveau/nouveau_shader_0_arb.c710
-rw-r--r--src/mesa/drivers/dri/nouveau/nouveau_shader_1.c318
-rw-r--r--src/mesa/drivers/dri/nouveau/nouveau_shader_2.c243
-rw-r--r--src/mesa/drivers/dri/nouveau/nouveau_span.c125
-rw-r--r--src/mesa/drivers/dri/nouveau/nouveau_span.h39
-rw-r--r--src/mesa/drivers/dri/nouveau/nouveau_state.c341
-rw-r--r--src/mesa/drivers/dri/nouveau/nouveau_state.h48
-rw-r--r--src/mesa/drivers/dri/nouveau/nouveau_state_cache.c69
-rw-r--r--src/mesa/drivers/dri/nouveau/nouveau_state_cache.h29
-rw-r--r--src/mesa/drivers/dri/nouveau/nouveau_swtcl.c127
-rw-r--r--src/mesa/drivers/dri/nouveau/nouveau_swtcl.h55
-rw-r--r--src/mesa/drivers/dri/nouveau/nouveau_sync.c136
-rw-r--r--src/mesa/drivers/dri/nouveau/nouveau_sync.h36
-rw-r--r--src/mesa/drivers/dri/nouveau/nouveau_tex.c49
-rw-r--r--src/mesa/drivers/dri/nouveau/nouveau_tex.h38
-rw-r--r--src/mesa/drivers/dri/nouveau/nv04_swtcl.c570
-rw-r--r--src/mesa/drivers/dri/nouveau/nv04_swtcl.h12
-rw-r--r--src/mesa/drivers/dri/nouveau/nv10_state.c746
-rw-r--r--src/mesa/drivers/dri/nouveau/nv10_swtcl.c569
-rw-r--r--src/mesa/drivers/dri/nouveau/nv10_swtcl.h40
-rw-r--r--src/mesa/drivers/dri/nouveau/nv20_shader.h121
-rw-r--r--src/mesa/drivers/dri/nouveau/nv20_state.c662
-rw-r--r--src/mesa/drivers/dri/nouveau/nv20_vertprog.c447
-rw-r--r--src/mesa/drivers/dri/nouveau/nv30_fragprog.c716
-rw-r--r--src/mesa/drivers/dri/nouveau/nv30_shader.h379
-rw-r--r--src/mesa/drivers/dri/nouveau/nv30_state.c901
-rw-r--r--src/mesa/drivers/dri/nouveau/nv30_vertprog.c353
-rw-r--r--src/mesa/drivers/dri/nouveau/nv40_fragprog.c152
-rw-r--r--src/mesa/drivers/dri/nouveau/nv40_shader.h467
-rw-r--r--src/mesa/drivers/dri/nouveau/nv40_vertprog.c685
56 files changed, 14920 insertions, 0 deletions
diff --git a/src/mesa/drivers/dri/nouveau/Makefile b/src/mesa/drivers/dri/nouveau/Makefile
new file mode 100644
index 0000000000..9eb40fb9c1
--- /dev/null
+++ b/src/mesa/drivers/dri/nouveau/Makefile
@@ -0,0 +1,50 @@
+# src/mesa/drivers/dri/nouveau/Makefile
+
+TOP = ../../../../..
+include $(TOP)/configs/current
+
+LIBNAME = nouveau_dri.so
+
+MINIGLX_SOURCES =
+
+DRIVER_SOURCES = \
+ nouveau_bufferobj.c \
+ nouveau_buffers.c \
+ nouveau_card.c \
+ nouveau_context.c \
+ nouveau_driver.c \
+ nouveau_fifo.c \
+ nouveau_lock.c \
+ nouveau_object.c \
+ nouveau_screen.c \
+ nouveau_span.c \
+ nouveau_state.c \
+ nouveau_shader.c \
+ nouveau_shader_0_arb.c \
+ nouveau_shader_1.c \
+ nouveau_shader_2.c \
+ nouveau_tex.c \
+ nouveau_swtcl.c \
+ nouveau_sync.c \
+ nv04_swtcl.c \
+ nv10_swtcl.c \
+ nv10_state.c \
+ nv20_state.c \
+ nv30_state.c \
+ nouveau_state_cache.c \
+ nv20_vertprog.c \
+ nv30_fragprog.c \
+ nv30_vertprog.c \
+ nv40_fragprog.c \
+ nv40_vertprog.c
+
+C_SOURCES = \
+ $(COMMON_SOURCES) \
+ $(DRIVER_SOURCES)
+
+ASM_SOURCES =
+
+
+include ../Makefile.template
+
+symlinks:
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_bufferobj.c b/src/mesa/drivers/dri/nouveau/nouveau_bufferobj.c
new file mode 100644
index 0000000000..d36196aeef
--- /dev/null
+++ b/src/mesa/drivers/dri/nouveau/nouveau_bufferobj.c
@@ -0,0 +1,272 @@
+#include "bufferobj.h"
+#include "enums.h"
+
+#include "nouveau_bufferobj.h"
+#include "nouveau_buffers.h"
+#include "nouveau_context.h"
+#include "nouveau_drm.h"
+#include "nouveau_object.h"
+#include "nouveau_msg.h"
+
+#define DEBUG(fmt,args...) do { \
+ if (NOUVEAU_DEBUG & DEBUG_BUFFEROBJ) { \
+ fprintf(stderr, "%s: "fmt, __func__, ##args); \
+ } \
+} while(0)
+
+/* Wrapper for nouveau_mem_gpu_offset_get() that marks the bufferobj dirty
+ * if the GPU modifies the data.
+ */
+uint32_t
+nouveau_bufferobj_gpu_ref(GLcontext *ctx, GLenum access,
+ struct gl_buffer_object *obj)
+{
+ nouveau_buffer_object *nbo = (nouveau_buffer_object *)obj;
+
+ DEBUG("obj=%p, access=%s\n", obj, _mesa_lookup_enum_by_nr(access));
+
+ if (access == GL_WRITE_ONLY_ARB || access == GL_READ_WRITE_ARB)
+ nbo->gpu_dirty = GL_TRUE;
+
+ return nouveau_mem_gpu_offset_get(ctx, nbo->gpu_mem);
+}
+
+static void
+nouveauBindBuffer(GLcontext *ctx, GLenum target, struct gl_buffer_object *obj)
+{
+}
+
+static struct gl_buffer_object *
+nouveauNewBufferObject(GLcontext *ctx, GLuint buffer, GLenum target)
+{
+ nouveau_buffer_object *nbo;
+
+ nbo = CALLOC_STRUCT(nouveau_buffer_object_t);
+ DEBUG("name=0x%08x, target=%s, obj=%p\n",
+ buffer, _mesa_lookup_enum_by_nr(target), nbo);
+ _mesa_initialize_buffer_object(&nbo->mesa, buffer, target);
+ return &nbo->mesa;
+}
+
+static void
+nouveauDeleteBuffer(GLcontext *ctx, struct gl_buffer_object *obj)
+{
+ nouveau_buffer_object *nbo = (nouveau_buffer_object *)obj;
+
+ DEBUG("obj=%p\n", obj);
+
+ if (nbo->gpu_mem) {
+ nouveau_mem_free(ctx, nbo->gpu_mem);
+ }
+ _mesa_delete_buffer_object(ctx, obj);
+}
+
+static void
+nouveauBufferData(GLcontext *ctx, GLenum target, GLsizeiptrARB size,
+ const GLvoid *data, GLenum usage,
+ struct gl_buffer_object *obj)
+{
+ nouveau_buffer_object *nbo = (nouveau_buffer_object *)obj;
+
+ DEBUG("obj=%p, target=%s, usage=%s, size=%d, data=%p\n",
+ obj,
+ _mesa_lookup_enum_by_nr(target),
+ _mesa_lookup_enum_by_nr(usage),
+ (unsigned int)size,
+ data);
+
+ if (nbo->gpu_mem && nbo->gpu_mem->size != size)
+ nouveau_mem_free(ctx, nbo->gpu_mem);
+
+ /* Always have the GPU access the data from VRAM if possible. For
+ * some "usage" values it may be better from AGP be default?
+ *
+ * TODO: At some point we should drop the NOUVEAU_MEM_MAPPED flag.
+ * TODO: Use the NOUVEAU_MEM_AGP_ACCEPTABLE flag.
+ * TODO: What about PCI-E and shared system memory?
+ */
+ if (!nbo->gpu_mem)
+ nbo->gpu_mem = nouveau_mem_alloc(ctx,
+ NOUVEAU_MEM_FB |
+ NOUVEAU_MEM_MAPPED,
+ size,
+ 0);
+
+ if (!nbo->gpu_mem) {
+ MESSAGE("AIII bufferobj malloc failed\n");
+ return;
+ }
+
+ obj->Usage = usage;
+ obj->Size = size;
+ if (!data)
+ return;
+
+ ctx->Driver.MapBuffer(ctx, target, GL_WRITE_ONLY_ARB, obj);
+ _mesa_memcpy(nbo->cpu_mem->map, data, size);
+ ctx->Driver.UnmapBuffer(ctx, target, obj);
+}
+
+/*TODO: we don't need to DMA the entire buffer like MapBuffer does.. */
+static void
+nouveauBufferSubData(GLcontext *ctx, GLenum target, GLintptrARB offset,
+ GLsizeiptrARB size, const GLvoid *data,
+ struct gl_buffer_object *obj)
+{
+ DEBUG("obj=%p, target=%s, offset=0x%x, size=%d, data=%p\n",
+ obj,
+ _mesa_lookup_enum_by_nr(target),
+ (unsigned int)offset,
+ (unsigned int)size,
+ data);
+
+ ctx->Driver.MapBuffer(ctx, target, GL_WRITE_ONLY_ARB, obj);
+ _mesa_memcpy((GLubyte *)obj->Pointer + offset, data, size);
+ ctx->Driver.UnmapBuffer(ctx, target, obj);
+}
+
+/*TODO: we don't need to DMA the entire buffer like MapBuffer does.. */
+static void
+nouveauGetBufferSubData(GLcontext *ctx, GLenum target, GLintptrARB offset,
+ GLsizeiptrARB size, GLvoid *data,
+ struct gl_buffer_object *obj)
+{
+ DEBUG("obj=%p, target=%s, offset=0x%x, size=%d, data=%p\n",
+ obj,
+ _mesa_lookup_enum_by_nr(target),
+ (unsigned int)offset,
+ (unsigned int)size,
+ data);
+
+ ctx->Driver.MapBuffer(ctx, target, GL_READ_ONLY_ARB, obj);
+ _mesa_memcpy(data, (GLubyte *)obj->Pointer + offset, size);
+ ctx->Driver.UnmapBuffer(ctx, target, obj);
+}
+
+static void *
+nouveauMapBuffer(GLcontext *ctx, GLenum target, GLenum access,
+ struct gl_buffer_object *obj)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ nouveau_buffer_object *nbo = (nouveau_buffer_object *)obj;
+
+ DEBUG("obj=%p, target=%s, access=%s\n",
+ obj,
+ _mesa_lookup_enum_by_nr(target),
+ _mesa_lookup_enum_by_nr(access));
+
+ if (obj->Pointer) {
+ DEBUG("already mapped, return NULL\n");
+ return NULL;
+ }
+
+#ifdef ALLOW_MULTI_SUBCHANNEL
+ /* If GPU is accessing the data from VRAM, copy to faster AGP memory
+ * before CPU access to the buffer.
+ */
+ if (nbo->gpu_mem->type & NOUVEAU_MEM_FB) {
+ DEBUG("Data in VRAM, copying to AGP for CPU access\n");
+
+ /* This can happen if BufferData grows the GPU-access buffer */
+ if (nbo->cpu_mem && nbo->cpu_mem->size != nbo->gpu_mem->size) {
+ nouveau_mem_free(ctx, nbo->cpu_mem);
+ nbo->cpu_mem = NULL;
+ }
+
+ if (!nbo->cpu_mem) {
+ nbo->cpu_mem = nouveau_mem_alloc(ctx,
+ NOUVEAU_MEM_AGP |
+ NOUVEAU_MEM_MAPPED,
+ nbo->gpu_mem->size,
+ 0);
+
+ /* Mark GPU data as modified, so it gets copied to
+ * the new buffer */
+ nbo->gpu_dirty = GL_TRUE;
+ }
+
+ if (nbo->cpu_mem && nbo->gpu_dirty) {
+ nouveau_memformat_flat_emit(ctx, nbo->cpu_mem,
+ nbo->gpu_mem,
+ 0, 0,
+ nbo->gpu_mem->size);
+
+ nouveau_notifier_wait_nop(ctx,
+ nmesa->syncNotifier,
+ NvSubMemFormat);
+ nbo->gpu_dirty = GL_FALSE;
+ }
+
+ /* buffer isn't guaranteed to be up-to-date on the card now */
+ nbo->cpu_dirty = GL_TRUE;
+ }
+#endif
+
+ /* If the copy to AGP failed for some reason, just return a pointer
+ * directly to vram..
+ */
+ if (!nbo->cpu_mem) {
+ DEBUG("Returning direct pointer to VRAM\n");
+ nbo->cpu_mem = nbo->gpu_mem;
+ nbo->cpu_dirty = GL_FALSE;
+ }
+
+ obj->Pointer = nbo->cpu_mem->map;
+ return obj->Pointer;
+}
+
+static GLboolean
+nouveauUnmapBuffer(GLcontext *ctx, GLenum target, struct gl_buffer_object *obj)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ nouveau_buffer_object *nbo = (nouveau_buffer_object *)obj;
+
+ DEBUG("obj=%p, target=%s\n", obj, _mesa_lookup_enum_by_nr(target));
+
+#ifdef ALLOW_MULTI_SUBCHANNEL
+ if (nbo->cpu_dirty && nbo->cpu_mem != nbo->gpu_mem) {
+ DEBUG("Copying potentially modified data back to GPU\n");
+
+ /* blit from GPU buffer -> CPU buffer */
+ nouveau_memformat_flat_emit(ctx, nbo->gpu_mem, nbo->cpu_mem,
+ 0, 0, nbo->cpu_mem->size);
+
+ /* buffer is now up-to-date on the hardware (or rather, will
+ * be by the time any other commands in this channel reference
+ * the data.)
+ */
+ nbo->cpu_dirty = GL_FALSE;
+
+ /* we can avoid this wait in some cases.. */
+ nouveau_notifier_wait_nop(ctx,
+ nmesa->syncNotifier,
+ NvSubMemFormat);
+
+ /* If it's likely CPU access to the buffer will occur often,
+ * keep the cpu_mem around to avoid repeated allocs.
+ */
+ if (obj->Usage != GL_DYNAMIC_DRAW_ARB) {
+
+ nouveau_mem_free(ctx, nbo->cpu_mem);
+ nbo->cpu_mem = NULL;
+ }
+ }
+#endif
+
+ obj->Pointer = NULL;
+ return GL_TRUE;
+}
+
+void
+nouveauInitBufferObjects(GLcontext *ctx)
+{
+ ctx->Driver.BindBuffer = nouveauBindBuffer;
+ ctx->Driver.NewBufferObject = nouveauNewBufferObject;
+ ctx->Driver.DeleteBuffer = nouveauDeleteBuffer;
+ ctx->Driver.BufferData = nouveauBufferData;
+ ctx->Driver.BufferSubData = nouveauBufferSubData;
+ ctx->Driver.GetBufferSubData = nouveauGetBufferSubData;
+ ctx->Driver.MapBuffer = nouveauMapBuffer;
+ ctx->Driver.UnmapBuffer = nouveauUnmapBuffer;
+}
+
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_bufferobj.h b/src/mesa/drivers/dri/nouveau/nouveau_bufferobj.h
new file mode 100644
index 0000000000..fccc349b83
--- /dev/null
+++ b/src/mesa/drivers/dri/nouveau/nouveau_bufferobj.h
@@ -0,0 +1,27 @@
+#ifndef __NOUVEAU_BUFFEROBJ_H__
+#define __NOUVEAU_BUFFEROBJ_H__
+
+#include "mtypes.h"
+#include "nouveau_buffers.h"
+
+typedef struct nouveau_buffer_object_t {
+ /* Base class, must be first */
+ struct gl_buffer_object mesa;
+
+ /* Memory used for GPU access to the buffer*/
+ nouveau_mem * gpu_mem;
+ /* Buffer has been dirtied by the GPU */
+ GLboolean gpu_dirty;
+
+ /* Memory used for CPU access to the buffer */
+ nouveau_mem * cpu_mem;
+ /* Buffer has possibly been dirtied by the CPU */
+ GLboolean cpu_dirty;
+} nouveau_buffer_object;
+
+extern uint32_t nouveau_bufferobj_gpu_ref(GLcontext *ctx, GLenum access,
+ struct gl_buffer_object *obj);
+
+extern void nouveauInitBufferObjects(GLcontext *ctx);
+
+#endif
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_buffers.c b/src/mesa/drivers/dri/nouveau/nouveau_buffers.c
new file mode 100644
index 0000000000..b54f68f402
--- /dev/null
+++ b/src/mesa/drivers/dri/nouveau/nouveau_buffers.c
@@ -0,0 +1,434 @@
+#include "utils.h"
+#include "framebuffer.h"
+#include "renderbuffer.h"
+#include "fbobject.h"
+
+#include "nouveau_context.h"
+#include "nouveau_buffers.h"
+#include "nouveau_object.h"
+#include "nouveau_fifo.h"
+#include "nouveau_reg.h"
+#include "nouveau_msg.h"
+
+#define MAX_MEMFMT_LENGTH 32768
+
+/* Unstrided blit using NV_MEMORY_TO_MEMORY_FORMAT */
+GLboolean
+nouveau_memformat_flat_emit(GLcontext *ctx,
+ nouveau_mem *dst, nouveau_mem *src,
+ GLuint dst_offset, GLuint src_offset,
+ GLuint size)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ uint32_t src_handle, dst_handle;
+ GLuint count;
+
+ if (src_offset + size > src->size) {
+ MESSAGE("src out of nouveau_mem bounds\n");
+ return GL_FALSE;
+ }
+ if (dst_offset + size > dst->size) {
+ MESSAGE("dst out of nouveau_mem bounds\n");
+ return GL_FALSE;
+ }
+
+ src_handle = (src->type & NOUVEAU_MEM_FB) ? NvDmaFB : NvDmaAGP;
+ dst_handle = (dst->type & NOUVEAU_MEM_FB) ? NvDmaFB : NvDmaAGP;
+ src_offset += nouveau_mem_gpu_offset_get(ctx, src);
+ dst_offset += nouveau_mem_gpu_offset_get(ctx, dst);
+
+ BEGIN_RING_SIZE(NvSubMemFormat, NV_MEMORY_TO_MEMORY_FORMAT_OBJECT_IN, 2);
+ OUT_RING (src_handle);
+ OUT_RING (dst_handle);
+
+ count = (size / MAX_MEMFMT_LENGTH) + ((size % MAX_MEMFMT_LENGTH) ? 1 : 0);
+
+ while (count--) {
+ GLuint length = (size > MAX_MEMFMT_LENGTH) ? MAX_MEMFMT_LENGTH : size;
+
+ BEGIN_RING_SIZE(NvSubMemFormat, NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
+ OUT_RING (src_offset);
+ OUT_RING (dst_offset);
+ OUT_RING (0); /* pitch in */
+ OUT_RING (0); /* pitch out */
+ OUT_RING (length); /* line length */
+ OUT_RING (1); /* number of lines */
+ OUT_RING ((1 << 8) /* dst_inc */ | (1 << 0) /* src_inc */);
+ OUT_RING (0); /* buffer notify? */
+ FIRE_RING();
+
+ src_offset += length;
+ dst_offset += length;
+ size -= length;
+ }
+
+ return GL_TRUE;
+}
+
+void
+nouveau_mem_free(GLcontext *ctx, nouveau_mem *mem)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ drm_nouveau_mem_free_t memf;
+
+ if (NOUVEAU_DEBUG & DEBUG_MEM) {
+ fprintf(stderr, "%s: type=0x%x, offset=0x%x, size=0x%x\n",
+ __func__, mem->type, (GLuint)mem->offset, (GLuint)mem->size);
+ }
+
+ if (mem->map)
+ drmUnmap(mem->map, mem->size);
+ memf.flags = mem->type;
+ memf.region_offset = mem->offset;
+ drmCommandWrite(nmesa->driFd, DRM_NOUVEAU_MEM_FREE, &memf, sizeof(memf));
+ FREE(mem);
+}
+
+nouveau_mem *
+nouveau_mem_alloc(GLcontext *ctx, int type, GLuint size, GLuint align)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ drm_nouveau_mem_alloc_t mema;
+ nouveau_mem *mem;
+ int ret;
+
+ if (NOUVEAU_DEBUG & DEBUG_MEM) {
+ fprintf(stderr, "%s: requested: type=0x%x, size=0x%x, align=0x%x\n",
+ __func__, type, (GLuint)size, align);
+ }
+
+ mem = CALLOC(sizeof(nouveau_mem));
+ if (!mem)
+ return NULL;
+
+ mema.flags = type;
+ mema.size = mem->size = size;
+ mema.alignment = align;
+ mem->map = NULL;
+ ret = drmCommandWriteRead(nmesa->driFd, DRM_NOUVEAU_MEM_ALLOC,
+ &mema, sizeof(mema));
+ if (ret) {
+ FREE(mem);
+ return NULL;
+ }
+ mem->offset = mema.region_offset;
+ mem->type = mema.flags;
+
+ if (NOUVEAU_DEBUG & DEBUG_MEM) {
+ fprintf(stderr, "%s: actual: type=0x%x, offset=0x%x, size=0x%x\n",
+ __func__, mem->type, (GLuint)mem->offset, (GLuint)mem->size);
+ }
+
+ if (type & NOUVEAU_MEM_MAPPED)
+ ret = drmMap(nmesa->driFd, mem->offset, mem->size, &mem->map);
+ if (ret) {
+ mem->map = NULL;
+ nouveau_mem_free(ctx, mem);
+ mem = NULL;
+ }
+
+ return mem;
+}
+
+uint32_t
+nouveau_mem_gpu_offset_get(GLcontext *ctx, nouveau_mem *mem)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+
+ if (mem->type & NOUVEAU_MEM_FB)
+ return (uint32_t)mem->offset - nmesa->vram_phys;
+ else if (mem->type & NOUVEAU_MEM_AGP)
+ return (uint32_t)mem->offset - nmesa->agp_phys;
+ else
+ return 0xDEADF00D;
+}
+
+static GLboolean
+nouveau_renderbuffer_pixelformat(nouveau_renderbuffer *nrb,
+ GLenum internalFormat)
+{
+ nrb->mesa.InternalFormat = internalFormat;
+
+ /*TODO: We probably want to extend this a bit, and maybe make
+ * card-specific?
+ */
+ switch (internalFormat) {
+ case GL_RGBA:
+ case GL_RGBA8:
+ nrb->mesa._BaseFormat = GL_RGBA;
+ nrb->mesa._ActualFormat= GL_RGBA8;
+ nrb->mesa.DataType = GL_UNSIGNED_BYTE;
+ nrb->mesa.RedBits = 8;
+ nrb->mesa.GreenBits = 8;
+ nrb->mesa.BlueBits = 8;
+ nrb->mesa.AlphaBits = 8;
+ nrb->cpp = 4;
+ break;
+ case GL_RGB:
+ case GL_RGB5:
+ nrb->mesa._BaseFormat = GL_RGB;
+ nrb->mesa._ActualFormat= GL_RGB5;
+ nrb->mesa.DataType = GL_UNSIGNED_BYTE;
+ nrb->mesa.RedBits = 5;
+ nrb->mesa.GreenBits = 6;
+ nrb->mesa.BlueBits = 5;
+ nrb->mesa.AlphaBits = 0;
+ nrb->cpp = 2;
+ break;
+ case GL_DEPTH_COMPONENT16:
+ nrb->mesa._BaseFormat = GL_DEPTH_COMPONENT;
+ nrb->mesa._ActualFormat= GL_DEPTH_COMPONENT16;
+ nrb->mesa.DataType = GL_UNSIGNED_SHORT;
+ nrb->mesa.DepthBits = 16;
+ nrb->cpp = 2;
+ break;
+ case GL_DEPTH_COMPONENT24:
+ nrb->mesa._BaseFormat = GL_DEPTH_COMPONENT;
+ nrb->mesa._ActualFormat= GL_DEPTH24_STENCIL8_EXT;
+ nrb->mesa.DataType = GL_UNSIGNED_INT_24_8_EXT;
+ nrb->mesa.DepthBits = 24;
+ nrb->cpp = 4;
+ break;
+ case GL_STENCIL_INDEX8_EXT:
+ nrb->mesa._BaseFormat = GL_STENCIL_INDEX;
+ nrb->mesa._ActualFormat= GL_DEPTH24_STENCIL8_EXT;
+ nrb->mesa.DataType = GL_UNSIGNED_INT_24_8_EXT;
+ nrb->mesa.StencilBits = 8;
+ nrb->cpp = 4;
+ break;
+ case GL_DEPTH24_STENCIL8_EXT:
+ nrb->mesa._BaseFormat = GL_DEPTH_STENCIL_EXT;
+ nrb->mesa._ActualFormat= GL_DEPTH24_STENCIL8_EXT;
+ nrb->mesa.DataType = GL_UNSIGNED_INT_24_8_EXT;
+ nrb->mesa.DepthBits = 24;
+ nrb->mesa.StencilBits = 8;
+ nrb->cpp = 4;
+ break;
+ default:
+ return GL_FALSE;
+ break;
+ }
+
+ return GL_TRUE;
+}
+
+static GLboolean
+nouveau_renderbuffer_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
+ GLenum internalFormat,
+ GLuint width,
+ GLuint height)
+{
+ nouveau_renderbuffer *nrb = (nouveau_renderbuffer*)rb;
+
+ if (!nouveau_renderbuffer_pixelformat(nrb, internalFormat)) {
+ fprintf(stderr, "%s: unknown internalFormat\n", __func__);
+ return GL_FALSE;
+ }
+
+ /* If this buffer isn't statically alloc'd, we may need to ask the
+ * drm for more memory */
+ if (!nrb->dPriv && (rb->Width != width || rb->Height != height)) {
+ GLuint pitch;
+
+ /* align pitches to 64 bytes */
+ pitch = ((width * nrb->cpp) + 63) & ~63;
+
+ if (nrb->mem)
+ nouveau_mem_free(ctx, nrb->mem);
+ nrb->mem = nouveau_mem_alloc(ctx,
+ NOUVEAU_MEM_FB | NOUVEAU_MEM_MAPPED,
+ pitch*height,
+ 0);
+ if (!nrb->mem)
+ return GL_FALSE;
+
+ /* update nouveau_renderbuffer info */
+ nrb->offset = nouveau_mem_gpu_offset_get(ctx, nrb->mem);
+ nrb->pitch = pitch;
+ }
+
+ rb->Width = width;
+ rb->Height = height;
+ rb->InternalFormat = internalFormat;
+ return GL_TRUE;
+}
+
+static void
+nouveau_renderbuffer_delete(struct gl_renderbuffer *rb)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ nouveau_renderbuffer *nrb = (nouveau_renderbuffer*)rb;
+
+ if (nrb->mem)
+ nouveau_mem_free(ctx, nrb->mem);
+ FREE(nrb);
+}
+
+nouveau_renderbuffer *
+nouveau_renderbuffer_new(GLenum internalFormat, GLvoid *map,
+ GLuint offset, GLuint pitch,
+ __DRIdrawablePrivate *dPriv)
+{
+ nouveau_renderbuffer *nrb;
+
+ nrb = CALLOC_STRUCT(nouveau_renderbuffer_t);
+ if (nrb) {
+ _mesa_init_renderbuffer(&nrb->mesa, 0);
+
+ nouveau_renderbuffer_pixelformat(nrb, internalFormat);
+
+ nrb->mesa.AllocStorage = nouveau_renderbuffer_storage;
+ nrb->mesa.Delete = nouveau_renderbuffer_delete;
+
+ nrb->dPriv = dPriv;
+ nrb->offset = offset;
+ nrb->pitch = pitch;
+ nrb->map = map;
+ }
+
+ return nrb;
+}
+
+static void
+nouveau_cliprects_drawable_set(nouveauContextPtr nmesa,
+ nouveau_renderbuffer *nrb)
+{
+ __DRIdrawablePrivate *dPriv = nrb->dPriv;
+
+ nmesa->numClipRects = dPriv->numClipRects;
+ nmesa->pClipRects = dPriv->pClipRects;
+ nmesa->drawX = dPriv->x;
+ nmesa->drawY = dPriv->y;
+}
+
+static void
+nouveau_cliprects_renderbuffer_set(nouveauContextPtr nmesa,
+ nouveau_renderbuffer *nrb)
+{
+ nmesa->numClipRects = 1;
+ nmesa->pClipRects = &nmesa->osClipRect;
+ nmesa->osClipRect.x1 = 0;
+ nmesa->osClipRect.y1 = 0;
+ nmesa->osClipRect.x2 = nrb->mesa.Width;
+ nmesa->osClipRect.y2 = nrb->mesa.Height;
+ nmesa->drawX = 0;
+ nmesa->drawY = 0;
+}
+
+void
+nouveau_window_moved(GLcontext *ctx)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ nouveau_renderbuffer *nrb;
+
+ nrb = (nouveau_renderbuffer *)ctx->DrawBuffer->_ColorDrawBuffers[0][0];
+ if (!nrb)
+ return;
+
+ if (!nrb->dPriv)
+ nouveau_cliprects_renderbuffer_set(nmesa, nrb);
+ else
+ nouveau_cliprects_drawable_set(nmesa, nrb);
+
+ /* Viewport depends on window size/position, nouveauCalcViewport
+ * will take care of calling the hw-specific WindowMoved
+ */
+ ctx->Driver.Viewport(ctx, ctx->Viewport.X, ctx->Viewport.Y,
+ ctx->Viewport.Width, ctx->Viewport.Height);
+ /* Scissor depends on window position */
+ ctx->Driver.Scissor(ctx, ctx->Scissor.X, ctx->Scissor.Y,
+ ctx->Scissor.Width, ctx->Scissor.Height);
+}
+
+GLboolean
+nouveau_build_framebuffer(GLcontext *ctx, struct gl_framebuffer *fb)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ nouveau_renderbuffer *color[MAX_DRAW_BUFFERS];
+ nouveau_renderbuffer *depth;
+
+ _mesa_update_framebuffer(ctx);
+ _mesa_update_draw_buffer_bounds(ctx);
+
+ color[0] = (nouveau_renderbuffer *)fb->_ColorDrawBuffers[0][0];
+ if (fb->_DepthBuffer && fb->_DepthBuffer->Wrapped)
+ depth = (nouveau_renderbuffer *)fb->_DepthBuffer->Wrapped;
+ else
+ depth = (nouveau_renderbuffer *)fb->_DepthBuffer;
+
+ if (!nmesa->hw_func.BindBuffers(nmesa, 1, color, depth))
+ return GL_FALSE;
+ nouveau_window_moved(ctx);
+
+ return GL_TRUE;
+}
+
+static void
+nouveauDrawBuffer(GLcontext *ctx, GLenum buffer)
+{
+ nouveau_build_framebuffer(ctx, ctx->DrawBuffer);
+}
+
+static struct gl_framebuffer *
+nouveauNewFramebuffer(GLcontext *ctx, GLuint name)
+{
+ return _mesa_new_framebuffer(ctx, name);
+}
+
+static struct gl_renderbuffer *
+nouveauNewRenderbuffer(GLcontext *ctx, GLuint name)
+{
+ nouveau_renderbuffer *nrb;
+
+ nrb = CALLOC_STRUCT(nouveau_renderbuffer_t);
+ if (nrb) {
+ _mesa_init_renderbuffer(&nrb->mesa, name);
+
+ nrb->mesa.AllocStorage = nouveau_renderbuffer_storage;
+ nrb->mesa.Delete = nouveau_renderbuffer_delete;
+ }
+ return &nrb->mesa;
+}
+
+static void
+nouveauBindFramebuffer(GLcontext *ctx, GLenum target, struct gl_framebuffer *fb)
+{
+ nouveau_build_framebuffer(ctx, fb);
+}
+
+static void
+nouveauFramebufferRenderbuffer(GLcontext *ctx,
+ struct gl_framebuffer *fb,
+ GLenum attachment,
+ struct gl_renderbuffer *rb)
+{
+ _mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb);
+ nouveau_build_framebuffer(ctx, fb);
+}
+
+static void
+nouveauRenderTexture(GLcontext *ctx,
+ struct gl_framebuffer *fb,
+ struct gl_renderbuffer_attachment *att)
+{
+}
+
+static void
+nouveauFinishRenderTexture(GLcontext *ctx,
+ struct gl_renderbuffer_attachment *att)
+{
+}
+
+void
+nouveauInitBufferFuncs(struct dd_function_table *func)
+{
+ func->DrawBuffer = nouveauDrawBuffer;
+
+ func->NewFramebuffer = nouveauNewFramebuffer;
+ func->NewRenderbuffer = nouveauNewRenderbuffer;
+ func->BindFramebuffer = nouveauBindFramebuffer;
+ func->FramebufferRenderbuffer = nouveauFramebufferRenderbuffer;
+ func->RenderTexture = nouveauRenderTexture;
+ func->FinishRenderTexture = nouveauFinishRenderTexture;
+}
+
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_buffers.h b/src/mesa/drivers/dri/nouveau/nouveau_buffers.h
new file mode 100644
index 0000000000..d86455184c
--- /dev/null
+++ b/src/mesa/drivers/dri/nouveau/nouveau_buffers.h
@@ -0,0 +1,48 @@
+#ifndef __NOUVEAU_BUFFERS_H__
+#define __NOUVEAU_BUFFERS_H__
+
+#include <stdint.h>
+#include "mtypes.h"
+#include "utils.h"
+#include "renderbuffer.h"
+
+typedef struct nouveau_mem_t {
+ int type;
+ uint64_t offset;
+ uint64_t size;
+ void* map;
+} nouveau_mem;
+
+extern nouveau_mem *nouveau_mem_alloc(GLcontext *ctx, int type,
+ GLuint size, GLuint align);
+extern void nouveau_mem_free(GLcontext *ctx, nouveau_mem *mem);
+extern uint32_t nouveau_mem_gpu_offset_get(GLcontext *ctx, nouveau_mem *mem);
+
+extern GLboolean nouveau_memformat_flat_emit(GLcontext *ctx,
+ nouveau_mem *dst,
+ nouveau_mem *src,
+ GLuint dst_offset,
+ GLuint src_offset,
+ GLuint size);
+
+typedef struct nouveau_renderbuffer_t {
+ struct gl_renderbuffer mesa; /* must be first! */
+ __DRIdrawablePrivate *dPriv;
+
+ nouveau_mem *mem;
+ void * map;
+
+ int cpp;
+ uint32_t offset;
+ uint32_t pitch;
+} nouveau_renderbuffer;
+
+extern nouveau_renderbuffer *nouveau_renderbuffer_new(GLenum internalFormat,
+ GLvoid *map, GLuint offset, GLuint pitch, __DRIdrawablePrivate *dPriv);
+extern void nouveau_window_moved(GLcontext *ctx);
+extern GLboolean nouveau_build_framebuffer(GLcontext *, struct gl_framebuffer *);
+extern nouveau_renderbuffer *nouveau_current_draw_buffer(GLcontext *ctx);
+
+extern void nouveauInitBufferFuncs(struct dd_function_table *func);
+
+#endif
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_card.c b/src/mesa/drivers/dri/nouveau/nouveau_card.c
new file mode 100644
index 0000000000..91f12f0d70
--- /dev/null
+++ b/src/mesa/drivers/dri/nouveau/nouveau_card.c
@@ -0,0 +1,17 @@
+
+#include "nouveau_card.h"
+#include "nouveau_reg.h"
+#include "nouveau_drm.h"
+#include "nouveau_card_list.h"
+
+
+nouveau_card* nouveau_card_lookup(uint32_t device_id)
+{
+ int i;
+ for(i=0;i<sizeof(nouveau_card_list)/sizeof(nouveau_card)-1;i++)
+ if (nouveau_card_list[i].id==(device_id&0xffff))
+ return &(nouveau_card_list[i]);
+ return NULL;
+}
+
+
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_card.h b/src/mesa/drivers/dri/nouveau/nouveau_card.h
new file mode 100644
index 0000000000..8a4c5f2244
--- /dev/null
+++ b/src/mesa/drivers/dri/nouveau/nouveau_card.h
@@ -0,0 +1,49 @@
+/**************************************************************************
+
+Copyright 2006 Stephane Marchesin
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+
+#ifndef __NOUVEAU_CARD_H__
+#define __NOUVEAU_CARD_H__
+
+#include "dri_util.h"
+#include "drm.h"
+#include "nouveau_drm.h"
+
+typedef struct nouveau_card_t {
+ uint16_t id; /* last 4 digits of pci id, last digit is always 0 */
+ char* name; /* the user-friendly card name */
+ uint32_t class_3d; /* the object class this card uses for 3D */
+ uint32_t type; /* the major card family */
+ uint32_t flags;
+}
+nouveau_card;
+
+#define NV_HAS_LMA 0x00000001
+
+extern nouveau_card* nouveau_card_lookup(uint32_t device_id);
+
+#endif
+
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_card_list.h b/src/mesa/drivers/dri/nouveau/nouveau_card_list.h
new file mode 100644
index 0000000000..14e7b69802
--- /dev/null
+++ b/src/mesa/drivers/dri/nouveau/nouveau_card_list.h
@@ -0,0 +1,230 @@
+static nouveau_card nouveau_card_list[]={
+{0x0008, "EDGE 3D", 0, NV_03, 0},
+{0x0009, "EDGE 3D", 0, NV_03, 0},
+{0x0010, "Mutara V08", 0, NV_03, 0},
+{0x0020, "RIVA TNT", NV04_DX6_MULTITEX_TRIANGLE, NV_04, 0},
+{0x0028, "RIVA TNT2/TNT2 Pro", NV04_DX6_MULTITEX_TRIANGLE, NV_04, 0},
+{0x0029, "RIVA TNT2 Ultra", NV04_DX6_MULTITEX_TRIANGLE, NV_04, 0},
+{0x002A, "Riva TnT2", NV04_DX6_MULTITEX_TRIANGLE, NV_04, 0},
+{0x002B, "Riva TnT2", NV04_DX6_MULTITEX_TRIANGLE, NV_04, 0},
+{0x002C, "Vanta/Vanta LT", NV04_DX6_MULTITEX_TRIANGLE, NV_04, 0},
+{0x002D, "RIVA TNT2 Model 64/Model 64 Pro", NV04_DX6_MULTITEX_TRIANGLE, NV_04, 0},
+{0x002E, "Vanta", NV04_DX6_MULTITEX_TRIANGLE, NV_04, 0},
+{0x002F, "Vanta", NV04_DX6_MULTITEX_TRIANGLE, NV_04, 0},
+{0x0040, "GeForce 6800 Ultra", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
+{0x0041, "GeForce 6800", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
+{0x0042, "GeForce 6800 LE", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
+{0x0043, "NV40.3", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
+{0x0044, "GeForce 6800 XT", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
+{0x0045, "GeForce 6800 GT", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
+{0x0046, "GeForce 6800 GT", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
+{0x0047, "GeForce 6800 GS", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
+{0x0048, "GeForce 6800 XT", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
+{0x0049, "NV40GL", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
+{0x004D, "Quadro FX 4000", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
+{0x004E, "Quadro FX 4000", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
+{0x0090, "GeForce 7800 GTX", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
+{0x0091, "GeForce 7800 GTX", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
+{0x0092, "GeForce 7800 GT", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
+{0x0093, "GeForce 7800 GS", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
+{0x0098, "GeForce Go 7800", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
+{0x0099, "GE Force Go 7800 GTX", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
+{0x009D, "Quadro FX4500", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
+{0x00A0, "Aladdin TNT2", NV04_DX6_MULTITEX_TRIANGLE, NV_04, 0},
+{0x00C0, "GeForce 6800 GS", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
+{0x00C1, "GeForce 6800", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
+{0x00C2, "GeForce 6800 LE", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
+{0x00C3, "Geforce 6800 XT", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
+{0x00C8, "GeForce Go 6800", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
+{0x00C9, "GeForce Go 6800 Ultra", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
+{0x00CC, "Quadro FX Go1400", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
+{0x00CD, "Quadro FX 3450/4000 SDI", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
+{0x00CE, "Quadro FX 1400", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
+{0x00F0, "GeForce 6800/GeForce 6800 Ultra", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
+{0x00F1, "GeForce 6600/GeForce 6600 GT", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
+{0x00F2, "GeForce 6600/GeForce 6600 GT", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
+{0x00F3, "GeForce 6200", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
+{0x00F4, "GeForce 6600 LE", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
+{0x00F5, "GeForce 7800 GS", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
+{0x00F6, "GeForce 6600 GS", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
+{0x00F8, "Quadro FX 3400/4400", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
+{0x00F9, "GeForce 6800 Ultra/GeForce 6800 GT", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
+{0x00FA, "GeForce PCX 5750", NV30_TCL_PRIMITIVE_3D|0x3000, NV_30, 0},
+{0x00FB, "GeForce PCX 5900", NV30_TCL_PRIMITIVE_3D|0x0400, NV_30, 0},
+{0x00FC, "Quadro FX 330/GeForce PCX 5300", NV30_TCL_PRIMITIVE_3D|0x0600, NV_30, 0},
+{0x00FD, "Quadro FX 330/Quadro NVS280", NV30_TCL_PRIMITIVE_3D|0x0600, NV_30, 0},
+{0x00FE, "Quadro FX 1300", NV30_TCL_PRIMITIVE_3D|0x3000, NV_30, 0},
+{0x00FF, "GeForce PCX 4300", NV17_TCL_PRIMITIVE_3D, NV_17, 0},
+{0x0100, "GeForce 256 SDR", NV10_TCL_PRIMITIVE_3D, NV_10, 0},
+{0x0101, "GeForce 256 DDR", NV10_TCL_PRIMITIVE_3D, NV_10, 0},
+{0x0103, "Quadro", NV10_TCL_PRIMITIVE_3D, NV_10, 0},
+{0x0110, "GeForce2 MX/MX 400", NV11_TCL_PRIMITIVE_3D, NV_11, 0},
+{0x0111, "GeForce2 MX 100 DDR/200 DDR", NV11_TCL_PRIMITIVE_3D, NV_11, 0},
+{0x0112, "GeForce2 Go", NV11_TCL_PRIMITIVE_3D, NV_11, 0},
+{0x0113, "Quadro2 MXR/EX/Go", NV11_TCL_PRIMITIVE_3D, NV_11, 0},
+{0x0140, "GeForce 6600 GT", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
+{0x0141, "GeForce 6600", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
+{0x0142, "GeForce 6600 PCIe", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
+{0x0144, "GeForce Go 6600", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
+{0x0145, "GeForce 6610 XL", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
+{0x0146, "Geforce Go 6600TE/6200TE", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
+{0x0148, "GeForce Go 6600", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
+{0x0149, "GeForce Go 6600 GT", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
+{0x014A, "Quadro NVS 440", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
+{0x014D, "Quadro FX 550", NV17_TCL_PRIMITIVE_3D, NV_17, 0},
+{0x014E, "Quadro FX 540", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
+{0x014F, "GeForce 6200", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
+{0x0150, "GeForce2 GTS/Pro", NV11_TCL_PRIMITIVE_3D, NV_15, 0},
+{0x0151, "GeForce2 Ti", NV11_TCL_PRIMITIVE_3D, NV_15, 0},
+{0x0152, "GeForce2 Ultra, Bladerunner", NV11_TCL_PRIMITIVE_3D, NV_15, 0},
+{0x0153, "Quadro2 Pro", NV11_TCL_PRIMITIVE_3D, NV_15, 0},
+{0x0161, "GeForce 6200 TurboCache(TM)", NV30_TCL_PRIMITIVE_3D|0x4400, NV_44, 0},
+{0x0162, "GeForce 6200 SE TurboCache (TM)", NV30_TCL_PRIMITIVE_3D|0x4400, NV_44, 0},
+{0x0163, "GeForce 6200 LE", NV30_TCL_PRIMITIVE_3D|0x4400, NV_44, 0},
+{0x0164, "GeForce Go 6200", NV30_TCL_PRIMITIVE_3D|0x4400, NV_44, 0},
+{0x0165, "Quadro NVS 285", NV30_TCL_PRIMITIVE_3D|0x4400, NV_44, 0},
+{0x0166, "GeForce Go 6400", NV30_TCL_PRIMITIVE_3D|0x4400, NV_44, 0},
+{0x0167, "GeForce Go 6200 TurboCache", NV30_TCL_PRIMITIVE_3D|0x4400, NV_44, 0},
+{0x0168, "GeForce Go 6200 TurboCache", NV30_TCL_PRIMITIVE_3D|0x4400, NV_44, 0},
+{0x0170, "GeForce4 MX 460", NV17_TCL_PRIMITIVE_3D, NV_17, 0},
+{0x0171, "GeForce4 MX 440", NV17_TCL_PRIMITIVE_3D, NV_17, 0},
+{0x0172, "GeForce4 MX 420", NV17_TCL_PRIMITIVE_3D, NV_17, 0},
+{0x0173, "GeForce4 MX 440-SE", NV17_TCL_PRIMITIVE_3D, NV_17, 0},
+{0x0174, "GeForce4 440 Go", NV17_TCL_PRIMITIVE_3D, NV_17, 0},
+{0x0175, "GeForce4 420 Go", NV17_TCL_PRIMITIVE_3D, NV_17, 0},
+{0x0176, "GeForce4 420 Go 32M", NV17_TCL_PRIMITIVE_3D, NV_17, 0},
+{0x0177, "GeForce4 460 Go", NV17_TCL_PRIMITIVE_3D, NV_17, 0},
+{0x0178, "Quadro4 550 XGL", NV17_TCL_PRIMITIVE_3D, NV_17, 0},
+{0x0179, "GeForce4 420 Go 32M", NV17_TCL_PRIMITIVE_3D, NV_17, 0},
+{0x017A, "Quadro4 200/400 NVS", NV17_TCL_PRIMITIVE_3D, NV_17, 0},
+{0x017B, "Quadro4 550 XGL", NV17_TCL_PRIMITIVE_3D, NV_17, 0},
+{0x017C, "Quadro4 500 GoGL", NV17_TCL_PRIMITIVE_3D, NV_17, 0},
+{0x017D, "GeForce4 410 Go 16M", NV17_TCL_PRIMITIVE_3D, NV_17, 0},
+{0x0181, "GeForce4 MX 440 AGP 8x", NV17_TCL_PRIMITIVE_3D, NV_17, 0},
+{0x0182, "GeForce4 MX 440SE AGP 8x", NV17_TCL_PRIMITIVE_3D, NV_17, 0},
+{0x0183, "GeForce4 MX 420 AGP 8x", NV17_TCL_PRIMITIVE_3D, NV_17, 0},
+{0x0185, "GeForce4 MX 4000 AGP 8x", NV17_TCL_PRIMITIVE_3D, NV_17, 0},
+{0x0186, "GeForce4 448 Go", NV17_TCL_PRIMITIVE_3D, NV_17, 0},
+{0x0187, "GeForce4 488 Go", NV17_TCL_PRIMITIVE_3D, NV_17, 0},
+{0x0188, "Quadro4 580 XGL", NV17_TCL_PRIMITIVE_3D, NV_17, 0},
+{0x018A, "Quadro4 NVS AGP 8x", NV17_TCL_PRIMITIVE_3D, NV_17, 0},
+{0x018B, "Quadro4 380 XGL", NV17_TCL_PRIMITIVE_3D, NV_17, 0},
+{0x018C, "Quadro NVS 50 PCI", NV17_TCL_PRIMITIVE_3D, NV_17, 0},
+{0x018D, "GeForce4 448 Go", NV17_TCL_PRIMITIVE_3D, NV_17, 0},
+{0x0191, "GeForce 8800 GTX", NV30_TCL_PRIMITIVE_3D|0x5000, NV_50, 0},
+{0x0193, "GeForce 8800 GTS", NV30_TCL_PRIMITIVE_3D|0x5000, NV_50, 0},
+{0x01A0, "GeForce2 MX Integrated Graphics", NV11_TCL_PRIMITIVE_3D, NV_11, 0},
+{0x01D1, "GeForce 7300 LE", NV30_TCL_PRIMITIVE_3D|0x4400, NV_44, 0},
+{0x01D6, "GeForce Go 7200", NV30_TCL_PRIMITIVE_3D|0x4400, NV_44, 0},
+{0x01D7, "Quadro NVS 110M / GeForce Go 7300", NV30_TCL_PRIMITIVE_3D|0x4400, NV_44, 0},
+{0x01D8, "GeForce Go 7400", NV30_TCL_PRIMITIVE_3D|0x4400, NV_44, 0},
+{0x01DA, "Quadro NVS 110M", NV30_TCL_PRIMITIVE_3D|0x4400, NV_44, 0},
+{0x01DF, "GeForce 7300 GS", NV30_TCL_PRIMITIVE_3D|0x4400, NV_44, 0},
+{0x01F0, "GeForce4 MX - nForce GPU", NV17_TCL_PRIMITIVE_3D, NV_17, 0},
+{0x0200, "GeForce3", NV20_TCL_PRIMITIVE_3D|0x2000, NV_20, 0},
+{0x0201, "GeForce3 Ti 200", NV20_TCL_PRIMITIVE_3D|0x2000, NV_20, 0},
+{0x0202, "GeForce3 Ti 500", NV20_TCL_PRIMITIVE_3D|0x2000, NV_20, 0},
+{0x0203, "Quadro DCC", NV20_TCL_PRIMITIVE_3D|0x2000, NV_20, 0},
+{0x0211, "GeForce 6800", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
+{0x0212, "GeForce 6800 LE", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
+{0x0215, "GeForce 6800 GT", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
+{0x0218, "GeForce 6800 XT", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
+{0x0221, "GeForce 6200", NV30_TCL_PRIMITIVE_3D|0x4400, NV_44, 0},
+{0x0240, "GeForce 6150", NV30_TCL_PRIMITIVE_3D|0x4400, NV_44, 0},
+{0x0242, "GeForce 6100", NV30_TCL_PRIMITIVE_3D|0x4400, NV_44, 0},
+{0x0244, "GeForce 6150 Go", NV30_TCL_PRIMITIVE_3D|0x4400, NV_44, 0},
+{0x0250, "GeForce4 Ti 4600", NV20_TCL_PRIMITIVE_3D|0x2500, NV_25, 0},
+{0x0251, "GeForce4 Ti 4400", NV20_TCL_PRIMITIVE_3D|0x2500, NV_25, 0},
+{0x0252, "GeForce4 Ti", NV20_TCL_PRIMITIVE_3D|0x2500, NV_25, 0},
+{0x0253, "GeForce4 Ti 4200", NV20_TCL_PRIMITIVE_3D|0x2500, NV_25, 0},
+{0x0258, "Quadro4 900 XGL", NV20_TCL_PRIMITIVE_3D|0x2500, NV_25, 0},
+{0x0259, "Quadro4 750 XGL", NV20_TCL_PRIMITIVE_3D|0x2500, NV_25, 0},
+{0x025B, "Quadro4 700 XGL", NV20_TCL_PRIMITIVE_3D|0x2500, NV_25, 0},
+{0x0280, "GeForce4 Ti 4800", NV20_TCL_PRIMITIVE_3D|0x2500, NV_25, 0},
+{0x0281, "GeForce4 Ti 4200 AGP 8x", NV20_TCL_PRIMITIVE_3D|0x2500, NV_25, 0},
+{0x0282, "GeForce4 Ti 4800 SE", NV20_TCL_PRIMITIVE_3D|0x2500, NV_25, 0},
+{0x0286, "GeForce4 Ti 4200 Go AGP 8x", NV20_TCL_PRIMITIVE_3D|0x2500, NV_25, 0},
+{0x0288, "Quadro4 980 XGL", NV20_TCL_PRIMITIVE_3D|0x2500, NV_25, 0},
+{0x0289, "Quadro4 780 XGL", NV20_TCL_PRIMITIVE_3D|0x2500, NV_25, 0},
+{0x028C, "Quadro4 700 GoGL", NV20_TCL_PRIMITIVE_3D|0x2500, NV_25, 0},
+{0x0290, "GeForce 7900 GTX", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
+{0x0291, "GeForce 7900 GT", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
+{0x0292, "GeForce 7900 GS", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
+{0x0298, "GeForce Go 7900 GS", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
+{0x0299, "GeForce Go 7900 GTX", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
+{0x029A, "Quadro FX 2500M", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
+{0x029B, "Quadro FX 1500M", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
+{0x029C, "Quadro FX 5500", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
+{0x029D, "Quadro FX 3500", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
+{0x029E, "Quadro FX 1500", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
+{0x029F, "Quadro FX 4500 X2", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
+{0x02A0, "XGPU", NV20_TCL_PRIMITIVE_3D|0x2000, NV_20, 0},
+{0x02E1, "GeForce 7600 GS", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
+{0x0300, "GeForce FX", NV30_TCL_PRIMITIVE_3D|0x3000, NV_30, 0},
+{0x0301, "GeForce FX 5800 Ultra", NV30_TCL_PRIMITIVE_3D|0x3000, NV_30, 0},
+{0x0302, "GeForce FX 5800", NV30_TCL_PRIMITIVE_3D|0x3000, NV_30, 0},
+{0x0308, "Quadro FX 2000", NV30_TCL_PRIMITIVE_3D|0x3000, NV_30, 0},
+{0x0309, "Quadro FX 1000", NV30_TCL_PRIMITIVE_3D|0x3000, NV_30, 0},
+{0x0311, "GeForce FX 5600 Ultra", NV30_TCL_PRIMITIVE_3D|0x3000, NV_30, 0},
+{0x0312, "GeForce FX 5600", NV30_TCL_PRIMITIVE_3D|0x3000, NV_30, 0},
+{0x0313, "NV31", NV30_TCL_PRIMITIVE_3D|0x3000, NV_30, 0},
+{0x0314, "GeForce FX 5600XT", NV30_TCL_PRIMITIVE_3D|0x3000, NV_30, 0},
+{0x0316, "NV31M", NV30_TCL_PRIMITIVE_3D|0x3000, NV_30, 0},
+{0x0317, "NV31M Pro", NV30_TCL_PRIMITIVE_3D|0x3000, NV_30, 0},
+{0x031A, "GeForce FX Go5600", NV30_TCL_PRIMITIVE_3D|0x3000, NV_30, 0},
+{0x031B, "GeForce FX Go5650", NV30_TCL_PRIMITIVE_3D|0x3000, NV_30, 0},
+{0x031D, "NV31GLM", NV30_TCL_PRIMITIVE_3D|0x3000, NV_30, 0},
+{0x031E, "NV31GLM Pro", NV30_TCL_PRIMITIVE_3D|0x3000, NV_30, 0},
+{0x031F, "NV31GLM Pro", NV30_TCL_PRIMITIVE_3D|0x3000, NV_30, 0},
+{0x0320, "GeForce FX 5200", NV30_TCL_PRIMITIVE_3D|0x3400, NV_34, 0},
+{0x0321, "GeForce FX 5200 Ultra", NV30_TCL_PRIMITIVE_3D|0x3400, NV_34, 0},
+{0x0322, "GeForce FX 5200", NV30_TCL_PRIMITIVE_3D|0x3400, NV_34, 0},
+{0x0323, "GeForce FX 5200LE", NV30_TCL_PRIMITIVE_3D|0x3400, NV_34, 0},
+{0x0324, "GeForce FX Go5200", NV30_TCL_PRIMITIVE_3D|0x3400, NV_34, 0},
+{0x0325, "GeForce FX Go5250", NV30_TCL_PRIMITIVE_3D|0x3400, NV_34, 0},
+{0x0326, "GeForce FX 5500", NV30_TCL_PRIMITIVE_3D|0x3400, NV_34, 0},
+{0x0327, "GeForce FX 5100", NV30_TCL_PRIMITIVE_3D|0x3400, NV_34, 0},
+{0x0328, "GeForce FX Go5200 32M/64M", NV30_TCL_PRIMITIVE_3D|0x3400, NV_34, 0},
+{0x0329, "GeForce FX Go5200", NV30_TCL_PRIMITIVE_3D|0x3400, NV_34, 0},
+{0x032A, "Quadro NVS 280 PCI", NV30_TCL_PRIMITIVE_3D|0x3400, NV_34, 0},
+{0x032B, "Quadro FX 500/600 PCI", NV30_TCL_PRIMITIVE_3D|0x3400, NV_34, 0},
+{0x032C, "GeForce FX Go 5300", NV30_TCL_PRIMITIVE_3D|0x3400, NV_34, 0},
+{0x032D, "GeForce FX Go5100", NV30_TCL_PRIMITIVE_3D|0x3400, NV_34, 0},
+{0x032F, "NV34GL", NV30_TCL_PRIMITIVE_3D|0x3400, NV_34, 0},
+{0x0330, "GeForce FX 5900 Ultra", NV30_TCL_PRIMITIVE_3D|0x0400, NV_30, 0},
+{0x0331, "GeForce FX 5900", NV30_TCL_PRIMITIVE_3D|0x0400, NV_30, 0},
+{0x0332, "GeForce FX 5900XT", NV30_TCL_PRIMITIVE_3D|0x0400, NV_30, 0},
+{0x0333, "GeForce FX 5950 Ultra", NV30_TCL_PRIMITIVE_3D|0x3000, NV_30, 0},
+{0x0334, "GeForce FX 5900ZT", NV30_TCL_PRIMITIVE_3D|0x0400, NV_30, 0},
+{0x0338, "Quadro FX 3000", NV30_TCL_PRIMITIVE_3D|0x3000, NV_30, 0},
+{0x033F, "Quadro FX 700", NV30_TCL_PRIMITIVE_3D|0x3000, NV_30, 0},
+{0x0341, "GeForce FX 5700 Ultra", NV30_TCL_PRIMITIVE_3D|0x3000, NV_30, 0},
+{0x0342, "GeForce FX 5700", NV30_TCL_PRIMITIVE_3D|0x3000, NV_30, 0},
+{0x0343, "GeForce FX 5700LE", NV30_TCL_PRIMITIVE_3D|0x3000, NV_30, 0},
+{0x0344, "GeForce FX 5700VE", NV30_TCL_PRIMITIVE_3D|0x3000, NV_30, 0},
+{0x0345, "NV36.5", NV30_TCL_PRIMITIVE_3D|0x3000, NV_30, 0},
+{0x0347, "GeForce FX Go5700", NV30_TCL_PRIMITIVE_3D|0x3000, NV_30, 0},
+{0x0348, "GeForce FX Go5700", NV30_TCL_PRIMITIVE_3D|0x3000, NV_30, 0},
+{0x0349, "NV36M Pro", NV30_TCL_PRIMITIVE_3D|0x3000, NV_30, 0},
+{0x034B, "NV36MAP", NV30_TCL_PRIMITIVE_3D|0x3000, NV_30, 0},
+{0x034C, "Quadro FX Go1000", NV30_TCL_PRIMITIVE_3D|0x3000, NV_30, 0},
+{0x034E, "Quadro FX 1100", NV30_TCL_PRIMITIVE_3D|0x3000, NV_30, 0},
+{0x034F, "NV36GL", NV30_TCL_PRIMITIVE_3D|0x3000, NV_30, 0},
+{0x0391, "GeForce 7600 GT", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
+{0x0392, "GeForce 7600 GS", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
+{0x0393, "GeForce 7300 GT", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
+{0x0398, "GeForce Go 7600", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0},
+{0x03D0, "GeForce 6100 nForce 430", NV30_TCL_PRIMITIVE_3D|0x4400, NV_44, 0},
+{0x03D1, "GeForce 6100 nForce 405", NV30_TCL_PRIMITIVE_3D|0x4400, NV_44, 0},
+{0x03D2, "GeForce 6100 nForce 400", NV30_TCL_PRIMITIVE_3D|0x4400, NV_44, 0},
+{0x03D5, "GeForce 6100 nForce 420", NV30_TCL_PRIMITIVE_3D|0x4400, NV_44, 0},
+{0x0008, "NV1", 0, NV_03, 0},
+{0x0009, "DAC64", 0, NV_03, 0},
+{0x0018, "Riva128", 0, NV_03, 0},
+{0x0019, "Riva128ZX", 0, NV_03, 0},
+{0x0020, "TNT", NV04_DX6_MULTITEX_TRIANGLE, NV_04, 0},
+{0x0028, "TNT2", NV04_DX6_MULTITEX_TRIANGLE, NV_04, 0},
+{0x0029, "UTNT2", NV04_DX6_MULTITEX_TRIANGLE, NV_04, 0},
+{0x002C, "VTNT2", NV04_DX6_MULTITEX_TRIANGLE, NV_04, 0},
+{0x00A0, "ITNT2", NV04_DX6_MULTITEX_TRIANGLE, NV_04, 0},
+};
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_context.c b/src/mesa/drivers/dri/nouveau/nouveau_context.c
new file mode 100644
index 0000000000..c86ff603f6
--- /dev/null
+++ b/src/mesa/drivers/dri/nouveau/nouveau_context.c
@@ -0,0 +1,366 @@
+/**************************************************************************
+
+Copyright 2006 Stephane Marchesin
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+#include "glheader.h"
+#include "context.h"
+#include "simple_list.h"
+#include "imports.h"
+#include "matrix.h"
+#include "swrast/swrast.h"
+#include "swrast_setup/swrast_setup.h"
+#include "framebuffer.h"
+
+#include "tnl/tnl.h"
+#include "tnl/t_pipeline.h"
+#include "tnl/t_vp_build.h"
+
+#include "drivers/common/driverfuncs.h"
+
+#include "nouveau_context.h"
+#include "nouveau_driver.h"
+//#include "nouveau_state.h"
+#include "nouveau_span.h"
+#include "nouveau_object.h"
+#include "nouveau_fifo.h"
+#include "nouveau_tex.h"
+#include "nouveau_msg.h"
+#include "nouveau_reg.h"
+#include "nouveau_lock.h"
+#include "nv10_swtcl.h"
+
+#include "vblank.h"
+#include "utils.h"
+#include "texmem.h"
+#include "xmlpool.h" /* for symbolic values of enum-type options */
+
+#ifndef NOUVEAU_DEBUG
+int NOUVEAU_DEBUG = 0;
+#endif
+
+static const struct dri_debug_control debug_control[] =
+{
+ { "shaders" , DEBUG_SHADERS },
+ { "mem" , DEBUG_MEM },
+ { "bufferobj" , DEBUG_BUFFEROBJ },
+ { NULL , 0 }
+};
+
+#define need_GL_ARB_vertex_program
+#include "extension_helper.h"
+
+const struct dri_extension common_extensions[] =
+{
+ { NULL, 0 }
+};
+
+const struct dri_extension nv10_extensions[] =
+{
+ { NULL, 0 }
+};
+
+const struct dri_extension nv20_extensions[] =
+{
+ { NULL, 0 }
+};
+
+const struct dri_extension nv30_extensions[] =
+{
+ { "GL_ARB_fragment_program", NULL },
+ { NULL, 0 }
+};
+
+const struct dri_extension nv40_extensions[] =
+{
+ /* ARB_vp can be moved to nv20/30 once the shader backend has been
+ * written for those cards.
+ */
+ { "GL_ARB_vertex_program", GL_ARB_vertex_program_functions },
+ { NULL, 0 }
+};
+
+const struct dri_extension nv50_extensions[] =
+{
+ { NULL, 0 }
+};
+
+/* Create the device specific context.
+ */
+GLboolean nouveauCreateContext( const __GLcontextModes *glVisual,
+ __DRIcontextPrivate *driContextPriv,
+ void *sharedContextPrivate )
+{
+ GLcontext *ctx, *shareCtx;
+ __DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv;
+ struct dd_function_table functions;
+ nouveauContextPtr nmesa;
+ nouveauScreenPtr screen;
+
+ /* Allocate the context */
+ nmesa = (nouveauContextPtr) CALLOC( sizeof(*nmesa) );
+ if ( !nmesa )
+ return GL_FALSE;
+
+ nmesa->driContext = driContextPriv;
+ nmesa->driScreen = sPriv;
+ nmesa->driDrawable = NULL;
+ nmesa->hHWContext = driContextPriv->hHWContext;
+ nmesa->driHwLock = &sPriv->pSAREA->lock;
+ nmesa->driFd = sPriv->fd;
+
+ nmesa->screen = (nouveauScreenPtr)(sPriv->private);
+ screen=nmesa->screen;
+
+ /* Create the hardware context */
+ if (!nouveauDRMGetParam(nmesa, NOUVEAU_GETPARAM_FB_PHYSICAL,
+ &nmesa->vram_phys))
+ return GL_FALSE;
+ if (!nouveauDRMGetParam(nmesa, NOUVEAU_GETPARAM_AGP_PHYSICAL,
+ &nmesa->agp_phys))
+ return GL_FALSE;
+ if (!nouveauFifoInit(nmesa))
+ return GL_FALSE;
+ nouveauObjectInit(nmesa);
+
+
+ /* Init default driver functions then plug in our nouveau-specific functions
+ * (the texture functions are especially important)
+ */
+ _mesa_init_driver_functions( &functions );
+ nouveauDriverInitFunctions( &functions );
+ nouveauTexInitFunctions( &functions );
+
+ /* Allocate the Mesa context */
+ if (sharedContextPrivate)
+ shareCtx = ((nouveauContextPtr) sharedContextPrivate)->glCtx;
+ else
+ shareCtx = NULL;
+ nmesa->glCtx = _mesa_create_context(glVisual, shareCtx,
+ &functions, (void *) nmesa);
+ if (!nmesa->glCtx) {
+ FREE(nmesa);
+ return GL_FALSE;
+ }
+ driContextPriv->driverPrivate = nmesa;
+ ctx = nmesa->glCtx;
+
+ /* Parse configuration files */
+ driParseConfigFiles (&nmesa->optionCache, &screen->optionCache,
+ screen->driScreen->myNum, "nouveau");
+
+ nmesa->sarea = (drm_nouveau_sarea_t *)((char *)sPriv->pSAREA +
+ screen->sarea_priv_offset);
+
+ /* Enable any supported extensions */
+ driInitExtensions(ctx, common_extensions, GL_TRUE);
+ if (nmesa->screen->card->type >= NV_10)
+ driInitExtensions(ctx, nv10_extensions, GL_FALSE);
+ if (nmesa->screen->card->type >= NV_20)
+ driInitExtensions(ctx, nv20_extensions, GL_FALSE);
+ if (nmesa->screen->card->type >= NV_30)
+ driInitExtensions(ctx, nv30_extensions, GL_FALSE);
+ if (nmesa->screen->card->type >= NV_40)
+ driInitExtensions(ctx, nv40_extensions, GL_FALSE);
+ if (nmesa->screen->card->type >= NV_50)
+ driInitExtensions(ctx, nv50_extensions, GL_FALSE);
+
+ nmesa->current_primitive = -1;
+
+ nouveauShaderInitFuncs(ctx);
+ /* Install Mesa's fixed-function texenv shader support */
+ if (nmesa->screen->card->type >= NV_40)
+ ctx->_MaintainTexEnvProgram = GL_TRUE;
+
+ /* Initialize the swrast */
+ _swrast_CreateContext( ctx );
+ _vbo_CreateContext( ctx );
+ _tnl_CreateContext( ctx );
+ _swsetup_CreateContext( ctx );
+
+ _math_matrix_ctr(&nmesa->viewport);
+
+ nouveauDDInitStateFuncs( ctx );
+ nouveauSpanInitFunctions( ctx );
+ nouveauDDInitState( nmesa );
+ switch(nmesa->screen->card->type)
+ {
+ case NV_03:
+ //nv03TriInitFunctions( ctx );
+ break;
+ case NV_04:
+ case NV_05:
+ //nv04TriInitFunctions( ctx );
+ break;
+ case NV_10:
+ case NV_20:
+ case NV_30:
+ case NV_40:
+ case NV_44:
+ case NV_50:
+ default:
+ nv10TriInitFunctions( ctx );
+ break;
+ }
+
+ nouveauInitBufferObjects(ctx);
+ if (!nouveauSyncInitFuncs(ctx))
+ return GL_FALSE;
+ nmesa->hw_func.InitCard(nmesa);
+ nouveauInitState(ctx);
+
+ driContextPriv->driverPrivate = (void *)nmesa;
+
+ NOUVEAU_DEBUG = driParseDebugString( getenv( "NOUVEAU_DEBUG" ),
+ debug_control );
+
+ if (driQueryOptionb(&nmesa->optionCache, "no_rast")) {
+ fprintf(stderr, "disabling 3D acceleration\n");
+ FALLBACK(nmesa, NOUVEAU_FALLBACK_DISABLE, 1);
+ }
+
+ return GL_TRUE;
+}
+
+/* Destroy the device specific context. */
+void nouveauDestroyContext( __DRIcontextPrivate *driContextPriv )
+{
+ nouveauContextPtr nmesa = (nouveauContextPtr) driContextPriv->driverPrivate;
+
+ assert(nmesa);
+ if ( nmesa ) {
+ /* free the option cache */
+ driDestroyOptionCache (&nmesa->optionCache);
+
+ FREE( nmesa );
+ }
+
+}
+
+
+/* Force the context `c' to be the current context and associate with it
+ * buffer `b'.
+ */
+GLboolean nouveauMakeCurrent( __DRIcontextPrivate *driContextPriv,
+ __DRIdrawablePrivate *driDrawPriv,
+ __DRIdrawablePrivate *driReadPriv )
+{
+ if ( driContextPriv ) {
+ nouveauContextPtr nmesa = (nouveauContextPtr) driContextPriv->driverPrivate;
+ struct gl_framebuffer *draw_fb =
+ (struct gl_framebuffer*)driDrawPriv->driverPrivate;
+ struct gl_framebuffer *read_fb =
+ (struct gl_framebuffer*)driReadPriv->driverPrivate;
+
+ driDrawableInitVBlank(driDrawPriv, nmesa->vblank_flags, &nmesa->vblank_seq );
+ nmesa->driDrawable = driDrawPriv;
+
+ _mesa_resize_framebuffer(nmesa->glCtx, draw_fb,
+ driDrawPriv->w, driDrawPriv->h);
+ if (draw_fb != read_fb) {
+ _mesa_resize_framebuffer(nmesa->glCtx, draw_fb,
+ driReadPriv->w,
+ driReadPriv->h);
+ }
+ _mesa_make_current(nmesa->glCtx, draw_fb, read_fb);
+
+ nouveau_build_framebuffer(nmesa->glCtx,
+ driDrawPriv->driverPrivate);
+ } else {
+ _mesa_make_current( NULL, NULL, NULL );
+ }
+
+ return GL_TRUE;
+}
+
+
+/* Force the context `c' to be unbound from its buffer.
+ */
+GLboolean nouveauUnbindContext( __DRIcontextPrivate *driContextPriv )
+{
+ return GL_TRUE;
+}
+
+static void nouveauDoSwapBuffers(nouveauContextPtr nmesa,
+ __DRIdrawablePrivate *dPriv)
+{
+ struct gl_framebuffer *fb;
+ nouveau_renderbuffer *src, *dst;
+ drm_clip_rect_t *box;
+ int nbox, i;
+
+ fb = (struct gl_framebuffer *)dPriv->driverPrivate;
+ dst = (nouveau_renderbuffer*)
+ fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer;
+ src = (nouveau_renderbuffer*)
+ fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer;
+
+#ifdef ALLOW_MULTI_SUBCHANNEL
+ LOCK_HARDWARE(nmesa);
+ nbox = dPriv->numClipRects;
+ box = dPriv->pClipRects;
+
+ if (nbox) {
+ BEGIN_RING_SIZE(NvSubCtxSurf2D,
+ NV10_CONTEXT_SURFACES_2D_FORMAT, 4);
+ if (src->mesa._ActualFormat == GL_RGBA8)
+ OUT_RING (6); /* X8R8G8B8 */
+ else
+ OUT_RING (4); /* R5G6B5 */
+ OUT_RING ((dst->pitch << 16) | src->pitch);
+ OUT_RING (src->offset);
+ OUT_RING (dst->offset);
+ }
+
+ for (i=0; i<nbox; i++, box++) {
+ BEGIN_RING_SIZE(NvSubImageBlit, NV10_IMAGE_BLIT_SET_POINT, 3);
+ OUT_RING (((box->y1 - dPriv->y) << 16) |
+ (box->x1 - dPriv->x));
+ OUT_RING ((box->y1 << 16) | box->x1);
+ OUT_RING (((box->y2 - box->y1) << 16) |
+ (box->x2 - box->x1));
+ }
+
+ UNLOCK_HARDWARE(nmesa);
+#endif
+}
+
+void nouveauSwapBuffers(__DRIdrawablePrivate *dPriv)
+{
+ if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
+ nouveauContextPtr nmesa = dPriv->driContextPriv->driverPrivate;
+
+ if (nmesa->glCtx->Visual.doubleBufferMode) {
+ _mesa_notifySwapBuffers(nmesa->glCtx);
+ nouveauDoSwapBuffers(nmesa, dPriv);
+ }
+
+ }
+}
+
+void nouveauCopySubBuffer(__DRIdrawablePrivate *dPriv,
+ int x, int y, int w, int h)
+{
+}
+
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_context.h b/src/mesa/drivers/dri/nouveau/nouveau_context.h
new file mode 100644
index 0000000000..c7bf387210
--- /dev/null
+++ b/src/mesa/drivers/dri/nouveau/nouveau_context.h
@@ -0,0 +1,227 @@
+/**************************************************************************
+
+Copyright 2006 Stephane Marchesin
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+
+
+#ifndef __NOUVEAU_CONTEXT_H__
+#define __NOUVEAU_CONTEXT_H__
+
+#include "dri_util.h"
+#include "drm.h"
+#include "nouveau_drm.h"
+
+#include "mtypes.h"
+#include "tnl/t_vertex.h"
+
+#include "nouveau_screen.h"
+#include "nouveau_state_cache.h"
+#include "nouveau_buffers.h"
+#include "nouveau_shader.h"
+#include "nouveau_sync.h"
+
+#include "xmlconfig.h"
+
+typedef struct nouveau_fifo_t{
+ u_int32_t* buffer;
+ u_int32_t* mmio;
+ u_int32_t put_base;
+ u_int32_t current;
+ u_int32_t put;
+ u_int32_t free;
+ u_int32_t max;
+}
+nouveau_fifo;
+
+#define TAG(x) nouveau##x
+#include "tnl_dd/t_dd_vertex.h"
+#undef TAG
+
+/* Subpixel offsets for window coordinates (triangles): */
+#define SUBPIXEL_X (0.0F)
+#define SUBPIXEL_Y (0.125F)
+
+struct nouveau_context;
+
+typedef void (*nouveau_tri_func)( struct nouveau_context*,
+ nouveauVertex *,
+ nouveauVertex *,
+ nouveauVertex * );
+
+typedef void (*nouveau_line_func)( struct nouveau_context*,
+ nouveauVertex *,
+ nouveauVertex * );
+
+typedef void (*nouveau_point_func)( struct nouveau_context*,
+ nouveauVertex * );
+
+typedef struct nouveau_hw_func_t {
+ /* Initialise any card-specific non-GL related state */
+ GLboolean (*InitCard)(struct nouveau_context *);
+ /* Update buffer offset/pitch/format */
+ GLboolean (*BindBuffers)(struct nouveau_context *, int num_color,
+ nouveau_renderbuffer **color,
+ nouveau_renderbuffer *depth);
+ /* Update anything that depends on the window position/size */
+ void (*WindowMoved)(struct nouveau_context *);
+} nouveau_hw_func;
+
+typedef struct nouveau_context {
+ /* Mesa context */
+ GLcontext *glCtx;
+
+ /* The per-context fifo */
+ nouveau_fifo fifo;
+
+ /* The read-only regs */
+ volatile unsigned char* mmio;
+
+ /* Physical addresses of AGP/VRAM apertures */
+ uint64_t vram_phys;
+ uint64_t agp_phys;
+
+ /* Channel synchronisation */
+ nouveau_notifier *syncNotifier;
+
+ /* Additional hw-specific functions */
+ nouveau_hw_func hw_func;
+
+ /* FIXME : do we want to put all state into a separate struct ? */
+ /* State for tris */
+ GLuint color_offset;
+ GLuint specular_offset;
+
+ /* Vertex state */
+ GLuint vertex_size;
+ GLubyte *verts;
+ struct tnl_attr_map vertex_attrs[VERT_ATTRIB_MAX];
+ GLuint vertex_attr_count;
+
+ /* Color buffer clear value */
+ uint32_t clear_color_value;
+
+ /* Depth/stencil clear value */
+ uint32_t clear_value;
+
+ /* Light state */
+ GLboolean lighting_enabled;
+ uint32_t enabled_lights;
+
+ /* Cached state */
+ nouveau_state_cache state_cache;
+
+ /* The drawing fallbacks */
+ GLuint Fallback;
+ nouveau_tri_func draw_tri;
+ nouveau_line_func draw_line;
+ nouveau_point_func draw_point;
+
+ /* Cliprects information */
+ GLuint numClipRects;
+ drm_clip_rect_t *pClipRects;
+ drm_clip_rect_t osClipRect;
+ GLuint drawX, drawY;
+
+ /* The rendering context information */
+ GLenum current_primitive; /* the current primitive enum */
+ DECLARE_RENDERINPUTS(render_inputs_bitset); /* the current render inputs */
+
+ /* Shader state */
+ nvsFunc VPfunc;
+ nvsFunc FPfunc;
+ nouveauShader *current_fragprog;
+ nouveauShader *current_vertprog;
+ nouveauShader *passthrough_vp;
+
+ nouveauScreenRec *screen;
+ drm_nouveau_sarea_t *sarea;
+
+ __DRIcontextPrivate *driContext; /* DRI context */
+ __DRIscreenPrivate *driScreen; /* DRI screen */
+ __DRIdrawablePrivate *driDrawable; /* DRI drawable bound to this ctx */
+ GLint lastStamp;
+
+ drm_context_t hHWContext;
+ drm_hw_lock_t *driHwLock;
+ int driFd;
+
+ /* Configuration cache */
+ driOptionCache optionCache;
+
+ /* vblank stuff */
+ uint32_t vblank_flags;
+ uint32_t vblank_seq;
+
+ GLuint new_state;
+ GLuint new_render_state;
+ GLuint render_index;
+ GLmatrix viewport;
+ GLfloat depth_scale;
+
+}nouveauContextRec, *nouveauContextPtr;
+
+
+#define NOUVEAU_CONTEXT(ctx) ((nouveauContextPtr)(ctx->DriverCtx))
+
+/* Flags for software fallback cases: */
+#define NOUVEAU_FALLBACK_TEXTURE 0x0001
+#define NOUVEAU_FALLBACK_DRAW_BUFFER 0x0002
+#define NOUVEAU_FALLBACK_READ_BUFFER 0x0004
+#define NOUVEAU_FALLBACK_STENCIL 0x0008
+#define NOUVEAU_FALLBACK_RENDER_MODE 0x0010
+#define NOUVEAU_FALLBACK_LOGICOP 0x0020
+#define NOUVEAU_FALLBACK_SEP_SPECULAR 0x0040
+#define NOUVEAU_FALLBACK_BLEND_EQ 0x0080
+#define NOUVEAU_FALLBACK_BLEND_FUNC 0x0100
+#define NOUVEAU_FALLBACK_PROJTEX 0x0200
+#define NOUVEAU_FALLBACK_DISABLE 0x0400
+
+
+extern GLboolean nouveauCreateContext( const __GLcontextModes *glVisual,
+ __DRIcontextPrivate *driContextPriv,
+ void *sharedContextPrivate );
+
+extern void nouveauDestroyContext( __DRIcontextPrivate * );
+
+extern GLboolean nouveauMakeCurrent( __DRIcontextPrivate *driContextPriv,
+ __DRIdrawablePrivate *driDrawPriv,
+ __DRIdrawablePrivate *driReadPriv );
+
+extern GLboolean nouveauUnbindContext( __DRIcontextPrivate *driContextPriv );
+
+extern void nouveauSwapBuffers(__DRIdrawablePrivate *dPriv);
+
+extern void nouveauCopySubBuffer(__DRIdrawablePrivate *dPriv,
+ int x, int y, int w, int h);
+
+/* Debugging utils: */
+extern int NOUVEAU_DEBUG;
+
+#define DEBUG_SHADERS 0x00000001
+#define DEBUG_MEM 0x00000002
+#define DEBUG_BUFFEROBJ 0x00000004
+
+#endif /* __NOUVEAU_CONTEXT_H__ */
+
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_ctrlreg.h b/src/mesa/drivers/dri/nouveau/nouveau_ctrlreg.h
new file mode 100644
index 0000000000..c9b2d59007
--- /dev/null
+++ b/src/mesa/drivers/dri/nouveau/nouveau_ctrlreg.h
@@ -0,0 +1,44 @@
+/**************************************************************************
+
+Copyright 2006 Stephane Marchesin, Sylvain Munaut
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+
+
+
+#define NV03_STATUS 0x004006b0
+#define NV04_STATUS 0x00400700
+
+#define NV03_FIFO_REGS_SIZE 0x10000
+# define NV03_FIFO_REGS_DMAPUT 0x00000040
+# define NV03_FIFO_REGS_DMAGET 0x00000044
+
+/* Fifo commands. These are not regs, neither masks */
+#define NV03_FIFO_CMD_JUMP 0x20000000
+#define NV03_FIFO_CMD_JUMP_OFFSET_MASK 0x1ffffffc
+#define NV03_FIFO_CMD_REWIND (NV03_FIFO_CMD_JUMP | (0 & NV03_FIFO_CMD_JUMP_OFFSET_MASK))
+
+
+#define NONINC_METHOD 0x40000000
+
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_dri.h b/src/mesa/drivers/dri/nouveau/nouveau_dri.h
new file mode 100644
index 0000000000..ce3c3fb9cc
--- /dev/null
+++ b/src/mesa/drivers/dri/nouveau/nouveau_dri.h
@@ -0,0 +1,28 @@
+#ifndef _NOUVEAU_DRI_
+#define _NOUVEAU_DRI_
+
+#include "xf86drm.h"
+#include "drm.h"
+#include "nouveau_drm.h"
+
+typedef struct {
+ uint32_t device_id; /**< \brief PCI device ID */
+ uint32_t width; /**< \brief width in pixels of display */
+ uint32_t height; /**< \brief height in scanlines of display */
+ uint32_t depth; /**< \brief depth of display (8, 15, 16, 24) */
+ uint32_t bpp; /**< \brief bit depth of display (8, 16, 24, 32) */
+
+ uint32_t bus_type; /**< \brief ths bus type */
+ uint32_t bus_mode; /**< \brief bus mode (used for AGP, maybe also for PCI-E ?) */
+
+ uint32_t front_offset; /**< \brief front buffer offset */
+ uint32_t front_pitch; /**< \brief front buffer pitch */
+ uint32_t back_offset; /**< \brief private back buffer offset */
+ uint32_t back_pitch; /**< \brief private back buffer pitch */
+ uint32_t depth_offset; /**< \brief private depth buffer offset */
+ uint32_t depth_pitch; /**< \brief private depth buffer pitch */
+
+} NOUVEAUDRIRec, *NOUVEAUDRIPtr;
+
+#endif
+
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_driver.c b/src/mesa/drivers/dri/nouveau/nouveau_driver.c
new file mode 100644
index 0000000000..00956aa8f8
--- /dev/null
+++ b/src/mesa/drivers/dri/nouveau/nouveau_driver.c
@@ -0,0 +1,146 @@
+/**************************************************************************
+
+Copyright 2006 Stephane Marchesin
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+#include "nouveau_context.h"
+//#include "nouveau_state.h"
+#include "nouveau_lock.h"
+#include "nouveau_fifo.h"
+#include "nouveau_driver.h"
+#include "swrast/swrast.h"
+
+#include "context.h"
+#include "framebuffer.h"
+
+#include "utils.h"
+
+/* Wrapper for DRM_NOUVEAU_GETPARAM ioctl */
+GLboolean nouveauDRMGetParam(nouveauContextPtr nmesa,
+ unsigned int param,
+ uint64_t* value)
+{
+ drm_nouveau_getparam_t getp;
+
+ getp.param = param;
+ if (!value || drmCommandWriteRead(nmesa->driFd, DRM_NOUVEAU_GETPARAM,
+ &getp, sizeof(getp)))
+ return GL_FALSE;
+ *value = getp.value;
+ return GL_TRUE;
+}
+
+/* Wrapper for DRM_NOUVEAU_GETPARAM ioctl */
+GLboolean nouveauDRMSetParam(nouveauContextPtr nmesa,
+ unsigned int param,
+ uint64_t value)
+{
+ drm_nouveau_setparam_t setp;
+
+ setp.param = param;
+ setp.value = value;
+ if (drmCommandWrite(nmesa->driFd, DRM_NOUVEAU_SETPARAM, &setp,
+ sizeof(setp)))
+ return GL_FALSE;
+ return GL_TRUE;
+}
+
+/* Return the width and height of the current color buffer */
+static void nouveauGetBufferSize( GLframebuffer *buffer,
+ GLuint *width, GLuint *height )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+
+ LOCK_HARDWARE( nmesa );
+ *width = nmesa->driDrawable->w;
+ *height = nmesa->driDrawable->h;
+ UNLOCK_HARDWARE( nmesa );
+}
+
+/* glGetString */
+static const GLubyte *nouveauGetString( GLcontext *ctx, GLenum name )
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ static char buffer[128];
+ const char * card_name = "Unknown";
+ GLuint agp_mode = 0;
+
+ switch ( name ) {
+ case GL_VENDOR:
+ return (GLubyte *)DRIVER_AUTHOR;
+
+ case GL_RENDERER:
+ card_name=nmesa->screen->card->name;
+
+ switch(nmesa->screen->bus_type)
+ {
+ case NV_PCI:
+ case NV_PCIE:
+ default:
+ agp_mode=0;
+ break;
+ case NV_AGP:
+ agp_mode=nmesa->screen->agp_mode;
+ break;
+ }
+ driGetRendererString( buffer, card_name, DRIVER_DATE,
+ agp_mode );
+ return (GLubyte *)buffer;
+ default:
+ return NULL;
+ }
+}
+
+/* glFlush */
+static void nouveauFlush( GLcontext *ctx )
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ FIRE_RING();
+}
+
+/* glFinish */
+static void nouveauFinish( GLcontext *ctx )
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ nouveauFlush( ctx );
+ nouveauWaitForIdle( nmesa );
+}
+
+/* glClear */
+static void nouveauClear( GLcontext *ctx, GLbitfield mask )
+{
+ // XXX we really should do something here...
+}
+
+void nouveauDriverInitFunctions( struct dd_function_table *functions )
+{
+ functions->GetBufferSize = nouveauGetBufferSize;
+ functions->ResizeBuffers = _mesa_resize_framebuffer;
+ functions->GetString = nouveauGetString;
+ functions->Flush = nouveauFlush;
+ functions->Finish = nouveauFinish;
+ functions->Clear = nouveauClear;
+}
+
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_driver.h b/src/mesa/drivers/dri/nouveau/nouveau_driver.h
new file mode 100644
index 0000000000..6164012b5b
--- /dev/null
+++ b/src/mesa/drivers/dri/nouveau/nouveau_driver.h
@@ -0,0 +1,42 @@
+/**************************************************************************
+
+Copyright 2006 Stephane Marchesin
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+
+
+#ifndef __NOUVEAU_DRIVER_H__
+#define __NOUVEAU_DRIVER_H__
+
+#define DRIVER_DATE "20060219"
+#define DRIVER_AUTHOR "Stephane Marchesin"
+
+extern void nouveauDriverInitFunctions( struct dd_function_table *functions );
+extern GLboolean nouveauDRMGetParam(nouveauContextPtr nmesa, unsigned int param,
+ uint64_t *value);
+extern GLboolean nouveauDRMSetParam(nouveauContextPtr nmesa, unsigned int param,
+ uint64_t value);
+
+#endif /* __NOUVEAU_DRIVER_H__ */
+
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_fifo.c b/src/mesa/drivers/dri/nouveau/nouveau_fifo.c
new file mode 100644
index 0000000000..7af9f1e3c2
--- /dev/null
+++ b/src/mesa/drivers/dri/nouveau/nouveau_fifo.c
@@ -0,0 +1,137 @@
+/**************************************************************************
+
+Copyright 2006 Stephane Marchesin
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+
+#include "vblank.h"
+#include <errno.h>
+#include "mtypes.h"
+#include "macros.h"
+#include "dd.h"
+#include "swrast/swrast.h"
+#include "nouveau_context.h"
+#include "nouveau_msg.h"
+#include "nouveau_fifo.h"
+#include "nouveau_lock.h"
+#include "nouveau_object.h"
+#include "nouveau_sync.h"
+
+
+#define RING_SKIPS 8
+
+void WAIT_RING(nouveauContextPtr nmesa,u_int32_t size)
+{
+#ifdef NOUVEAU_RING_DEBUG
+ return;
+#endif
+ u_int32_t fifo_get;
+ while(nmesa->fifo.free < size+1) {
+ fifo_get = NV_FIFO_READ_GET();
+
+ if(nmesa->fifo.put >= fifo_get) {
+ nmesa->fifo.free = nmesa->fifo.max - nmesa->fifo.current;
+ if(nmesa->fifo.free < size+1) {
+ OUT_RING(NV03_FIFO_CMD_JUMP | nmesa->fifo.put_base);
+ if(fifo_get <= RING_SKIPS) {
+ if(nmesa->fifo.put <= RING_SKIPS) /* corner case - will be idle */
+ NV_FIFO_WRITE_PUT(RING_SKIPS + 1);
+ do { fifo_get = NV_FIFO_READ_GET(); }
+ while(fifo_get <= RING_SKIPS);
+ }
+ NV_FIFO_WRITE_PUT(RING_SKIPS);
+ nmesa->fifo.current = nmesa->fifo.put = RING_SKIPS;
+ nmesa->fifo.free = fifo_get - (RING_SKIPS + 1);
+ }
+ } else
+ nmesa->fifo.free = fifo_get - nmesa->fifo.current - 1;
+ }
+}
+
+/*
+ * Wait for the channel to be idle
+ */
+void nouveauWaitForIdleLocked(nouveauContextPtr nmesa)
+{
+ /* Wait for FIFO idle */
+ FIRE_RING();
+ while(RING_AHEAD()>0);
+
+ /* Wait on notifier to indicate all commands in the channel have
+ * been completed.
+ */
+ nouveau_notifier_wait_nop(nmesa->glCtx, nmesa->syncNotifier, NvSub3D);
+}
+
+void nouveauWaitForIdle(nouveauContextPtr nmesa)
+{
+ LOCK_HARDWARE(nmesa);
+ nouveauWaitForIdleLocked(nmesa);
+ UNLOCK_HARDWARE(nmesa);
+}
+
+// here we call the fifo initialization ioctl and fill in stuff accordingly
+GLboolean nouveauFifoInit(nouveauContextPtr nmesa)
+{
+ drm_nouveau_fifo_alloc_t fifo_init;
+ int i;
+
+#ifdef NOUVEAU_RING_DEBUG
+ return GL_TRUE;
+#endif
+
+ int ret;
+ ret=drmCommandWriteRead(nmesa->driFd, DRM_NOUVEAU_FIFO_ALLOC, &fifo_init, sizeof(fifo_init));
+ if (ret) {
+ FATAL("Fifo initialization ioctl failed (returned %d)\n",ret);
+ return GL_FALSE;
+ }
+
+ ret = drmMap(nmesa->driFd, fifo_init.cmdbuf, fifo_init.cmdbuf_size, &nmesa->fifo.buffer);
+ if (ret) {
+ FATAL("Unable to map the fifo (returned %d)\n",ret);
+ return GL_FALSE;
+ }
+ ret = drmMap(nmesa->driFd, fifo_init.ctrl, fifo_init.ctrl_size, &nmesa->fifo.mmio);
+ if (ret) {
+ FATAL("Unable to map the control regs (returned %d)\n",ret);
+ return GL_FALSE;
+ }
+
+ /* Setup our initial FIFO tracking params */
+ nmesa->fifo.put_base = fifo_init.put_base;
+ nmesa->fifo.current = 0;
+ nmesa->fifo.put = 0;
+ nmesa->fifo.max = (fifo_init.cmdbuf_size >> 2) - 1;
+ nmesa->fifo.free = nmesa->fifo.max - nmesa->fifo.current;
+
+ for (i=0; i<RING_SKIPS; i++)
+ OUT_RING(0);
+ nmesa->fifo.free -= RING_SKIPS;
+
+ MESSAGE("Fifo init ok. Using context %d\n", fifo_init.channel);
+ return GL_TRUE;
+}
+
+
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_fifo.h b/src/mesa/drivers/dri/nouveau/nouveau_fifo.h
new file mode 100644
index 0000000000..9056bfb255
--- /dev/null
+++ b/src/mesa/drivers/dri/nouveau/nouveau_fifo.h
@@ -0,0 +1,156 @@
+/**************************************************************************
+
+Copyright 2006 Stephane Marchesin
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+
+
+#ifndef __NOUVEAU_FIFO_H__
+#define __NOUVEAU_FIFO_H__
+
+#include "nouveau_context.h"
+#include "nouveau_ctrlreg.h"
+#include "nouveau_state_cache.h"
+
+//#define NOUVEAU_RING_DEBUG
+//#define NOUVEAU_STATE_CACHE_DISABLE
+
+#define NV_READ(reg) *(volatile u_int32_t *)(nmesa->mmio + (reg))
+
+#define NV_FIFO_READ(reg) *(volatile u_int32_t *)(nmesa->fifo.mmio + (reg/4))
+#define NV_FIFO_WRITE(reg,value) *(volatile u_int32_t *)(nmesa->fifo.mmio + (reg/4)) = value;
+#define NV_FIFO_READ_GET() ((NV_FIFO_READ(NV03_FIFO_REGS_DMAGET) - nmesa->fifo.put_base) >> 2)
+#define NV_FIFO_WRITE_PUT(val) NV_FIFO_WRITE(NV03_FIFO_REGS_DMAPUT, ((val)<<2) + nmesa->fifo.put_base)
+
+/*
+ * Ring/fifo interface
+ *
+ * - Begin a ring section with BEGIN_RING_SIZE (if you know the full size in advance)
+ * - Output stuff to the ring with either OUT_RINGp (outputs a raw mem chunk), OUT_RING (1 uint32_t) or OUT_RINGf (1 float)
+ * - RING_AVAILABLE returns the available fifo (in uint32_ts)
+ * - RING_AHEAD returns how much ahead of the last submission point we are
+ * - FIRE_RING fires whatever we have that wasn't fired before
+ * - WAIT_RING waits for size (in uint32_ts) to be available in the fifo
+ */
+
+/* Enable for ring debugging. Prints out writes to the ring buffer
+ * but does not actually write to it.
+ */
+#ifdef NOUVEAU_RING_DEBUG
+
+#define OUT_RINGp(ptr,sz) do { \
+uint32_t* p=(uint32_t*)(ptr); \
+int i; printf("OUT_RINGp: (size 0x%x dwords)\n",sz); for(i=0;i<sz;i++) printf(" 0x%08x %f\n", *(p+i), *((float*)(p+i))); \
+}while(0)
+
+#define OUT_RING(n) do { \
+ printf("OUT_RINGn: 0x%08x (%s)\n", n, __func__); \
+}while(0)
+
+#define OUT_RINGf(n) do { \
+ printf("OUT_RINGf: %.04f (%s)\n", n, __func__); \
+}while(0)
+
+#else
+
+#define OUT_RINGp(ptr,sz) do{ \
+ memcpy(nmesa->fifo.buffer+nmesa->fifo.current,ptr,(sz)*4); \
+ nmesa->fifo.current+=(sz); \
+}while(0)
+
+#define OUT_RING(n) do { \
+nmesa->fifo.buffer[nmesa->fifo.current++]=(n); \
+}while(0)
+
+#define OUT_RINGf(n) do { \
+*((float*)(nmesa->fifo.buffer+nmesa->fifo.current++))=(n); \
+}while(0)
+
+#endif
+
+#define BEGIN_RING_SIZE(subchannel,tag,size) do { \
+ nouveau_state_cache_flush(nmesa); \
+ if (nmesa->fifo.free <= (size)) \
+ WAIT_RING(nmesa,(size)); \
+ OUT_RING( ((size)<<18) | ((subchannel) << 13) | (tag)); \
+ nmesa->fifo.free -= ((size) + 1); \
+}while(0)
+
+extern void WAIT_RING(nouveauContextPtr nmesa,u_int32_t size);
+extern void nouveau_state_cache_flush(nouveauContextPtr nmesa);
+extern void nouveau_state_cache_init(nouveauContextPtr nmesa);
+
+#ifdef NOUVEAU_STATE_CACHE_DISABLE
+#define BEGIN_RING_CACHE(subc,tag,size) BEGIN_RING_SIZE((subc), (tag), (size))
+#define OUT_RING_CACHE(n) OUT_RING((n))
+#define OUT_RING_CACHEf(n) OUT_RINGf((n))
+#define OUT_RING_CACHEp(ptr, sz) OUT_RINGp((ptr), (sz))
+#else
+#define BEGIN_RING_CACHE(subchannel,tag,size) do { \
+ nmesa->state_cache.dirty=1; \
+ nmesa->state_cache.current_pos=((tag)/4); \
+}while(0)
+
+#define OUT_RING_CACHE(n) do { \
+ if (nmesa->state_cache.atoms[nmesa->state_cache.current_pos].value!=(n)) { \
+ nmesa->state_cache.atoms[nmesa->state_cache.current_pos].dirty=1; \
+ nmesa->state_cache.hdirty[nmesa->state_cache.current_pos/NOUVEAU_STATE_CACHE_HIER_SIZE]=1; \
+ nmesa->state_cache.atoms[nmesa->state_cache.current_pos].value=(n); \
+ } \
+ nmesa->state_cache.current_pos++; \
+}while(0)
+
+#define OUT_RING_CACHEf(n) do { \
+ if ((*(float*)(&nmesa->state_cache.atoms[nmesa->state_cache.current_pos].value))!=(n)){ \
+ nmesa->state_cache.atoms[nmesa->state_cache.current_pos].dirty=1; \
+ nmesa->state_cache.hdirty[nmesa->state_cache.current_pos/NOUVEAU_STATE_CACHE_HIER_SIZE]=1; \
+ (*(float*)(&nmesa->state_cache.atoms[nmesa->state_cache.current_pos].value))=(n);\
+ } \
+ nmesa->state_cache.current_pos++; \
+}while(0)
+
+#define OUT_RING_CACHEp(ptr,sz) do { \
+uint32_t* p=(uint32_t*)(ptr); \
+int i; for(i=0;i<sz;i++) OUT_RING_CACHE(*(p+i)); \
+}while(0)
+#endif
+
+#define RING_AVAILABLE() (nmesa->fifo.free-1)
+
+#define RING_AHEAD() ((nmesa->fifo.put<=nmesa->fifo.current)?(nmesa->fifo.current-nmesa->fifo.put):nmesa->fifo.max-nmesa->fifo.put+nmesa->fifo.current)
+
+#define FIRE_RING() do { \
+ if (nmesa->fifo.current!=nmesa->fifo.put) { \
+ nmesa->fifo.put=nmesa->fifo.current; \
+ NV_FIFO_WRITE_PUT(nmesa->fifo.put); \
+ } \
+}while(0)
+
+extern void nouveauWaitForIdle(nouveauContextPtr nmesa);
+extern void nouveauWaitForIdleLocked(nouveauContextPtr nmesa);
+extern GLboolean nouveauFifoInit(nouveauContextPtr nmesa);
+
+#endif /* __NOUVEAU_FIFO_H__ */
+
+
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_lock.c b/src/mesa/drivers/dri/nouveau/nouveau_lock.c
new file mode 100644
index 0000000000..c119d14dd7
--- /dev/null
+++ b/src/mesa/drivers/dri/nouveau/nouveau_lock.c
@@ -0,0 +1,81 @@
+/**************************************************************************
+
+Copyright 2006 Stephane Marchesin
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+
+#include "nouveau_context.h"
+#include "nouveau_lock.h"
+
+#include "drirenderbuffer.h"
+#include "framebuffer.h"
+
+
+/* Update the hardware state. This is called if another context has
+ * grabbed the hardware lock, which includes the X server. This
+ * function also updates the driver's window state after the X server
+ * moves, resizes or restacks a window -- the change will be reflected
+ * in the drawable position and clip rects. Since the X server grabs
+ * the hardware lock when it changes the window state, this routine will
+ * automatically be called after such a change.
+ */
+void nouveauGetLock( nouveauContextPtr nmesa, GLuint flags )
+{
+ __DRIdrawablePrivate *dPriv = nmesa->driDrawable;
+ __DRIscreenPrivate *sPriv = nmesa->driScreen;
+ drm_nouveau_sarea_t *sarea = nmesa->sarea;
+
+ drmGetLock( nmesa->driFd, nmesa->hHWContext, flags );
+
+ /* The window might have moved, so we might need to get new clip
+ * rects.
+ *
+ * NOTE: This releases and regrabs the hw lock to allow the X server
+ * to respond to the DRI protocol request for new drawable info.
+ * Since the hardware state depends on having the latest drawable
+ * clip rects, all state checking must be done _after_ this call.
+ */
+ DRI_VALIDATE_DRAWABLE_INFO( sPriv, dPriv );
+
+ /* If timestamps don't match, the window has been changed */
+ if (nmesa->lastStamp != dPriv->lastStamp) {
+ struct gl_framebuffer *fb = (struct gl_framebuffer *)dPriv->driverPrivate;
+
+ /* _mesa_resize_framebuffer will take care of calling the renderbuffer's
+ * AllocStorage function if we need more memory to hold it */
+ if (fb->Width != dPriv->w || fb->Height != dPriv->h) {
+ _mesa_resize_framebuffer(nmesa->glCtx, fb, dPriv->w, dPriv->h);
+ /* resize buffers, will call nouveau_window_moved */
+ nouveau_build_framebuffer(nmesa->glCtx, fb);
+ } else {
+ nouveau_window_moved(nmesa->glCtx);
+ }
+
+ nmesa->lastStamp = dPriv->lastStamp;
+ }
+
+ nmesa->numClipRects = dPriv->numClipRects;
+ nmesa->pClipRects = dPriv->pClipRects;
+
+}
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_lock.h b/src/mesa/drivers/dri/nouveau/nouveau_lock.h
new file mode 100644
index 0000000000..38bb001425
--- /dev/null
+++ b/src/mesa/drivers/dri/nouveau/nouveau_lock.h
@@ -0,0 +1,69 @@
+/**************************************************************************
+
+Copyright 2006 Stephane Marchesin
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+
+#ifndef __NOUVEAU_LOCK_H__
+#define __NOUVEAU_LOCK_H__
+
+#include "nouveau_context.h"
+
+extern void nouveauGetLock( nouveauContextPtr nmesa, GLuint flags );
+
+/*
+ * !!! We may want to separate locks from locks with validation. This
+ * could be used to improve performance for those things commands that
+ * do not do any drawing !!!
+ */
+
+/* Lock the hardware and validate our state.
+ */
+#define LOCK_HARDWARE( nmesa ) \
+ do { \
+ char __ret = 0; \
+ DEBUG_CHECK_LOCK(); \
+ DRM_CAS( nmesa->driHwLock, nmesa->hHWContext, \
+ (DRM_LOCK_HELD | nmesa->hHWContext), __ret ); \
+ if ( __ret ) \
+ nouveauGetLock( nmesa, 0 ); \
+ DEBUG_LOCK(); \
+ } while (0)
+
+/* Unlock the hardware.
+ */
+#define UNLOCK_HARDWARE( nmesa ) \
+ do { \
+ DRM_UNLOCK( nmesa->driFd, \
+ nmesa->driHwLock, \
+ nmesa->hHWContext ); \
+ DEBUG_RESET(); \
+ } while (0)
+
+#define DEBUG_LOCK()
+#define DEBUG_RESET()
+#define DEBUG_CHECK_LOCK()
+
+
+#endif /* __NOUVEAU_LOCK_H__ */
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_msg.h b/src/mesa/drivers/dri/nouveau/nouveau_msg.h
new file mode 100644
index 0000000000..5dea2189c7
--- /dev/null
+++ b/src/mesa/drivers/dri/nouveau/nouveau_msg.h
@@ -0,0 +1,67 @@
+/*
+Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
+Copyright 2006 Stephane Marchesin. All Rights Reserved
+
+The Weather Channel (TM) funded Tungsten Graphics to develop the
+initial release of the Radeon 8500 driver under the XFree86 license.
+This notice must be preserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ * Nicolai Haehnle <prefect_@gmx.net>
+ */
+
+
+#ifndef __NOUVEAU_MSG_H__
+#define __NOUVEAU_MSG_H__
+
+#define WARN_ONCE(a, ...) do {\
+ static int warn##__LINE__=1;\
+ if(warn##__LINE__){\
+ fprintf(stderr, "*********************************WARN_ONCE*********************************\n");\
+ fprintf(stderr, "File %s function %s line %d\n", __FILE__, __FUNCTION__, __LINE__);\
+ fprintf(stderr, a, ## __VA_ARGS__);\
+ fprintf(stderr, "***************************************************************************\n");\
+ warn##__LINE__=0;\
+ } \
+ }while(0)
+
+#define MESSAGE(a, ...) do{\
+ fprintf(stderr, "************************************INFO***********************************\n");\
+ fprintf(stderr, "File %s function %s line %d\n", __FILE__, __FUNCTION__, __LINE__); \
+ fprintf(stderr, a, ## __VA_ARGS__);\
+ fprintf(stderr, "***************************************************************************\n");\
+ }while(0)
+
+#define FATAL(a, ...) do{\
+ fprintf(stderr, "***********************************FATAL***********************************\n");\
+ fprintf(stderr, "File %s function %s line %d\n", __FILE__, __FUNCTION__, __LINE__); \
+ fprintf(stderr, a, ## __VA_ARGS__);\
+ fprintf(stderr, "***************************************************************************\n");\
+ }while(0)
+
+#endif /* __NOUVEAU_MSG_H__ */
+
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_object.c b/src/mesa/drivers/dri/nouveau/nouveau_object.c
new file mode 100644
index 0000000000..1558f2963d
--- /dev/null
+++ b/src/mesa/drivers/dri/nouveau/nouveau_object.c
@@ -0,0 +1,92 @@
+
+#include "nouveau_fifo.h"
+#include "nouveau_object.h"
+#include "nouveau_reg.h"
+
+
+GLboolean nouveauCreateContextObject(nouveauContextPtr nmesa, int handle, int class, uint32_t flags, uint32_t dma_in, uint32_t dma_out, uint32_t dma_notifier)
+{
+ drm_nouveau_object_init_t cto;
+ int ret;
+
+ cto.handle = handle;
+ cto.class = class;
+ cto.flags = flags;
+ cto.dma0= dma_in;
+ cto.dma1= dma_out;
+ cto.dma_notifier = dma_notifier;
+ ret = drmCommandWrite(nmesa->driFd, DRM_NOUVEAU_OBJECT_INIT, &cto, sizeof(cto));
+
+ return ret == 0;
+}
+
+GLboolean nouveauCreateDmaObject(nouveauContextPtr nmesa,
+ uint32_t handle,
+ uint32_t offset,
+ uint32_t size,
+ int target,
+ int access)
+{
+ drm_nouveau_dma_object_init_t dma;
+ int ret;
+
+ dma.handle = handle;
+ dma.target = target;
+ dma.access = access;
+ dma.offset = offset;
+ dma.size = size;
+ ret = drmCommandWriteRead(nmesa->driFd, DRM_NOUVEAU_DMA_OBJECT_INIT,
+ &dma, sizeof(dma));
+ return ret == 0;
+}
+
+void nouveauObjectOnSubchannel(nouveauContextPtr nmesa, int subchannel, int handle)
+{
+ BEGIN_RING_SIZE(subchannel, 0, 1);
+ OUT_RING(handle);
+}
+
+void nouveauObjectInit(nouveauContextPtr nmesa)
+{
+#ifdef NOUVEAU_RING_DEBUG
+ return;
+#endif
+
+/* We need to know vram size.. and AGP size (and even if the card is AGP..) */
+ nouveauCreateDmaObject( nmesa, NvDmaFB,
+ 0, (256*1024*1024),
+ 0 /*NV_DMA_TARGET_FB*/, 0 /*NV_DMA_ACCESS_RW*/);
+ nouveauCreateDmaObject( nmesa, NvDmaAGP,
+ nmesa->agp_phys, (128*1024*1024),
+ 3 /* AGP */, 0 /* RW */);
+
+ nouveauCreateContextObject(nmesa, Nv3D, nmesa->screen->card->class_3d,
+ 0, 0, 0, 0);
+ nouveauCreateContextObject(nmesa, NvCtxSurf2D, NV10_CONTEXT_SURFACES_2D,
+ 0, 0, 0, 0);
+ nouveauCreateContextObject(nmesa, NvImageBlit, NV10_IMAGE_BLIT,
+ NV_DMA_CONTEXT_FLAGS_PATCH_SRCCOPY, 0, 0, 0);
+ nouveauCreateContextObject(nmesa, NvMemFormat,
+ NV_MEMORY_TO_MEMORY_FORMAT,
+ 0, 0, 0, 0);
+
+#ifdef ALLOW_MULTI_SUBCHANNEL
+ nouveauObjectOnSubchannel(nmesa, NvSubCtxSurf2D, NvCtxSurf2D);
+ BEGIN_RING_SIZE(NvSubCtxSurf2D, NV10_CONTEXT_SURFACES_2D_SET_DMA_IN_MEMORY0, 2);
+ OUT_RING(NvDmaFB);
+ OUT_RING(NvDmaFB);
+
+ nouveauObjectOnSubchannel(nmesa, NvSubImageBlit, NvImageBlit);
+ BEGIN_RING_SIZE(NvSubImageBlit, NV10_IMAGE_BLIT_SET_CONTEXT_SURFACES_2D, 1);
+ OUT_RING(NvCtxSurf2D);
+ BEGIN_RING_SIZE(NvSubImageBlit, NV10_IMAGE_BLIT_SET_OPERATION, 1);
+ OUT_RING(3); /* SRCCOPY */
+
+ nouveauObjectOnSubchannel(nmesa, NvSubMemFormat, NvMemFormat);
+#endif
+
+ nouveauObjectOnSubchannel(nmesa, NvSub3D, Nv3D);
+}
+
+
+
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_object.h b/src/mesa/drivers/dri/nouveau/nouveau_object.h
new file mode 100644
index 0000000000..b1ff5a5d0d
--- /dev/null
+++ b/src/mesa/drivers/dri/nouveau/nouveau_object.h
@@ -0,0 +1,41 @@
+#ifndef __NOUVEAU_OBJECT_H__
+#define __NOUVEAU_OBJECT_H__
+
+#include "nouveau_context.h"
+
+#define ALLOW_MULTI_SUBCHANNEL
+
+void nouveauObjectInit(nouveauContextPtr nmesa);
+
+enum DMAObjects {
+ Nv3D = 0x80000019,
+ NvCtxSurf2D = 0x80000020,
+ NvImageBlit = 0x80000021,
+ NvMemFormat = 0x80000022,
+ NvDmaFB = 0xD0FB0001,
+ NvDmaAGP = 0xD0AA0001,
+ NvSyncNotify = 0xD0000001
+};
+
+enum DMASubchannel {
+ NvSubCtxSurf2D = 0,
+ NvSubImageBlit = 1,
+ NvSubMemFormat = 2,
+ NvSub3D = 7,
+};
+
+extern void nouveauObjectOnSubchannel(nouveauContextPtr nmesa, int subchannel, int handle);
+
+extern GLboolean nouveauCreateContextObject(nouveauContextPtr nmesa,
+ int handle, int class,
+ uint32_t flags,
+ uint32_t dma_in,
+ uint32_t dma_out,
+ uint32_t dma_notifier);
+extern GLboolean nouveauCreateDmaObject(nouveauContextPtr nmesa,
+ uint32_t handle,
+ uint32_t offset,
+ uint32_t size,
+ int target,
+ int access);
+#endif
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_reg.h b/src/mesa/drivers/dri/nouveau/nouveau_reg.h
new file mode 100644
index 0000000000..8758b538c8
--- /dev/null
+++ b/src/mesa/drivers/dri/nouveau/nouveau_reg.h
@@ -0,0 +1,1505 @@
+/*
+ Autogenerated file, do not edit !
+
+**************************************************************************
+
+ Copyright (C) 2006 :
+ Dmitry Baryshkov,
+ Laurent Carlier,
+ Matthieu Castet,
+ Dawid Gajownik,
+ Jeremy Kolb,
+ Stephane Loeuillet,
+ Patrice Mandin,
+ Stephane Marchesin,
+ Serge Martin,
+ Sylvain Munaut,
+ Ben Skeggs,
+ Erik Waling,
+ koala_br,
+ sturmflut.
+
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************
+
+ Created from objects.c rev. 1.398
+*/
+
+#ifndef _NOUVEAU_REG_H
+#define _NOUVEAU_REG_H
+
+/******************************************
+Object NV01_CONTEXT_CLIP_RECTANGLE used on: NV03 NV04 NV10 NV15 NV20 NV40 G70
+*/
+#define NV01_CONTEXT_CLIP_RECTANGLE 0x00000019
+# define NV01_CONTEXT_CLIP_RECTANGLE_SET_POINT 0x00000300 /* Parameters: x y */
+# define NV01_CONTEXT_CLIP_RECTANGLE_SET_SIZE 0x00000304 /* Parameters: width height */
+
+/******************************************
+Object NV_MEMORY_TO_MEMORY_FORMAT used on: NV04 NV10 NV15 NV20 NV30 NV40 G70
+*/
+#define NV_MEMORY_TO_MEMORY_FORMAT 0x00000039
+# define NV_MEMORY_TO_MEMORY_FORMAT_NOP 0x00000100
+# define NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY 0x00000104
+# define NV_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY 0x00000180
+# define NV_MEMORY_TO_MEMORY_FORMAT_OBJECT_IN 0x00000184
+# define NV_MEMORY_TO_MEMORY_FORMAT_OBJECT_OUT 0x00000188
+# define NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN 0x0000030c
+# define NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_OUT 0x00000310
+# define NV_MEMORY_TO_MEMORY_FORMAT_PITCH_IN 0x00000314
+# define NV_MEMORY_TO_MEMORY_FORMAT_PITCH_OUT 0x00000318
+# define NV_MEMORY_TO_MEMORY_FORMAT_LINE_LENGTH_IN 0x0000031c
+# define NV_MEMORY_TO_MEMORY_FORMAT_LINE_COUNT 0x00000320
+# define NV_MEMORY_TO_MEMORY_FORMAT_FORMAT 0x00000324 /* Parameters: src_inc dst_inc */
+# define NV_MEMORY_TO_MEMORY_FORMAT_BUF_NOTIFY 0x00000328
+
+/******************************************
+Object NV03_PRIMITIVE_RASTER_OP used on: NV03 NV04 NV10 NV15 NV20 NV30 NV40 G70
+*/
+#define NV03_PRIMITIVE_RASTER_OP 0x00000043
+# define NV03_PRIMITIVE_RASTER_OP_NOTIFY 0x00000100
+# define NV03_PRIMITIVE_RASTER_OP_DMA_NOTIFY 0x00000180
+# define NV03_PRIMITIVE_RASTER_OP_LOGIC_OP 0x00000300 /* Parameters: logic_op */
+
+/******************************************
+Object NV04_GDI_RECTANGLE_TEXT used on: NV04 NV10 NV15 NV20 NV30 NV40 G70
+*/
+#define NV04_GDI_RECTANGLE_TEXT 0x0000004a
+# define NV04_GDI_RECTANGLE_TEXT_SET_DMA_NOTIFY 0x00000180
+# define NV04_GDI_RECTANGLE_TEXT_PATTERN 0x00000188
+# define NV04_GDI_RECTANGLE_TEXT_ROP5 0x0000018c
+# define NV04_GDI_RECTANGLE_TEXT_SURFACE 0x00000198
+# define NV04_GDI_RECTANGLE_TEXT_OPERATION 0x000002fc
+# define NV04_GDI_RECTANGLE_TEXT_FORMAT 0x00000300
+# define NV04_GDI_RECTANGLE_TEXT_BLOCK_LEVEL1_TL 0x000005f4 /* Parameters: left top */
+# define NV04_GDI_RECTANGLE_TEXT_BLOCK_LEVEL1_BR 0x000005f8 /* Parameters: right bottom */
+# define NV04_GDI_RECTANGLE_TEXT_FILL_VALUE 0x000005fc
+# define NV04_GDI_RECTANGLE_TEXT_BLOCK_LEVEL2_TL 0x00000600 /* Parameters: left top */
+# define NV04_GDI_RECTANGLE_TEXT_BLOCK_LEVEL2_BR 0x00000604 /* Parameters: right bottom */
+
+/******************************************
+Object NV04_SWIZZLED_SURFACE used on: NV04 NV10 NV15
+*/
+#define NV04_SWIZZLED_SURFACE 0x00000052
+# define NV04_SWIZZLED_SURFACE_DMA_NOTIFY 0x00000180
+# define NV04_SWIZZLED_SURFACE_DMA_IMAGE 0x00000184
+# define NV04_SWIZZLED_SURFACE_FORMAT 0x00000300 /* Parameters: log2(height) log2(width) color */
+# define NV04_SWIZZLED_SURFACE_OFFSET 0x00000304
+
+/******************************************
+Object NV04_CONTEXT_SURFACES_3D used on: NV04
+*/
+#define NV04_CONTEXT_SURFACES_3D 0x00000053
+# define NV04_CONTEXT_SURFACES_3D_DMA_NOTIFY 0x00000180
+# define NV04_CONTEXT_SURFACES_3D_DMA_COLOR 0x00000184
+# define NV04_CONTEXT_SURFACES_3D_DMA_ZETA 0x00000188
+# define NV04_CONTEXT_SURFACES_3D_CLIP_HORIZONTAL 0x000002f8 /* Parameters: x width */
+# define NV04_CONTEXT_SURFACES_3D_CLIP_VERTICAL 0x000002fc /* Parameters: y height */
+# define NV04_CONTEXT_SURFACES_3D_FORMAT 0x00000300 /* Parameters: color type width height */
+# define NV04_CONTEXT_SURFACES_3D_CLIP_SIZE 0x00000304 /* Parameters: width height */
+# define NV04_CONTEXT_SURFACES_3D_PITCH 0x00000308 /* Parameters: color zeta */
+# define NV04_CONTEXT_SURFACES_3D_OFFSET_COLOR 0x0000030c
+# define NV04_CONTEXT_SURFACES_3D_OFFSET_ZETA 0x00000310
+
+/******************************************
+Object NV04_DX5_TEXTURED_TRIANGLE used on: NV04
+*/
+#define NV04_DX5_TEXTURED_TRIANGLE 0x00000054
+# define NV04_DX5_TEXTURED_TRIANGLE_NOP 0x00000100
+# define NV04_DX5_TEXTURED_TRIANGLE_NOTIFY 0x00000104
+# define NV04_DX5_TEXTURED_TRIANGLE_DMA_NOTIFY 0x00000180
+# define NV04_DX5_TEXTURED_TRIANGLE_DMA_1 0x00000184
+# define NV04_DX5_TEXTURED_TRIANGLE_DMA_2 0x00000188
+# define NV04_DX5_TEXTURED_TRIANGLE_SURFACE 0x0000018c
+# define NV04_DX5_TEXTURED_TRIANGLE_COLOR_KEY 0x00000300
+# define NV04_DX5_TEXTURED_TRIANGLE_TEXTURE_OFFSET 0x00000304
+# define NV04_DX5_TEXTURED_TRIANGLE_TEXTURE_FORMAT 0x00000308 /* Parameters: color mipmaps log(u) log(v) wrap_s wrap_t */
+# define NV04_DX5_TEXTURED_TRIANGLE_TEXTURE_FILTER 0x0000030c /* Parameters: magfilter minfilter lodbias */
+# define NV04_DX5_TEXTURED_TRIANGLE_BLEND 0x00000310 /* Parameters: texture benable dst src */
+# define NV04_DX5_TEXTURED_TRIANGLE_CONTROL 0x00000314 /* Parameters: alpharef alphafunc alphaenable zenable zwrite zfunc cullmode */
+# define NV04_DX5_TEXTURED_TRIANGLE_FOG_COLOR 0x00000318
+# define NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX( d) (0x00000400 + d * 0x0020)
+# define NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SY( d) (0x00000404 + d * 0x0020)
+# define NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SZ( d) (0x00000408 + d * 0x0020)
+# define NV04_DX5_TEXTURED_TRIANGLE_INV_W( d) (0x0000040c + d * 0x0020)
+# define NV04_DX5_TEXTURED_TRIANGLE_COLOR( d) (0x00000410 + d * 0x0020)
+# define NV04_DX5_TEXTURED_TRIANGLE_SPECULAR( d) (0x00000414 + d * 0x0020)
+# define NV04_DX5_TEXTURED_TRIANGLE_TEXTURE_S( d) (0x00000418 + d * 0x0020)
+# define NV04_DX5_TEXTURED_TRIANGLE_TEXTURE_T( d) (0x0000041c + d * 0x0020)
+# define NV04_DX5_TEXTURED_TRIANGLE_DRAW 0x00000600 /* Parameters: v0 v1 v2 v3 v4 v5 */
+
+/******************************************
+Object NV04_DX6_MULTITEX_TRIANGLE used on: NV04 NV10 NV15
+*/
+#define NV04_DX6_MULTITEX_TRIANGLE 0x00000055
+# define NV04_DX6_MULTITEX_TRIANGLE_NOP 0x00000100
+# define NV04_DX6_MULTITEX_TRIANGLE_NOTIFY 0x00000104
+# define NV04_DX6_MULTITEX_TRIANGLE_DMA_NOTIFY 0x00000180
+# define NV04_DX6_MULTITEX_TRIANGLE_DMA_1 0x00000184
+# define NV04_DX6_MULTITEX_TRIANGLE_DMA_2 0x00000188
+# define NV04_DX6_MULTITEX_TRIANGLE_SURFACE 0x0000018c
+# define NV04_DX6_MULTITEX_TRIANGLE_OFFSET0 0x00000308
+# define NV04_DX6_MULTITEX_TRIANGLE_OFFSET1 0x0000030c
+# define NV04_DX6_MULTITEX_TRIANGLE_FORMAT0 0x00000310 /* Parameters: color mipmaps log(u) log(v) wrap_s wrap_t */
+# define NV04_DX6_MULTITEX_TRIANGLE_FORMAT1 0x00000314 /* Parameters: color mipmaps log(u) log(v) wrap_s wrap_t */
+# define NV04_DX6_MULTITEX_TRIANGLE_FILTER0 0x00000318 /* Parameters: magfilter minfilter lodbias */
+# define NV04_DX6_MULTITEX_TRIANGLE_FILTER1 0x0000031c /* Parameters: magfilter minfilter lodbias */
+# define NV04_DX6_MULTITEX_TRIANGLE_COMBINE_0_ALPHA 0x00000320
+# define NV04_DX6_MULTITEX_TRIANGLE_COMBINE_0_COLOR 0x00000324
+# define NV04_DX6_MULTITEX_TRIANGLE_COMBINE_1_ALPHA 0x0000032c
+# define NV04_DX6_MULTITEX_TRIANGLE_COMBINE_1_COLOR 0x00000330
+# define NV04_DX6_MULTITEX_TRIANGLE_COMBINE_FACTOR 0x00000334
+# define NV04_DX6_MULTITEX_TRIANGLE_BLEND 0x00000338 /* Parameters: benable dst src */
+# define NV04_DX6_MULTITEX_TRIANGLE_CONTROL0 0x0000033c /* Parameters: red_write green_write blue_write alpha_write alpha_write stencil_write alpharef alphafunc alphaenable zenable zwrite zfunc cullmode */
+# define NV04_DX6_MULTITEX_TRIANGLE_CONTROL1 0x00000340 /* Parameters: stencil_enable stencil_mask_write stencil_mask_read stencilref stencilfunc */
+# define NV04_DX6_MULTITEX_TRIANGLE_CONTROL2 0x00000344 /* Parameters: stencil_fail stencil_zfail stencil_zpass */
+# define NV04_DX6_MULTITEX_TRIANGLE_FOG_COLOR 0x00000348
+# define NV04_DX6_MULTITEX_TRIANGLE_TLVERTEX_SX( d) (0x00000400 + d * 0x0028)
+# define NV04_DX6_MULTITEX_TRIANGLE_TLVERTEX_SY( d) (0x00000404 + d * 0x0028)
+# define NV04_DX6_MULTITEX_TRIANGLE_TLVERTEX_SZ( d) (0x00000408 + d * 0x0028)
+# define NV04_DX6_MULTITEX_TRIANGLE_INV_W( d) (0x0000040c + d * 0x0028)
+# define NV04_DX6_MULTITEX_TRIANGLE_COLOR( d) (0x00000410 + d * 0x0028)
+# define NV04_DX6_MULTITEX_TRIANGLE_SPECULAR( d) (0x00000414 + d * 0x0028)
+# define NV04_DX6_MULTITEX_TRIANGLE_TEXTURE0_S( d) (0x00000418 + d * 0x0028)
+# define NV04_DX6_MULTITEX_TRIANGLE_TEXTURE0_T( d) (0x0000041c + d * 0x0028)
+# define NV04_DX6_MULTITEX_TRIANGLE_TEXTURE1_S( d) (0x00000420 + d * 0x0028)
+# define NV04_DX6_MULTITEX_TRIANGLE_TEXTURE1_T( d) (0x00000424 + d * 0x0028)
+# define NV04_DX6_MULTITEX_TRIANGLE_DRAW 0x00000540 /* Parameters: v0 v1 v2 v3 v4 v5 */
+
+/******************************************
+Object NV04_COLOR_KEY used on: NV04 NV10 NV15 NV20 NV40
+*/
+#define NV04_COLOR_KEY 0x00000057
+# define NV04_COLOR_KEY_SET_DMA_NOTIFY 0x00000180
+# define NV04_COLOR_KEY_FORMAT 0x00000300
+# define NV04_COLOR_KEY_VALUE 0x00000304
+
+/******************************************
+Object NV04_SOLID_LINE used on: NV04
+*/
+#define NV04_SOLID_LINE 0x0000005c
+# define NV04_SOLID_LINE_CLIP_RECTANGLE 0x00000184
+# define NV04_SOLID_LINE_PATTERN 0x00000188
+# define NV04_SOLID_LINE_ROP 0x0000018c
+# define NV04_SOLID_LINE_SURFACE 0x00000198
+# define NV04_SOLID_LINE_OPERATION 0x000002fc
+# define NV04_SOLID_LINE_COLOR_FORMAT 0x00000300
+# define NV04_SOLID_LINE_COLOR_VALUE 0x00000304
+# define NV04_SOLID_LINE_START 0x00000400 /* Parameters: x y */
+# define NV04_SOLID_LINE_END 0x00000400 /* Parameters: x y */
+
+/******************************************
+Object NV04_UNK005E used on: NV04
+*/
+#define NV04_UNK005E 0x0000005e
+# define NV04_UNK005E_SET_SURFACE 0x00000198
+# define NV04_UNK005E_UNK02fc 0x000002fc
+# define NV04_UNK005E_UNK0300 0x00000300
+# define NV04_UNK005E_COUNTER 0x00000304
+
+/******************************************
+Object NV05_SCALED_IMAGE_FROM_MEMORY used on: NV04
+*/
+#define NV05_SCALED_IMAGE_FROM_MEMORY 0x00000063
+# define NV05_SCALED_IMAGE_FROM_MEMORY_SURFACE 0x00000198
+# define NV05_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION 0x000002fc
+# define NV05_SCALED_IMAGE_FROM_MEMORY_OPERATION 0x00000304
+
+/******************************************
+Object NV04_SCALED_IMAGE_FROM_MEMORY used on: NV04
+*/
+#define NV04_SCALED_IMAGE_FROM_MEMORY 0x00000077
+# define NV04_SCALED_IMAGE_FROM_MEMORY_DMA_NOTIFY 0x00000180
+# define NV04_SCALED_IMAGE_FROM_MEMORY_DMA_IMAGE 0x00000184
+# define NV04_SCALED_IMAGE_FROM_MEMORY_SURFACE 0x00000198
+# define NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT 0x00000300
+# define NV04_SCALED_IMAGE_FROM_MEMORY_OPERATION 0x00000304
+# define NV04_SCALED_IMAGE_FROM_MEMORY_CLIP_POS 0x00000308 /* Parameters: x y */
+# define NV04_SCALED_IMAGE_FROM_MEMORY_CLIP_SIZE 0x0000030c /* Parameters: width height */
+# define NV04_SCALED_IMAGE_FROM_MEMORY_OUT_POS 0x00000310 /* Parameters: x y */
+# define NV04_SCALED_IMAGE_FROM_MEMORY_OUT_SIZE 0x00000314 /* Parameters: width height */
+# define NV04_SCALED_IMAGE_FROM_MEMORY_DU_DX 0x00000318 /* Parameters: int frac*0x100000 */
+# define NV04_SCALED_IMAGE_FROM_MEMORY_DV_DY 0x0000031c /* Parameters: int frac*0x100000 */
+# define NV04_SCALED_IMAGE_FROM_MEMORY_SIZE 0x00000400 /* Parameters: width height */
+# define NV04_SCALED_IMAGE_FROM_MEMORY_FORMAT 0x00000404 /* Parameters: pitch origin filter */
+# define NV04_SCALED_IMAGE_FROM_MEMORY_OFFSET 0x00000408
+# define NV04_SCALED_IMAGE_FROM_MEMORY_POINT 0x0000040c /* Parameters: u_int u_frac*0x10 v_int v_frac*0x10 */
+
+/******************************************
+Object NV_IMAGE_FROM_CPU used on: NV04
+*/
+#define NV_IMAGE_FROM_CPU 0x00000061
+# define NV_IMAGE_FROM_CPU_DMA_NOTIFY 0x00000180
+# define NV_IMAGE_FROM_CPU_CLIP_RECTANGLE 0x00000188
+# define NV_IMAGE_FROM_CPU_PATTERN 0x0000018c
+# define NV_IMAGE_FROM_CPU_ROP 0x00000190
+# define NV_IMAGE_FROM_CPU_SURFACE 0x0000019c
+# define NV_IMAGE_FROM_CPU_OPERATION 0x000002fc
+# define NV_IMAGE_FROM_CPU_FORMAT 0x00000300
+
+/******************************************
+Object NV05_IMAGE_FROM_CPU used on: NV04
+*/
+#define NV05_IMAGE_FROM_CPU 0x00000065
+# define NV05_IMAGE_FROM_CPU_DMA_NOTIFY 0x00000180
+# define NV05_IMAGE_FROM_CPU_CLIP_RECTANGLE 0x00000188
+# define NV05_IMAGE_FROM_CPU_PATTERN 0x0000018c
+# define NV05_IMAGE_FROM_CPU_ROP 0x00000190
+# define NV05_IMAGE_FROM_CPU_SURFACE 0x0000019c
+# define NV05_IMAGE_FROM_CPU_OPERATION 0x000002fc
+# define NV05_IMAGE_FROM_CPU_FORMAT 0x00000300
+# define NV05_IMAGE_FROM_CPU_POINT 0x00000304 /* Parameters: x y */
+# define NV05_IMAGE_FROM_CPU_SIZE_OUT 0x00000308 /* Parameters: x y */
+# define NV05_IMAGE_FROM_CPU_SIZE_IN 0x0000030c /* Parameters: x y */
+# define NV05_IMAGE_FROM_CPU_COLOR( d) (0x00000400 + d * 0x0004)
+
+/******************************************
+Object NV_IMAGE_BLIT used on: NV04 NV10 NV15 NV20 NV40
+*/
+#define NV_IMAGE_BLIT 0x0000005f
+# define NV_IMAGE_BLIT_DMA_NOTIFY 0x00000180
+# define NV_IMAGE_BLIT_COLOR_KEY 0x00000184
+# define NV_IMAGE_BLIT_CLIP_RECTANGLE 0x00000188
+# define NV_IMAGE_BLIT_PATTERN 0x0000018c
+# define NV_IMAGE_BLIT_ROP5 0x00000190
+# define NV_IMAGE_BLIT_SURFACE 0x0000019c
+# define NV_IMAGE_BLIT_OPERATION 0x000002fc
+# define NV_IMAGE_BLIT_POINT_IN 0x00000300 /* Parameters: x y */
+# define NV_IMAGE_BLIT_POINT_OUT 0x00000304 /* Parameters: x y */
+# define NV_IMAGE_BLIT_SIZE 0x00000308 /* Parameters: width height */
+
+/******************************************
+Object NV10_TCL_PRIMITIVE_3D used on: NV10
+*/
+#define NV10_TCL_PRIMITIVE_3D 0x00000056
+
+/******************************************
+Object NV17_TCL_PRIMITIVE_3D used on: NV15
+*/
+#define NV17_TCL_PRIMITIVE_3D 0x00000099
+
+/******************************************
+Object NV11_TCL_PRIMITIVE_3D used on: NV15
+*/
+#define NV11_TCL_PRIMITIVE_3D 0x00000096
+# define NV10_TCL_PRIMITIVE_3D_NOP 0x00000100
+# define NV10_TCL_PRIMITIVE_3D_NOTIFY 0x00000104
+# define NV10_TCL_PRIMITIVE_3D_SET_DMA_NOTIFY 0x00000180
+# define NV10_TCL_PRIMITIVE_3D_SET_DMA_IN_MEMORY0 0x00000184
+# define NV10_TCL_PRIMITIVE_3D_SET_DMA_IN_MEMORY1 0x00000188
+# define NV10_TCL_PRIMITIVE_3D_SET_DISPLAY_LIST 0x0000018c
+# define NV10_TCL_PRIMITIVE_3D_SET_DMA_IN_MEMORY2 0x00000194
+# define NV10_TCL_PRIMITIVE_3D_SET_DMA_IN_MEMORY3 0x00000198
+# define NV17_TCL_PRIMITIVE_3D_SET_DMA_IN_MEMORY4 0x000001ac
+# define NV17_TCL_PRIMITIVE_3D_SET_DMA_IN_MEMORY5 0x000001b0
+# define NV10_TCL_PRIMITIVE_3D_VIEWPORT_HORIZ 0x00000200 /* Parameters: width x */
+# define NV10_TCL_PRIMITIVE_3D_VIEWPORT_VERT 0x00000204 /* Parameters: height y */
+# define NV10_TCL_PRIMITIVE_3D_BUFFER_FORMAT 0x00000208 /* Parameters: type color */
+# define NV10_TCL_PRIMITIVE_3D_BUFFER_PITCH 0x0000020c /* Parameters: depth/stencil buffer pitch color buffer pitch */
+# define NV10_TCL_PRIMITIVE_3D_COLOR_OFFSET 0x00000210
+# define NV10_TCL_PRIMITIVE_3D_DEPTH_OFFSET 0x00000214
+# define NV10_TCL_PRIMITIVE_3D_TX_OFFSET(d) (0x00000218 + d * 0x0004)
+# define NV10_TCL_PRIMITIVE_3D_TX_FORMAT(d) (0x00000220 + d * 0x0004) /* Parameters: wrap_t wrap_s log2(height) log2(width) lod npot format cube_map */
+# define NV10_TCL_PRIMITIVE_3D_TX_ENABLE(d) (0x00000228 + d * 0x0004) /* Parameters: enable anisotropy */
+# define NV10_TCL_PRIMITIVE_3D_TX_NPOT_PITCH(d) (0x00000230 + d * 0x0004) /* Parameters: pitch */
+# define NV10_TCL_PRIMITIVE_3D_TX_NPOT_SIZE(d) (0x00000240 + d * 0x0004) /* Parameters: width height */
+# define NV10_TCL_PRIMITIVE_3D_TX_FILTER(d) (0x00000248 + d * 0x0004) /* Parameters: mag_filter min_filter */
+# define NV10_TCL_PRIMITIVE_3D_TX_PALETTE_OFFSET(d) (0x00000250 + d * 0x0004)
+# define NV10_TCL_PRIMITIVE_3D_TX_MATRIX_ENABLE(d) (0x000003e0 + d * 0x0004)
+# define NV10_TCL_PRIMITIVE_3D_TX_MATRIX(x,y) (0x00000540 + y * 0x0010 + x * 0x0004)
+# define NV10_TCL_PRIMITIVE_3D_RC_IN_ALPHA(d) (0x00000260 + d * 0x0004) /* Parameters: vara_mapping vara_component_usage vara_input varb_mapping varb_component_usage varb_input varc_mapping varc_component_usage varc_input vard_mapping vard_component_usage vard_input */
+# define NV10_TCL_PRIMITIVE_3D_RC_IN_RGB(d) (0x00000268 + d * 0x0004) /* Parameters: vara_mapping vara_component_usage vara_input varb_mapping varb_component_usage varb_input varc_mapping varc_component_usage varc_input vard_mapping vard_component_usage vard_input */
+# define NV10_TCL_PRIMITIVE_3D_RC_OUT_ALPHA(d) (0x00000278 + d * 0x0004) /* Parameters: scale bias mux_sum ab_dot_product cd_dot_product sum_output ab_output cd_output */
+# define NV10_TCL_PRIMITIVE_3D_RC_OUT_RGB(d) (0x00000280 + d * 0x0004) /* Parameters: rc1_tx_units_enabled rc1_rc_enabled scale bias mux_sum ab_dot_product cd_dot_product sum_output ab_output cd_output */
+# define NV10_TCL_PRIMITIVE_3D_RC_COLOR0 0x00000270 /* Parameters: a r g b */
+# define NV10_TCL_PRIMITIVE_3D_RC_COLOR1 0x00000274 /* Parameters: a r g b */
+# define NV10_TCL_PRIMITIVE_3D_RC_FINAL0 0x00000288 /* Parameters: vara_mapping vara_component_usage vara_input varb_mapping varb_component_usage varb_input varc_mapping varc_component_usage varc_input vard_mapping vard_component_usage vard_input */
+# define NV10_TCL_PRIMITIVE_3D_RC_FINAL1 0x0000028c /* Parameters: vare_mapping vare_component_usage vare_input varf_mapping varf_component_usage varf_input varg_mapping varg_component_usage varg_input color_sum_clamp */
+# define NV10_TCL_PRIMITIVE_3D_LIGHT_MODEL 0x00000294 /* Parameters: local_viewer color_control */
+# define NV10_TCL_PRIMITIVE_3D_COLOR_MATERIAL_ENABLE 0x00000298 /* Parameters: specular diffuse ambient emission */
+# define NV10_TCL_PRIMITIVE_3D_FOG_MODE 0x0000029c
+# define NV10_TCL_PRIMITIVE_3D_FOG_COORD_DIST 0x000002a0
+# define NV10_TCL_PRIMITIVE_3D_FOG_ENABLE 0x000002a4
+# define NV10_TCL_PRIMITIVE_3D_FOG_COLOR 0x000002a8 /* Parameters: a b g r */
+# define NV17_TCL_PRIMITIVE_3D_COLOR_MASK_ENABLE 0x000002bc
+# define NV10_TCL_PRIMITIVE_3D_VIEWPORT_CLIP_HORIZ(d) (0x000002c0 + d * 0x0004) /* Parameters: x2 x1 */
+# define NV10_TCL_PRIMITIVE_3D_VIEWPORT_CLIP_VERT(d) (0x000002e0 + d * 0x0004) /* Parameters: y2 y1 */
+# define NV10_TCL_PRIMITIVE_3D_ALPHA_FUNC_ENABLE 0x00000300
+# define NV10_TCL_PRIMITIVE_3D_BLEND_FUNC_ENABLE 0x00000304
+# define NV10_TCL_PRIMITIVE_3D_CULL_FACE_ENABLE 0x00000308
+# define NV10_TCL_PRIMITIVE_3D_DEPTH_TEST_ENABLE 0x0000030c
+# define NV10_TCL_PRIMITIVE_3D_DITHER_ENABLE 0x00000310
+# define NV10_TCL_PRIMITIVE_3D_LIGHTING_ENABLE 0x00000314
+# define NV10_TCL_PRIMITIVE_3D_POINT_PARAMETERS_ENABLE 0x00000318
+# define NV10_TCL_PRIMITIVE_3D_POINT_SMOOTH_ENABLE 0x0000031c
+# define NV10_TCL_PRIMITIVE_3D_LINE_SMOOTH_ENABLE 0x00000320
+# define NV10_TCL_PRIMITIVE_3D_POLYGON_SMOOTH_ENABLE 0x00000324
+# define NV10_TCL_PRIMITIVE_3D_VERTEX_WEIGHT_ENABLE 0x00000328
+# define NV10_TCL_PRIMITIVE_3D_STENCIL_ENABLE 0x0000032c
+# define NV10_TCL_PRIMITIVE_3D_POLYGON_OFFSET_POINT_ENABLE 0x00000330
+# define NV10_TCL_PRIMITIVE_3D_POLYGON_OFFSET_LINE_ENABLE 0x00000334
+# define NV10_TCL_PRIMITIVE_3D_POLYGON_OFFSET_FILL_ENABLE 0x00000338
+# define NV10_TCL_PRIMITIVE_3D_ALPHA_FUNC_FUNC 0x0000033c
+# define NV10_TCL_PRIMITIVE_3D_ALPHA_FUNC_REF 0x00000340
+# define NV10_TCL_PRIMITIVE_3D_BLEND_FUNC_SRC 0x00000344
+# define NV10_TCL_PRIMITIVE_3D_BLEND_FUNC_DST 0x00000348
+# define NV10_TCL_PRIMITIVE_3D_BLEND_COLOR 0x0000034c /* Parameters: a r g b */
+# define NV10_TCL_PRIMITIVE_3D_BLEND_EQUATION 0x00000350
+# define NV10_TCL_PRIMITIVE_3D_DEPTH_FUNC 0x00000354
+# define NV10_TCL_PRIMITIVE_3D_COLOR_MASK 0x00000358 /* Parameters: a r g b */
+# define NV10_TCL_PRIMITIVE_3D_DEPTH_WRITE_ENABLE 0x0000035c
+# define NV10_TCL_PRIMITIVE_3D_STENCIL_MASK 0x00000360
+# define NV10_TCL_PRIMITIVE_3D_STENCIL_FUNC_FUNC 0x00000364
+# define NV10_TCL_PRIMITIVE_3D_STENCIL_FUNC_REF 0x00000368
+# define NV10_TCL_PRIMITIVE_3D_STENCIL_FUNC_MASK 0x0000036c
+# define NV10_TCL_PRIMITIVE_3D_STENCIL_OP_FAIL 0x00000370
+# define NV10_TCL_PRIMITIVE_3D_STENCIL_OP_ZFAIL 0x00000374
+# define NV10_TCL_PRIMITIVE_3D_STENCIL_OP_ZPASS 0x00000378
+# define NV10_TCL_PRIMITIVE_3D_SHADE_MODEL 0x0000037c
+# define NV10_TCL_PRIMITIVE_3D_LINE_WIDTH 0x00000380
+# define NV10_TCL_PRIMITIVE_3D_POLYGON_OFFSET_FACTOR 0x00000384
+# define NV10_TCL_PRIMITIVE_3D_POLYGON_OFFSET_UNITS 0x00000388
+# define NV10_TCL_PRIMITIVE_3D_POLYGON_MODE_FRONT 0x0000038c
+# define NV10_TCL_PRIMITIVE_3D_POLYGON_MODE_BACK 0x00000390
+# define NV10_TCL_PRIMITIVE_3D_DEPTH_RANGE_NEAR 0x00000394
+# define NV10_TCL_PRIMITIVE_3D_DEPTH_RANGE_FAR 0x00000398
+# define NV10_TCL_PRIMITIVE_3D_CULL_FACE 0x0000039c
+# define NV10_TCL_PRIMITIVE_3D_FRONT_FACE 0x000003a0
+# define NV10_TCL_PRIMITIVE_3D_NORMALIZE_ENABLE 0x000003a4
+# define NV10_TCL_PRIMITIVE_3D_COLOR_MATERIAL_R 0x000003a8
+# define NV10_TCL_PRIMITIVE_3D_COLOR_MATERIAL_G 0x000003ac
+# define NV10_TCL_PRIMITIVE_3D_COLOR_MATERIAL_B 0x000003b0
+# define NV10_TCL_PRIMITIVE_3D_COLOR_MATERIAL_A 0x000003b4
+# define NV10_TCL_PRIMITIVE_3D_COLOR_CONTROL 0x000003b8 /* Parameters: color_control */
+# define NV10_TCL_PRIMITIVE_3D_ENABLED_LIGHTS 0x000003bc /* Parameters: light 7 light 6 light 5 light 4 light 3 light 2 light 1 light 0 */
+# define NV10_TCL_PRIMITIVE_3D_CLIP_PLANE_ENABLE( d) (0x000003c0 + d * 0x0004)
+# define NV10_TCL_PRIMITIVE_3D_VIEW_MATRIX_ENABLE 0x000003e8 /* Parameters: projection modelview0 modelview1 */
+# define NV10_TCL_PRIMITIVE_3D_POINT_SIZE 0x000003ec
+# define NV10_TCL_PRIMITIVE_3D_MODELVIEW0_MATRIX( d) (0x00000400 + d * 0x0004)
+# define NV10_TCL_PRIMITIVE_3D_MODELVIEW1_MATRIX( d) (0x00000440 + d * 0x0004)
+# define NV10_TCL_PRIMITIVE_3D_INVERSE_MODELVIEW0_MATRIX( d) (0x00000480 + d * 0x0004)
+# define NV10_TCL_PRIMITIVE_3D_INVERSE_MODELVIEW1_MATRIX( d) (0x000004c0 + d * 0x0004)
+# define NV10_TCL_PRIMITIVE_3D_PROJECTION_MATRIX( d) (0x00000500 + d * 0x0004)
+# define NV10_TCL_PRIMITIVE_3D_CLIP_PLANE_A(d) (0x00000600 + d * 0x0010)
+# define NV10_TCL_PRIMITIVE_3D_CLIP_PLANE_B(d) (0x00000604 + d * 0x0010)
+# define NV10_TCL_PRIMITIVE_3D_CLIP_PLANE_C(d) (0x00000608 + d * 0x0010)
+# define NV10_TCL_PRIMITIVE_3D_CLIP_PLANE_D(d) (0x0000060c + d * 0x0010)
+# define NV10_TCL_PRIMITIVE_3D_FOG_EQUATION_CONSTANT 0x00000680
+# define NV10_TCL_PRIMITIVE_3D_FOG_EQUATION_LINEAR 0x00000684
+# define NV10_TCL_PRIMITIVE_3D_FOG_EQUATION_QUADRATIC 0x00000688
+# define NV10_TCL_PRIMITIVE_3D_FRONT_MATERIAL_SHININESS_A 0x000006a0
+# define NV10_TCL_PRIMITIVE_3D_FRONT_MATERIAL_SHININESS_B 0x000006a4
+# define NV10_TCL_PRIMITIVE_3D_FRONT_MATERIAL_SHININESS_C 0x000006a8
+# define NV10_TCL_PRIMITIVE_3D_FRONT_MATERIAL_SHININESS_D 0x000006ac
+# define NV10_TCL_PRIMITIVE_3D_FRONT_MATERIAL_SHININESS_E 0x000006b0
+# define NV10_TCL_PRIMITIVE_3D_FRONT_MATERIAL_SHININESS_F 0x000006b4
+# define NV10_TCL_PRIMITIVE_3D_LIGHT_MODEL_FRONT_SIDE_PRODUCT_AMBIENT_PLUS_EMISSION_R 0x000006c4
+# define NV10_TCL_PRIMITIVE_3D_LIGHT_MODEL_FRONT_SIDE_PRODUCT_AMBIENT_PLUS_EMISSION_G 0x000006c8
+# define NV10_TCL_PRIMITIVE_3D_LIGHT_MODEL_FRONT_SIDE_PRODUCT_AMBIENT_PLUS_EMISSION_B 0x000006cc
+# define NV10_TCL_PRIMITIVE_3D_VIEWPORT_SCALE_X 0x000006e8
+# define NV10_TCL_PRIMITIVE_3D_VIEWPORT_SCALE_Y 0x000006ec
+# define NV10_TCL_PRIMITIVE_3D_VIEWPORT_SCALE_Z 0x000006f0
+# define NV10_TCL_PRIMITIVE_3D_VIEWPORT_SCALE_W 0x000006f4
+# define NV10_TCL_PRIMITIVE_3D_POINT_PARAMETER_A 0x000006f8
+# define NV10_TCL_PRIMITIVE_3D_POINT_PARAMETER_B 0x000006fc
+# define NV10_TCL_PRIMITIVE_3D_POINT_PARAMETER_C 0x00000700
+# define NV10_TCL_PRIMITIVE_3D_POINT_PARAMETER_D 0x00000704
+# define NV10_TCL_PRIMITIVE_3D_POINT_PARAMETER_E 0x00000708
+# define NV10_TCL_PRIMITIVE_3D_POINT_PARAMETER_F 0x0000070c
+# define NV10_TCL_PRIMITIVE_3D_POINT_PARAMETER_G 0x00000710
+# define NV10_TCL_PRIMITIVE_3D_POINT_PARAMETER_H 0x00000714
+# define NV10_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_AMBIENT_R(d) (0x00000800 + d * 0x0080)
+# define NV10_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_AMBIENT_G(d) (0x00000804 + d * 0x0080)
+# define NV10_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_AMBIENT_B(d) (0x00000808 + d * 0x0080)
+# define NV10_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_DIFFUSE_R(d) (0x0000080c + d * 0x0080)
+# define NV10_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_DIFFUSE_G(d) (0x00000810 + d * 0x0080)
+# define NV10_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_DIFFUSE_B(d) (0x00000814 + d * 0x0080)
+# define NV10_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_SPECULAR_R(d) (0x00000818 + d * 0x0080)
+# define NV10_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_SPECULAR_G(d) (0x0000081c + d * 0x0080)
+# define NV10_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_SPECULAR_B(d) (0x00000820 + d * 0x0080)
+# define NV10_TCL_PRIMITIVE_3D_LIGHT_HALF_VECTOR_X(d) (0x00000828 + d * 0x0080)
+# define NV10_TCL_PRIMITIVE_3D_LIGHT_HALF_VECTOR_Y(d) (0x0000082c + d * 0x0080)
+# define NV10_TCL_PRIMITIVE_3D_LIGHT_HALF_VECTOR_Z(d) (0x00000830 + d * 0x0080)
+# define NV10_TCL_PRIMITIVE_3D_LIGHT_DIRECTION_X(d) (0x00000834 + d * 0x0080)
+# define NV10_TCL_PRIMITIVE_3D_LIGHT_DIRECTION_Y(d) (0x00000838 + d * 0x0080)
+# define NV10_TCL_PRIMITIVE_3D_LIGHT_DIRECTION_Z(d) (0x0000083c + d * 0x0080)
+# define NV10_TCL_PRIMITIVE_3D_LIGHT_SPOT_CUTOFF_A(d) (0x00000840 + d * 0x0080)
+# define NV10_TCL_PRIMITIVE_3D_LIGHT_SPOT_EXPONENT(d) (0x00000844 + d * 0x0080)
+# define NV10_TCL_PRIMITIVE_3D_LIGHT_SPOT_CUTOFF_B(d) (0x00000848 + d * 0x0080)
+# define NV10_TCL_PRIMITIVE_3D_LIGHT_SPOT_DIR_X(d) (0x0000084c + d * 0x0080)
+# define NV10_TCL_PRIMITIVE_3D_LIGHT_SPOT_DIR_Y(d) (0x00000850 + d * 0x0080)
+# define NV10_TCL_PRIMITIVE_3D_LIGHT_SPOT_DIR_Z(d) (0x00000854 + d * 0x0080)
+# define NV10_TCL_PRIMITIVE_3D_LIGHT_SPOT_CUTOFF_C(d) (0x00000858 + d * 0x0080)
+# define NV10_TCL_PRIMITIVE_3D_LIGHT_POSITION_X(d) (0x0000085c + d * 0x0080)
+# define NV10_TCL_PRIMITIVE_3D_LIGHT_POSITION_Y(d) (0x00000860 + d * 0x0080)
+# define NV10_TCL_PRIMITIVE_3D_LIGHT_POSITION_Z(d) (0x00000864 + d * 0x0080)
+# define NV10_TCL_PRIMITIVE_3D_LIGHT_CONSTANT_ATTENUATION(d) (0x00000868 + d * 0x0080)
+# define NV10_TCL_PRIMITIVE_3D_LIGHT_LINEAR_ATTENUATION(d) (0x0000086c + d * 0x0080)
+# define NV10_TCL_PRIMITIVE_3D_LIGHT_QUADRATIC_ATTENUATION(d) (0x00000870 + d * 0x0080)
+# define NV10_TCL_PRIMITIVE_3D_VERTEX_POS_3F_X 0x00000c00
+# define NV10_TCL_PRIMITIVE_3D_VERTEX_POS_3F_Y 0x00000c04
+# define NV10_TCL_PRIMITIVE_3D_VERTEX_POS_3F_Z 0x00000c08
+# define NV10_TCL_PRIMITIVE_3D_VERTEX_POS_4F_X 0x00000c18
+# define NV10_TCL_PRIMITIVE_3D_VERTEX_POS_4F_Y 0x00000c1c
+# define NV10_TCL_PRIMITIVE_3D_VERTEX_POS_4F_Z 0x00000c20
+# define NV10_TCL_PRIMITIVE_3D_VERTEX_POS_4F_W 0x00000c24
+# define NV10_TCL_PRIMITIVE_3D_VERTEX_NOR_3F_X 0x00000c30
+# define NV10_TCL_PRIMITIVE_3D_VERTEX_NOR_3F_Y 0x00000c34
+# define NV10_TCL_PRIMITIVE_3D_VERTEX_NOR_3F_Z 0x00000c38
+# define NV10_TCL_PRIMITIVE_3D_VERTEX_NOR_3I_XY 0x00000c40 /* Parameters: y x */
+# define NV10_TCL_PRIMITIVE_3D_VERTEX_NOR_3I_Z 0x00000c44 /* Parameters: z */
+# define NV10_TCL_PRIMITIVE_3D_VERTEX_COL_4F_R 0x00000c50
+# define NV10_TCL_PRIMITIVE_3D_VERTEX_COL_4F_G 0x00000c54
+# define NV10_TCL_PRIMITIVE_3D_VERTEX_COL_4F_B 0x00000c58
+# define NV10_TCL_PRIMITIVE_3D_VERTEX_COL_4F_A 0x00000c5c
+# define NV10_TCL_PRIMITIVE_3D_VERTEX_COL_3F_R 0x00000c60
+# define NV10_TCL_PRIMITIVE_3D_VERTEX_COL_3F_G 0x00000c64
+# define NV10_TCL_PRIMITIVE_3D_VERTEX_COL_3F_B 0x00000c68
+# define NV10_TCL_PRIMITIVE_3D_VERTEX_COL_4I 0x00000c6c /* Parameters: a b g r */
+# define NV10_TCL_PRIMITIVE_3D_VERTEX_COL2_3F_R 0x00000c80
+# define NV10_TCL_PRIMITIVE_3D_VERTEX_COL2_3F_G 0x00000c84
+# define NV10_TCL_PRIMITIVE_3D_VERTEX_COL2_3F_B 0x00000c88
+# define NV10_TCL_PRIMITIVE_3D_VERTEX_COL2_3I 0x00000c8c /* Parameters: a b g r */
+# define NV10_TCL_PRIMITIVE_3D_VERTEX_TX0_2F_S 0x00000c90
+# define NV10_TCL_PRIMITIVE_3D_VERTEX_TX0_2F_T 0x00000c94
+# define NV10_TCL_PRIMITIVE_3D_VERTEX_TX0_2I 0x00000c98 /* Parameters: t s */
+# define NV10_TCL_PRIMITIVE_3D_VERTEX_TX0_4F_S 0x00000ca0
+# define NV10_TCL_PRIMITIVE_3D_VERTEX_TX0_4F_T 0x00000ca4
+# define NV10_TCL_PRIMITIVE_3D_VERTEX_TX0_4F_R 0x00000ca8
+# define NV10_TCL_PRIMITIVE_3D_VERTEX_TX0_4F_Q 0x00000cac
+# define NV10_TCL_PRIMITIVE_3D_VERTEX_TX0_4I_ST 0x00000cb0 /* Parameters: t s */
+# define NV10_TCL_PRIMITIVE_3D_VERTEX_TX0_4I_RQ 0x00000cb4 /* Parameters: q r */
+# define NV10_TCL_PRIMITIVE_3D_VERTEX_TX1_2F_S 0x00000cb8
+# define NV10_TCL_PRIMITIVE_3D_VERTEX_TX1_2F_T 0x00000cbc
+# define NV10_TCL_PRIMITIVE_3D_VERTEX_TX1_2I 0x00000cc0 /* Parameters: t s */
+# define NV10_TCL_PRIMITIVE_3D_VERTEX_TX1_4F_S 0x00000cc8
+# define NV10_TCL_PRIMITIVE_3D_VERTEX_TX1_4F_T 0x00000ccc
+# define NV10_TCL_PRIMITIVE_3D_VERTEX_TX1_4F_R 0x00000cd0
+# define NV10_TCL_PRIMITIVE_3D_VERTEX_TX1_4F_Q 0x00000cd4
+# define NV10_TCL_PRIMITIVE_3D_VERTEX_TX1_4I_ST 0x00000cd8 /* Parameters: t s */
+# define NV10_TCL_PRIMITIVE_3D_VERTEX_TX1_4I_RQ 0x00000cdc /* Parameters: q r */
+# define NV10_TCL_PRIMITIVE_3D_VERTEX_FOG_1F 0x00000ce0
+# define NV10_TCL_PRIMITIVE_3D_VERTEX_WGH_1F 0x00000ce4
+# define NV10_TCL_PRIMITIVE_3D_EDGEFLAG_ENABLE 0x00000cec
+# define NV10_TCL_PRIMITIVE_3D_VERTEX_ATTR( d) (0x00000d04 + d * 0x0008) /* Parameters: stride fields type */
+# define NV10_TCL_PRIMITIVE_3D_VERTEX_ARRAY_VALIDATE 0x00000cf0
+# define NV10_TCL_PRIMITIVE_3D_VERTEX_ARRAY_OFFSET_POS 0x00000d00
+# define NV10_TCL_PRIMITIVE_3D_VERTEX_ARRAY_FORMAT_POS 0x00000d04 /* Parameters: stride fields type */
+# define NV10_TCL_PRIMITIVE_3D_VERTEX_ARRAY_OFFSET_COL 0x00000d08
+# define NV10_TCL_PRIMITIVE_3D_VERTEX_ARRAY_FORMAT_COL 0x00000d0c /* Parameters: stride fields type */
+# define NV10_TCL_PRIMITIVE_3D_VERTEX_ARRAY_OFFSET_COL2 0x00000d10
+# define NV10_TCL_PRIMITIVE_3D_VERTEX_ARRAY_FORMAT_COL2 0x00000d14 /* Parameters: stride fields type */
+# define NV10_TCL_PRIMITIVE_3D_VERTEX_ARRAY_OFFSET_TX0 0x00000d18
+# define NV10_TCL_PRIMITIVE_3D_VERTEX_ARRAY_FORMAT_TX0 0x00000d1c /* Parameters: stride fields type */
+# define NV10_TCL_PRIMITIVE_3D_VERTEX_ARRAY_OFFSET_TX1 0x00000d20
+# define NV10_TCL_PRIMITIVE_3D_VERTEX_ARRAY_FORMAT_TX1 0x00000d24 /* Parameters: stride fields type */
+# define NV10_TCL_PRIMITIVE_3D_VERTEX_ARRAY_OFFSET_NOR 0x00000d28
+# define NV10_TCL_PRIMITIVE_3D_VERTEX_ARRAY_FORMAT_NOR 0x00000d2c /* Parameters: stride fields type */
+# define NV10_TCL_PRIMITIVE_3D_VERTEX_ARRAY_OFFSET_WGH 0x00000d30
+# define NV10_TCL_PRIMITIVE_3D_VERTEX_ARRAY_FORMAT_WGH 0x00000d34 /* Parameters: stride fields type */
+# define NV10_TCL_PRIMITIVE_3D_VERTEX_ARRAY_OFFSET_FOG 0x00000d38
+# define NV10_TCL_PRIMITIVE_3D_VERTEX_ARRAY_FORMAT_FOG 0x00000d3c /* Parameters: stride fields type */
+# define NV10_TCL_PRIMITIVE_3D_COLOR_LOGIC_OP_ENABLE 0x00000d40
+# define NV10_TCL_PRIMITIVE_3D_COLOR_LOGIC_OP_OP 0x00000d44
+# define NV17_TCL_PRIMITIVE_3D_LMA_DEPTH_BUFFER_PITCH 0x00000d5c /* Parameters: pitch */
+# define NV17_TCL_PRIMITIVE_3D_LMA_DEPTH_BUFFER_OFFSET 0x00000d60
+# define NV17_TCL_PRIMITIVE_3D_LMA_DEPTH_FILL_VALUE 0x00000d68
+# define NV17_TCL_PRIMITIVE_3D_LMA_DEPTH_CLEAR_ENABLE 0x00000d6c
+# define NV10_TCL_PRIMITIVE_3D_BEGIN_END 0x00000dfc
+# define NV10_TCL_PRIMITIVE_3D_INDEX_DATA 0x00000e00 /* Parameters: index1 index0 */
+# define NV10_TCL_PRIMITIVE_3D_VERTEX_BUFFER_BEGIN_END 0x000013fc
+# define NV10_TCL_PRIMITIVE_3D_VERTEX_BUFFER_DRAW_ARRAYS 0x00001400 /* Parameters: count-1 first */
+# define NV10_TCL_PRIMITIVE_3D_VIEWPORT_ORIGIN_X 0x00001638
+# define NV10_TCL_PRIMITIVE_3D_VIEWPORT_ORIGIN_Y 0x0000163c
+# define NV10_TCL_PRIMITIVE_3D_VIEWPORT_ORIGIN_Z 0x00001640
+# define NV10_TCL_PRIMITIVE_3D_VIEWPORT_ORIGIN_W 0x00001644
+# define NV17_TCL_PRIMITIVE_3D_LMA_DEPTH_ENABLE 0x00001658
+# define NV10_TCL_PRIMITIVE_3D_VERTEX_ARRAY_DATA 0x00001800
+
+/******************************************
+Object NV10_IMAGE_FROM_CPU used on: NV10 NV15 NV20 NV30 NV40 G70
+*/
+#define NV10_IMAGE_FROM_CPU 0x0000008a
+# define NV10_IMAGE_FROM_CPU_SET_DMA_NOTIFY 0x00000180
+# define NV10_IMAGE_FROM_CPU_SET_CONTEXT_CLIP_RECTANGLE 0x00000188
+# define NV10_IMAGE_FROM_CPU_SET_IMAGE_PATTERN 0x0000018c
+# define NV10_IMAGE_FROM_CPU_SET_RASTER_OP 0x00000190
+# define NV10_IMAGE_FROM_CPU_SET_CONTEXT_SURFACES_2D 0x0000019c
+# define NV10_IMAGE_FROM_CPU_OPERATION 0x000002fc
+# define NV10_IMAGE_FROM_CPU_FORMAT 0x00000300
+# define NV10_IMAGE_FROM_CPU_POINT 0x00000304 /* Parameters: x y */
+# define NV10_IMAGE_FROM_CPU_SIZE_OUT 0x00000308 /* Parameters: width height */
+# define NV10_IMAGE_FROM_CPU_SIZE_IN 0x0000030c /* Parameters: width height */
+# define NV10_IMAGE_FROM_CPU_HLINE 0x00000400
+
+/******************************************
+Object NV10_PRIMITIVE_2D used on: NV10 NV15 NV20 NV30 NV40 G70
+*/
+#define NV10_PRIMITIVE_2D 0x0000007b
+# define NV10_PRIMITIVE_2D_SET_DMA_NOTIFY 0x00000180
+# define NV10_PRIMITIVE_2D_SET_SURFACE 0x00000184
+# define NV10_PRIMITIVE_2D_SET_FORMAT 0x00000300
+# define NV10_PRIMITIVE_2D_SET_POINT 0x00000304 /* Parameters: x y */
+# define NV10_PRIMITIVE_2D_SET_SIZE 0x00000308 /* Parameters: width height */
+# define NV10_PRIMITIVE_2D_SET_CLIP_HORIZ 0x0000030c /* Parameters: width x */
+# define NV10_PRIMITIVE_2D_SET_CLIP_VERT 0x00000310 /* Parameters: height y */
+# define NV10_PRIMITIVE_2D_SET_DATA( d) (0x00000400 + d * 0x0004)
+
+/******************************************
+Object NV10_IMAGE_BLIT used on: NV10 NV15 NV20 NV30 NV40 G70
+*/
+#define NV10_IMAGE_BLIT 0x0000009f
+# define NV10_IMAGE_BLIT_NOP 0x00000100
+# define NV10_IMAGE_BLIT_NOTIFY 0x00000104
+# define NV10_IMAGE_BLIT_SET_DMA_NOTIFY 0x00000180
+# define NV10_IMAGE_BLIT_SET_CONTEXT_CLIP_RECTANGLE 0x00000188
+# define NV10_IMAGE_BLIT_SET_IMAGE_PATTERN 0x0000018c
+# define NV10_IMAGE_BLIT_SET_RASTER_OP 0x00000190
+# define NV10_IMAGE_BLIT_SET_CONTEXT_SURFACES_2D 0x0000019c
+# define NV10_IMAGE_BLIT_SET_OPERATION 0x000002fc
+# define NV10_IMAGE_BLIT_SET_POINT 0x00000300 /* Parameters: x y */
+# define NV10_IMAGE_BLIT_SET_PITCH 0x00000304 /* Parameters: skip */
+# define NV10_IMAGE_BLIT_SET_SIZE 0x00000308 /* Parameters: width height */
+
+/******************************************
+Object NV10_VIDEO_DISPLAY used on: NV10 NV15 NV20 NV30 NV40 G70
+*/
+#define NV10_VIDEO_DISPLAY 0x0000007c
+# define NV10_VIDEO_DISPLAY_COUNTER 0x00000050
+# define NV10_VIDEO_DISPLAY_SET_DMA_FROM_MEMORY 0x00000180
+# define NV10_VIDEO_DISPLAY_SET_DMA_IN_MEMORY0 0x00000184
+# define NV10_VIDEO_DISPLAY_SET_DMA_IN_MEMORY1 0x00000188
+# define NV10_VIDEO_DISPLAY_SET_OBJECT3 0x0000019c
+# define NV10_VIDEO_DISPLAY_SIZE 0x000002f8 /* Parameters: height width */
+# define NV10_VIDEO_DISPLAY_OFFSET 0x00000300
+
+/******************************************
+Object NV10_UNK0072 used on: NV10 NV15 NV20 NV40 G70
+*/
+#define NV10_UNK0072 0x00000072
+# define NV10_UNK0072_COUNTER 0x00000050
+# define NV40_UNK0072_SET_OBJECT 0x00000060
+# define NV10_UNK0072_SET_DMA_NOTIFY 0x00000180
+
+/******************************************
+Object NV10_SCALED_IMAGE_FROM_MEMORY used on: NV10 NV15 NV20 NV30 NV40 G70
+*/
+#define NV10_SCALED_IMAGE_FROM_MEMORY 0x00000089
+# define NV10_SCALED_IMAGE_FROM_MEMORY_COUNTER 0x00000050
+# define NV10_SCALED_IMAGE_FROM_MEMORY_SET_DMA_IN_MEMORY 0x00000184
+# define NV10_SCALED_IMAGE_FROM_MEMORY_SET_RASTER_OP 0x0000018c
+# define NV10_SCALED_IMAGE_FROM_MEMORY_SET_IMAGE_PATTERN 0x00000188
+# define NV10_SCALED_IMAGE_FROM_MEMORY_SET_SURFACE 0x00000198
+# define NV10_SCALED_IMAGE_FROM_MEMORY_OPERATION 0x00000304
+# define NV10_SCALED_IMAGE_FROM_MEMORY_CLIP_POS 0x00000308 /* Parameters: x y */
+# define NV10_SCALED_IMAGE_FROM_MEMORY_CLIP_SIZE 0x0000030c /* Parameters: width height */
+# define NV10_SCALED_IMAGE_FROM_MEMORY_OUT_POS 0x00000310 /* Parameters: x y */
+# define NV10_SCALED_IMAGE_FROM_MEMORY_OUT_SIZE 0x00000314 /* Parameters: width height */
+# define NV10_SCALED_IMAGE_FROM_MEMORY_SIZE 0x00000400 /* Parameters: width height */
+# define NV10_SCALED_IMAGE_FROM_MEMORY_FORMAT 0x00000404 /* Parameters: pitch */
+# define NV10_SCALED_IMAGE_FROM_MEMORY_OFFSET 0x00000408
+# define NV10_SCALED_IMAGE_FROM_MEMORY_POINT 0x0000040c /* Parameters: u_int u_frac*0x10 v_int v_frac*0x10 */
+
+/******************************************
+Object NV10_CONTEXT_SURFACES_2D used on: NV10 NV15 NV20 NV30 NV40 G70
+*/
+#define NV10_CONTEXT_SURFACES_2D 0x00000062
+# define NV10_CONTEXT_SURFACES_2D_SET_DMA_NOTIFY 0x00000180
+# define NV10_CONTEXT_SURFACES_2D_SET_DMA_IN_MEMORY0 0x00000184
+# define NV10_CONTEXT_SURFACES_2D_SET_DMA_IN_MEMORY1 0x00000188
+# define NV10_CONTEXT_SURFACES_2D_FORMAT 0x00000300 /* Parameters: color type width height */
+# define NV10_CONTEXT_SURFACES_2D_PITCH 0x00000304 /* Parameters: src dst */
+# define NV10_CONTEXT_SURFACES_2D_OFFSET_SRC 0x00000308
+# define NV10_CONTEXT_SURFACES_2D_OFFSET_DST 0x0000030c
+
+/******************************************
+Object NV04_CONTEXT_SURFACES_2D used on: NV04 NV10 NV15
+*/
+#define NV04_CONTEXT_SURFACES_2D 0x00000042
+# define NV04_CONTEXT_SURFACES_2D_NOTIFY 0x00000104
+# define NV04_CONTEXT_SURFACES_2D_SET_DMA_NOTIFY 0x00000180
+# define NV04_CONTEXT_SURFACES_2D_SET_DMA_IMAGE_SRC 0x00000184
+# define NV04_CONTEXT_SURFACES_2D_SET_DMA_IMAGE_DST 0x00000188
+# define NV04_CONTEXT_SURFACES_2D_FORMAT 0x00000300
+# define NV04_CONTEXT_SURFACES_2D_PITCH 0x00000304 /* Parameters: src dst */
+# define NV04_CONTEXT_SURFACES_2D_OFFSET_SRC 0x00000308
+# define NV04_CONTEXT_SURFACES_2D_OFFSET_DST 0x0000030c
+
+/******************************************
+Object NV04_IMAGE_PATTERN used on: NV04 NV10 NV15 NV20 NV30 NV40 G70
+*/
+#define NV04_IMAGE_PATTERN 0x00000044
+# define NV04_IMAGE_PATTERN_COLOR_FORMAT 0x00000300
+# define NV04_IMAGE_PATTERN_MONO_FORMAT 0x00000304
+# define NV04_IMAGE_PATTERN_SELECT 0x0000030c
+# define NV04_IMAGE_PATTERN_MONOCHROME_SHAPE 0x00000308
+# define NV04_IMAGE_PATTERN_MONOCHROME_COLOR0 0x00000310
+# define NV04_IMAGE_PATTERN_MONOCHROME_COLOR1 0x00000314
+# define NV04_IMAGE_PATTERN_MONOCHROME_PATTERN0 0x00000318
+# define NV04_IMAGE_PATTERN_MONOCHROME_PATTERN1 0x0000031c
+
+/******************************************
+Object NV20_SWIZZLED_SURFACE used on: NV20 NV30 NV40 G70
+*/
+#define NV20_SWIZZLED_SURFACE 0x0000009e
+# define NV20_SWIZZLED_SURFACE_SET_OBJECT0 0x00000180
+# define NV20_SWIZZLED_SURFACE_SET_OBJECT1 0x00000184
+# define NV20_SWIZZLED_SURFACE_FORMAT 0x00000300 /* Parameters: log2(height) log2(width) color */
+# define NV20_SWIZZLED_SURFACE_OFFSET 0x00000304
+
+/******************************************
+Object NV20_TCL_PRIMITIVE_3D used on: NV20
+*/
+#define NV20_TCL_PRIMITIVE_3D 0x00000097
+# define NV20_TCL_PRIMITIVE_3D_NOP 0x00000100
+# define NV20_TCL_PRIMITIVE_3D_NOTIFY 0x00000104
+# define NV20_TCL_PRIMITIVE_3D_SET_OBJECT0 0x00000180
+# define NV20_TCL_PRIMITIVE_3D_SET_OBJECT1 0x00000184
+# define NV20_TCL_PRIMITIVE_3D_SET_OBJECT2 0x00000188
+# define NV20_TCL_PRIMITIVE_3D_SET_OBJECT3 0x00000194
+# define NV20_TCL_PRIMITIVE_3D_SET_OBJECT4 0x00000198
+# define NV20_TCL_PRIMITIVE_3D_SET_OBJECT5 0x0000019c
+# define NV20_TCL_PRIMITIVE_3D_SET_OBJECT6 0x000001a0
+# define NV20_TCL_PRIMITIVE_3D_SET_OBJECT7 0x000001a4
+# define NV20_TCL_PRIMITIVE_3D_SET_OBJECT8 0x000001a8
+# define NV20_TCL_PRIMITIVE_3D_SET_OBJECT9 0x000001ac
+# define NV20_TCL_PRIMITIVE_3D_SET_OBJECT10 0x000001b0
+# define NV20_TCL_PRIMITIVE_3D_VIEWPORT_HORIZ 0x00000200 /* Parameters: width x */
+# define NV20_TCL_PRIMITIVE_3D_VIEWPORT_VERT 0x00000204 /* Parameters: height y */
+# define NV20_TCL_PRIMITIVE_3D_BUFFER_FORMAT 0x00000208 /* Parameters: type color */
+# define NV20_TCL_PRIMITIVE_3D_BUFFER_PITCH 0x0000020c /* Parameters: depth/stencil buffer pitch color buffer pitch */
+# define NV20_TCL_PRIMITIVE_3D_COLOR_OFFSET 0x00000210
+# define NV20_TCL_PRIMITIVE_3D_DEPTH_OFFSET 0x00000214
+# define NV20_TCL_PRIMITIVE_3D_LMA_DEPTH_BUFFER_PITCH 0x0000022c /* Parameters: pitch */
+# define NV20_TCL_PRIMITIVE_3D_LMA_DEPTH_BUFFER_OFFSET 0x00000230
+# define NV20_TCL_PRIMITIVE_3D_LIGHT_CONTROL 0x00000294
+# define NV20_TCL_PRIMITIVE_3D_COLOR_MATERIAL_CONTROL 0x00000298 /* Parameters: back_specular back_ambient back_diffuse back_emission front_specular front_ambient front_diffuse front_emission */
+# define NV20_TCL_PRIMITIVE_3D_FOG_MODE 0x0000029c
+# define NV20_TCL_PRIMITIVE_3D_FOG_COORD_DIST 0x000002a0
+# define NV20_TCL_PRIMITIVE_3D_FOG_ENABLE 0x000002a4
+# define NV20_TCL_PRIMITIVE_3D_VIEWPORT_CLIP_HORIZ(d) (0x000002c0 + d * 0x0004) /* Parameters: x2 x1 */
+# define NV20_TCL_PRIMITIVE_3D_VIEWPORT_CLIP_VERT(d) (0x000002e0 + d * 0x0004) /* Parameters: y2 y1 */
+# define NV20_TCL_PRIMITIVE_3D_ALPHA_FUNC_ENABLE 0x00000300
+# define NV20_TCL_PRIMITIVE_3D_BLEND_FUNC_ENABLE 0x00000304
+# define NV20_TCL_PRIMITIVE_3D_CULL_FACE_ENABLE 0x00000308
+# define NV20_TCL_PRIMITIVE_3D_DEPTH_TEST_ENABLE 0x0000030c
+# define NV20_TCL_PRIMITIVE_3D_DITHER_ENABLE 0x00000310
+# define NV20_TCL_PRIMITIVE_3D_LIGHTING_ENABLE 0x00000314
+# define NV20_TCL_PRIMITIVE_3D_POINT_SMOOTH_ENABLE 0x0000031c
+# define NV20_TCL_PRIMITIVE_3D_POINT_PARAMETERS_ENABLE 0x00000318
+# define NV20_TCL_PRIMITIVE_3D_LINE_SMOOTH_ENABLE 0x00000320
+# define NV20_TCL_PRIMITIVE_3D_POLYGON_SMOOTH_ENABLE 0x00000324
+# define NV20_TCL_PRIMITIVE_3D_STENCIL_ENABLE 0x0000032c
+# define NV20_TCL_PRIMITIVE_3D_POLYGON_OFFSET_POINT_ENABLE 0x00000330
+# define NV20_TCL_PRIMITIVE_3D_POLYGON_OFFSET_LINE_ENABLE 0x00000334
+# define NV20_TCL_PRIMITIVE_3D_POLYGON_OFFSET_FILL_ENABLE 0x00000338
+# define NV20_TCL_PRIMITIVE_3D_ALPHA_FUNC_FUNC 0x0000033c
+# define NV20_TCL_PRIMITIVE_3D_ALPHA_FUNC_REF 0x00000340
+# define NV20_TCL_PRIMITIVE_3D_BLEND_FUNC_SRC 0x00000344
+# define NV20_TCL_PRIMITIVE_3D_BLEND_FUNC_DST 0x00000348
+# define NV20_TCL_PRIMITIVE_3D_BLEND_COLOR 0x0000034c /* Parameters: a r g b */
+# define NV20_TCL_PRIMITIVE_3D_BLEND_EQUATION 0x00000350
+# define NV20_TCL_PRIMITIVE_3D_DEPTH_FUNC 0x00000354
+# define NV20_TCL_PRIMITIVE_3D_COLOR_MASK 0x00000358 /* Parameters: a r g b */
+# define NV20_TCL_PRIMITIVE_3D_DEPTH_WRITE_ENABLE 0x0000035c
+# define NV20_TCL_PRIMITIVE_3D_STENCIL_MASK 0x00000360
+# define NV20_TCL_PRIMITIVE_3D_STENCIL_FUNC_FUNC 0x00000364
+# define NV20_TCL_PRIMITIVE_3D_STENCIL_FUNC_REF 0x00000368
+# define NV20_TCL_PRIMITIVE_3D_STENCIL_FUNC_MASK 0x0000036c
+# define NV20_TCL_PRIMITIVE_3D_STENCIL_OP_FAIL 0x00000370
+# define NV20_TCL_PRIMITIVE_3D_STENCIL_OP_ZFAIL 0x00000374
+# define NV20_TCL_PRIMITIVE_3D_STENCIL_OP_ZPASS 0x00000378
+# define NV20_TCL_PRIMITIVE_3D_SHADE_MODEL 0x0000037c
+# define NV20_TCL_PRIMITIVE_3D_LINE_WIDTH 0x00000380
+# define NV20_TCL_PRIMITIVE_3D_POLYGON_OFFSET_FACTOR 0x00000384
+# define NV20_TCL_PRIMITIVE_3D_POLYGON_OFFSET_UNITS 0x00000388
+# define NV20_TCL_PRIMITIVE_3D_POLYGON_MODE_FRONT 0x0000038c
+# define NV20_TCL_PRIMITIVE_3D_POLYGON_MODE_BACK 0x00000390
+# define NV20_TCL_PRIMITIVE_3D_DEPTH_RANGE_NEAR 0x00000394
+# define NV20_TCL_PRIMITIVE_3D_DEPTH_RANGE_FAR 0x00000398
+# define NV20_TCL_PRIMITIVE_3D_CULL_FACE 0x0000039c
+# define NV20_TCL_PRIMITIVE_3D_FRONT_FACE 0x000003a0
+# define NV20_TCL_PRIMITIVE_3D_NORMALIZE_ENABLE 0x000003a4
+# define NV20_TCL_PRIMITIVE_3D_COLOR_MATERIAL_FRONT_R 0x000003a8
+# define NV20_TCL_PRIMITIVE_3D_COLOR_MATERIAL_FRONT_G 0x000003ac
+# define NV20_TCL_PRIMITIVE_3D_COLOR_MATERIAL_FRONT_B 0x000003b0
+# define NV20_TCL_PRIMITIVE_3D_COLOR_MATERIAL_FRONT_A 0x000003b4
+# define NV20_TCL_PRIMITIVE_3D_SEPARATE_SPECULAR_ENABLE 0x000003b8
+# define NV20_TCL_PRIMITIVE_3D_ENABLED_LIGHTS 0x000003bc /* Parameters: light 7 light 6 light 5 light 4 light 3 light 2 light 1 light 0 */
+# define NV20_TCL_PRIMITIVE_3D_CLIP_PLANE_ENABLE(d) (0x000003c0 + d * 0x0004)
+# define NV20_TCL_PRIMITIVE_3D_TX_MATRIX_ENABLE(d) (0x00000420 + d * 0x0004)
+# define NV20_TCL_PRIMITIVE_3D_POINT_SIZE 0x0000043c
+# define NV20_TCL_PRIMITIVE_3D_MODELVIEW_MATRIX( d) (0x00000480 + d * 0x0004)
+# define NV20_TCL_PRIMITIVE_3D_INVERSE_MODELVIEW_MATRIX( d) (0x00000580 + d * 0x0004)
+# define NV20_TCL_PRIMITIVE_3D_PROJECTION_MATRIX( d) (0x00000680 + d * 0x0004)
+# define NV20_TCL_PRIMITIVE_3D_TX_MATRIX(x,y) (0x000006c0 + y * 0x0010 + x * 0x0004)
+# define NV20_TCL_PRIMITIVE_3D_CLIP_PLANE_A(d) (0x00000840 + d * 0x0010)
+# define NV20_TCL_PRIMITIVE_3D_CLIP_PLANE_B(d) (0x00000844 + d * 0x0010)
+# define NV20_TCL_PRIMITIVE_3D_CLIP_PLANE_C(d) (0x00000848 + d * 0x0010)
+# define NV20_TCL_PRIMITIVE_3D_CLIP_PLANE_D(d) (0x0000084c + d * 0x0010)
+# define NV20_TCL_PRIMITIVE_3D_FOG_EQUATION_CONSTANT 0x000009c0
+# define NV20_TCL_PRIMITIVE_3D_FOG_EQUATION_LINEAR 0x000009c4
+# define NV20_TCL_PRIMITIVE_3D_FOG_EQUATION_QUADRATIC 0x000009c8
+# define NV20_TCL_PRIMITIVE_3D_FRONT_MATERIAL_SHININESS_A 0x000009e0
+# define NV20_TCL_PRIMITIVE_3D_FRONT_MATERIAL_SHININESS_B 0x000009e4
+# define NV20_TCL_PRIMITIVE_3D_FRONT_MATERIAL_SHININESS_C 0x000009e8
+# define NV20_TCL_PRIMITIVE_3D_FRONT_MATERIAL_SHININESS_D 0x000009ec
+# define NV20_TCL_PRIMITIVE_3D_FRONT_MATERIAL_SHININESS_E 0x000009f0
+# define NV20_TCL_PRIMITIVE_3D_FRONT_MATERIAL_SHININESS_F 0x000009f4
+# define NV20_TCL_PRIMITIVE_3D_POINT_SPRITE 0x00000a1c /* Parameters: coord_replace r_mode enable */
+# define NV20_TCL_PRIMITIVE_3D_VIEWPORT_OX 0x00000a20
+# define NV20_TCL_PRIMITIVE_3D_VIEWPORT_OY 0x00000a24
+# define NV20_TCL_PRIMITIVE_3D_VIEWPORT_DEPTH_AVG_S 0x00000a28
+# define NV20_TCL_PRIMITIVE_3D_VIEWPORT_UNKNOWN_A 0x00000a2c
+# define NV20_TCL_PRIMITIVE_3D_POINT_PARAMETER_A 0x00000a30
+# define NV20_TCL_PRIMITIVE_3D_POINT_PARAMETER_B 0x00000a34
+# define NV20_TCL_PRIMITIVE_3D_POINT_PARAMETER_C 0x00000a38
+# define NV20_TCL_PRIMITIVE_3D_POINT_PARAMETER_D 0x00000a3c
+# define NV20_TCL_PRIMITIVE_3D_POINT_PARAMETER_E 0x00000a40
+# define NV20_TCL_PRIMITIVE_3D_POINT_PARAMETER_F 0x00000a44
+# define NV20_TCL_PRIMITIVE_3D_POINT_PARAMETER_G 0x00000a48
+# define NV20_TCL_PRIMITIVE_3D_POINT_PARAMETER_H 0x00000a4c
+# define NV20_TCL_PRIMITIVE_3D_VIEWPORT_PX_DIV2 0x00000af0
+# define NV20_TCL_PRIMITIVE_3D_VIEWPORT_PY_DIV2 0x00000af4
+# define NV20_TCL_PRIMITIVE_3D_VIEWPORT_DEPTH_HALF_S 0x00000af8
+# define NV20_TCL_PRIMITIVE_3D_VIEWPORT_UNKNOWN_B 0x00000afc
+# define NV20_TCL_PRIMITIVE_3D_VP_UPLOAD_INST0 0x00000b00
+# define NV20_TCL_PRIMITIVE_3D_VP_UPLOAD_INST1 0x00000b04
+# define NV20_TCL_PRIMITIVE_3D_VP_UPLOAD_INST2 0x00000b08
+# define NV20_TCL_PRIMITIVE_3D_VP_UPLOAD_INST3 0x00000b0c
+# define NV20_TCL_PRIMITIVE_3D_VP_UPLOAD_CONST_X 0x00000b80
+# define NV20_TCL_PRIMITIVE_3D_VP_UPLOAD_CONST_Y 0x00000b84
+# define NV20_TCL_PRIMITIVE_3D_VP_UPLOAD_CONST_Z 0x00000b88
+# define NV20_TCL_PRIMITIVE_3D_VP_UPLOAD_CONST_W 0x00000b8c
+# define NV20_TCL_PRIMITIVE_3D_VP_UPLOAD_CONST_ID 0x00001ea4
+# define NV20_TCL_PRIMITIVE_3D_LIGHT_MODEL_FRONT_SIDE_PRODUCT_AMBIENT_PLUS_EMISSION_R 0x00000a10
+# define NV20_TCL_PRIMITIVE_3D_LIGHT_MODEL_FRONT_SIDE_PRODUCT_AMBIENT_PLUS_EMISSION_G 0x00000a14
+# define NV20_TCL_PRIMITIVE_3D_LIGHT_MODEL_FRONT_SIDE_PRODUCT_AMBIENT_PLUS_EMISSION_B 0x00000a18
+# define NV20_TCL_PRIMITIVE_3D_TX_OFFSET(d) (0x00001b00 + d * 0x0040)
+# define NV20_TCL_PRIMITIVE_3D_TX_FORMAT(d) (0x00001b04 + d * 0x0040) /* Parameters: log2(height) log2(width) lod format cube_map */
+# define NV20_TCL_PRIMITIVE_3D_TX_WRAP(d) (0x00001b08 + d * 0x0040) /* Parameters: wrap_s wrap_t wrap_r */
+# define NV20_TCL_PRIMITIVE_3D_TX_ENABLE(d) (0x00001b0c + d * 0x0040) /* Parameters: enable anisotropy */
+# define NV20_TCL_PRIMITIVE_3D_TX_NPOT_PITCH(d) (0x00001b10 + d * 0x0040) /* Parameters: pitch */
+# define NV20_TCL_PRIMITIVE_3D_TX_FILTER(d) (0x00001b14 + d * 0x0040) /* Parameters: mag_filter min_filter */
+# define NV20_TCL_PRIMITIVE_3D_TX_NPOT_SIZE(d) (0x00001b1c + d * 0x0040) /* Parameters: width height */
+# define NV20_TCL_PRIMITIVE_3D_TX_PALETTE_OFFSET(d) (0x00001b20 + d * 0x0040)
+# define NV20_TCL_PRIMITIVE_3D_RC_ENABLE 0x00001e60 /* Parameters: number of rc enabled */
+# define NV20_TCL_PRIMITIVE_3D_TX_SHADER_OP 0x00001e70 /* Parameters: op0 op1 op2 op3 */
+# define NV20_TCL_PRIMITIVE_3D_TX_SHADER_CULL_MODE 0x000017f8 /* Parameters: cull0 cull1 cull2 cull3 */
+# define NV20_TCL_PRIMITIVE_3D_TX_SHADER_PREVIOUS 0x00001e78 /* Parameters: prev2 prev3 */
+# define NV20_TCL_PRIMITIVE_3D_RC_COLOR0 0x00001e20 /* Parameters: a r g b */
+# define NV20_TCL_PRIMITIVE_3D_RC_COLOR1 0x00001e24 /* Parameters: a r g b */
+# define NV20_TCL_PRIMITIVE_3D_RC_FINAL0 0x00000288 /* Parameters: vara_mapping vara_component_usage vara_input varb_mapping varb_component_usage varb_input varc_mapping varc_component_usage varc_input vard_mapping vard_component_usage vard_input */
+# define NV20_TCL_PRIMITIVE_3D_RC_FINAL1 0x0000028c /* Parameters: vare_mapping vare_component_usage vare_input varf_mapping varf_component_usage varf_input varg_mapping varg_component_usage varg_input color_sum_clamp */
+# define NV20_TCL_PRIMITIVE_3D_RC_IN_ALPHA(d) (0x00000260 + d * 0x0004) /* Parameters: vara_mapping vara_component_usage vara_input varb_mapping varb_component_usage varb_input varc_mapping varc_component_usage varc_input vard_mapping vard_component_usage vard_input */
+# define NV20_TCL_PRIMITIVE_3D_RC_IN_RGB(d) (0x00000ac0 + d * 0x0004) /* Parameters: vara_mapping vara_component_usage vara_input varb_mapping varb_component_usage varb_input varc_mapping varc_component_usage varc_input vard_mapping vard_component_usage vard_input */
+# define NV20_TCL_PRIMITIVE_3D_RC_CONSTANT_COLOR0(d) (0x00000a60 + d * 0x0004) /* Parameters: a r g b */
+# define NV20_TCL_PRIMITIVE_3D_RC_CONSTANT_COLOR1(d) (0x00000a80 + d * 0x0004) /* Parameters: a r g b */
+# define NV20_TCL_PRIMITIVE_3D_RC_OUT_ALPHA(d) (0x00000aa0 + d * 0x0004) /* Parameters: scale bias mux_sum ab_dot_product cd_dot_product sum_output ab_output cd_output */
+# define NV20_TCL_PRIMITIVE_3D_RC_OUT_RGB(d) (0x00001e40 + d * 0x0004) /* Parameters: scale bias mux_sum ab_dot_product cd_dot_product sum_output ab_output cd_output */
+# define NV20_TCL_PRIMITIVE_3D_LIGHT_POSITION_X(d) (0x0000105c + d * 0x0080)
+# define NV20_TCL_PRIMITIVE_3D_LIGHT_POSITION_Y(d) (0x00001060 + d * 0x0080)
+# define NV20_TCL_PRIMITIVE_3D_LIGHT_POSITION_Z(d) (0x00001064 + d * 0x0080)
+# define NV20_TCL_PRIMITIVE_3D_LIGHT_HALF_VECTOR_X(d) (0x00001028 + d * 0x0080)
+# define NV20_TCL_PRIMITIVE_3D_LIGHT_HALF_VECTOR_Y(d) (0x0000102c + d * 0x0080)
+# define NV20_TCL_PRIMITIVE_3D_LIGHT_HALF_VECTOR_Z(d) (0x00001030 + d * 0x0080)
+# define NV20_TCL_PRIMITIVE_3D_LIGHT_DIRECTION_X(d) (0x00001034 + d * 0x0080)
+# define NV20_TCL_PRIMITIVE_3D_LIGHT_DIRECTION_Y(d) (0x00001038 + d * 0x0080)
+# define NV20_TCL_PRIMITIVE_3D_LIGHT_DIRECTION_Z(d) (0x0000103c + d * 0x0080)
+# define NV20_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_AMBIENT_R(d) (0x00001000 + d * 0x0080)
+# define NV20_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_AMBIENT_G(d) (0x00001004 + d * 0x0080)
+# define NV20_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_AMBIENT_B(d) (0x00001008 + d * 0x0080)
+# define NV20_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_DIFFUSE_R(d) (0x0000100c + d * 0x0080)
+# define NV20_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_DIFFUSE_G(d) (0x00001010 + d * 0x0080)
+# define NV20_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_DIFFUSE_B(d) (0x00001014 + d * 0x0080)
+# define NV20_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_SPECULAR_R(d) (0x00001018 + d * 0x0080)
+# define NV20_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_SPECULAR_G(d) (0x0000101c + d * 0x0080)
+# define NV20_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_SPECULAR_B(d) (0x00001020 + d * 0x0080)
+# define NV20_TCL_PRIMITIVE_3D_LIGHT_BACK_SIDE_PRODUCT_AMBIENT(d) (0x00000c00 + d * 0x0040)
+# define NV20_TCL_PRIMITIVE_3D_LIGHT_BACK_SIDE_PRODUCT_DIFFUSE(d) (0x00000c0c + d * 0x0040)
+# define NV20_TCL_PRIMITIVE_3D_LIGHT_BACK_SIDE_PRODUCT_SPECULAR(d) (0x00000c18 + d * 0x0040)
+# define NV20_TCL_PRIMITIVE_3D_LIGHT_CONSTANT_ATTENUATION(d) (0x00001068 + d * 0x0080)
+# define NV20_TCL_PRIMITIVE_3D_LIGHT_LINEAR_ATTENUATION(d) (0x0000106c + d * 0x0080)
+# define NV20_TCL_PRIMITIVE_3D_LIGHT_QUADRATIC_ATTENUATION(d) (0x00001070 + d * 0x0080)
+# define NV20_TCL_PRIMITIVE_3D_LIGHT_SPOT_CUTOFF_A(d) (0x00001040 + d * 0x0080)
+# define NV20_TCL_PRIMITIVE_3D_LIGHT_SPOT_EXPONENT(d) (0x00001044 + d * 0x0080)
+# define NV20_TCL_PRIMITIVE_3D_LIGHT_SPOT_CUTOFF_B(d) (0x00001048 + d * 0x0080)
+# define NV20_TCL_PRIMITIVE_3D_LIGHT_SPOT_DIR_X(d) (0x0000104c + d * 0x0080)
+# define NV20_TCL_PRIMITIVE_3D_LIGHT_SPOT_DIR_Y(d) (0x00001050 + d * 0x0080)
+# define NV20_TCL_PRIMITIVE_3D_LIGHT_SPOT_DIR_Z(d) (0x00001054 + d * 0x0080)
+# define NV20_TCL_PRIMITIVE_3D_LIGHT_SPOT_CUTOFF_C(d) (0x00001058 + d * 0x0080)
+# define NV20_TCL_PRIMITIVE_3D_BACK_MATERIAL_SHININESS_A 0x00001e28
+# define NV20_TCL_PRIMITIVE_3D_BACK_MATERIAL_SHININESS_B 0x00001e2c
+# define NV20_TCL_PRIMITIVE_3D_BACK_MATERIAL_SHININESS_C 0x00001e30
+# define NV20_TCL_PRIMITIVE_3D_BACK_MATERIAL_SHININESS_D 0x00001e34
+# define NV20_TCL_PRIMITIVE_3D_BACK_MATERIAL_SHININESS_E 0x00001e38
+# define NV20_TCL_PRIMITIVE_3D_BACK_MATERIAL_SHININESS_F 0x00001e3c
+# define NV20_TCL_PRIMITIVE_3D_POLYGON_STIPPLE_ENABLE 0x0000147c
+# define NV20_TCL_PRIMITIVE_3D_POLYGON_STIPPLE_PATTERN(d) (0x00001480 + d * 0x0004)
+# define NV20_TCL_PRIMITIVE_3D_VERTEX_POS_3F_X 0x00001500
+# define NV20_TCL_PRIMITIVE_3D_VERTEX_POS_3F_Y 0x00001504
+# define NV20_TCL_PRIMITIVE_3D_VERTEX_POS_3F_Z 0x00001508
+# define NV20_TCL_PRIMITIVE_3D_VERTEX_POS_4F_X 0x00001518
+# define NV20_TCL_PRIMITIVE_3D_VERTEX_POS_4F_Y 0x0000151c
+# define NV20_TCL_PRIMITIVE_3D_VERTEX_POS_4F_Z 0x00001520
+# define NV20_TCL_PRIMITIVE_3D_VERTEX_POS_4F_W 0x00001524
+# define NV20_TCL_PRIMITIVE_3D_VERTEX_POS_4I_XY 0x00001528 /* Parameters: y x */
+# define NV20_TCL_PRIMITIVE_3D_VERTEX_POS_4I_ZW 0x0000152c /* Parameters: w z */
+# define NV20_TCL_PRIMITIVE_3D_VERTEX_NOR_3F_X 0x00001530
+# define NV20_TCL_PRIMITIVE_3D_VERTEX_NOR_3F_Y 0x00001534
+# define NV20_TCL_PRIMITIVE_3D_VERTEX_NOR_3F_Z 0x00001538
+# define NV20_TCL_PRIMITIVE_3D_VERTEX_NOR_3I_XY 0x00001540 /* Parameters: y x */
+# define NV20_TCL_PRIMITIVE_3D_VERTEX_NOR_3I_Z 0x00001544 /* Parameters: z */
+# define NV20_TCL_PRIMITIVE_3D_VERTEX_COL_4F_R 0x00001550
+# define NV20_TCL_PRIMITIVE_3D_VERTEX_COL_4F_G 0x00001554
+# define NV20_TCL_PRIMITIVE_3D_VERTEX_COL_4F_B 0x00001558
+# define NV20_TCL_PRIMITIVE_3D_VERTEX_COL_4F_A 0x0000155c
+# define NV20_TCL_PRIMITIVE_3D_VERTEX_COL_3F_R 0x00001560
+# define NV20_TCL_PRIMITIVE_3D_VERTEX_COL_3F_G 0x00001564
+# define NV20_TCL_PRIMITIVE_3D_VERTEX_COL_3F_B 0x00001568
+# define NV20_TCL_PRIMITIVE_3D_VERTEX_COL_4I 0x0000156c /* Parameters: a b g r */
+# define NV20_TCL_PRIMITIVE_3D_VERTEX_COL2_3F_R 0x00001580
+# define NV20_TCL_PRIMITIVE_3D_VERTEX_COL2_3F_G 0x00001584
+# define NV20_TCL_PRIMITIVE_3D_VERTEX_COL2_3F_B 0x00001588
+# define NV20_TCL_PRIMITIVE_3D_VERTEX_COL2_3I 0x0000158c /* Parameters: a b g r */
+# define NV20_TCL_PRIMITIVE_3D_VERTEX_TX0_2F_S 0x00001590
+# define NV20_TCL_PRIMITIVE_3D_VERTEX_TX0_2F_T 0x00001594
+# define NV20_TCL_PRIMITIVE_3D_VERTEX_TX0_2I 0x00001598 /* Parameters: t s */
+# define NV20_TCL_PRIMITIVE_3D_VERTEX_TX0_4F_S 0x000015a0
+# define NV20_TCL_PRIMITIVE_3D_VERTEX_TX0_4F_T 0x000015a4
+# define NV20_TCL_PRIMITIVE_3D_VERTEX_TX0_4F_R 0x000015a8
+# define NV20_TCL_PRIMITIVE_3D_VERTEX_TX0_4F_Q 0x000015ac
+# define NV20_TCL_PRIMITIVE_3D_VERTEX_TX0_4I_ST 0x000015b0 /* Parameters: t s */
+# define NV20_TCL_PRIMITIVE_3D_VERTEX_TX0_4I_RQ 0x000015b4 /* Parameters: q r */
+# define NV20_TCL_PRIMITIVE_3D_VERTEX_TX1_2F_S 0x000015b8
+# define NV20_TCL_PRIMITIVE_3D_VERTEX_TX1_2F_T 0x000015bc
+# define NV20_TCL_PRIMITIVE_3D_VERTEX_TX1_2I 0x000015c0 /* Parameters: t s */
+# define NV20_TCL_PRIMITIVE_3D_VERTEX_TX1_4F_S 0x000015c8
+# define NV20_TCL_PRIMITIVE_3D_VERTEX_TX1_4F_T 0x000015cc
+# define NV20_TCL_PRIMITIVE_3D_VERTEX_TX1_4F_R 0x000015d0
+# define NV20_TCL_PRIMITIVE_3D_VERTEX_TX1_4F_Q 0x000015d4
+# define NV20_TCL_PRIMITIVE_3D_VERTEX_TX1_4I_ST 0x000015d8 /* Parameters: t s */
+# define NV20_TCL_PRIMITIVE_3D_VERTEX_TX1_4I_RQ 0x000015dc /* Parameters: q r */
+# define NV20_TCL_PRIMITIVE_3D_VERTEX_TX2_2F_S 0x000015e0
+# define NV20_TCL_PRIMITIVE_3D_VERTEX_TX2_2F_T 0x000015e4
+# define NV20_TCL_PRIMITIVE_3D_VERTEX_TX2_2I 0x000015e8 /* Parameters: t s */
+# define NV20_TCL_PRIMITIVE_3D_VERTEX_TX2_4F_S 0x000015f0
+# define NV20_TCL_PRIMITIVE_3D_VERTEX_TX2_4F_T 0x000015f4
+# define NV20_TCL_PRIMITIVE_3D_VERTEX_TX2_4F_R 0x000015f8
+# define NV20_TCL_PRIMITIVE_3D_VERTEX_TX2_4F_Q 0x000015fc
+# define NV20_TCL_PRIMITIVE_3D_VERTEX_TX2_4I_ST 0x00001600 /* Parameters: t s */
+# define NV20_TCL_PRIMITIVE_3D_VERTEX_TX2_4I_RQ 0x00001604 /* Parameters: q r */
+# define NV20_TCL_PRIMITIVE_3D_VERTEX_TX3_2F_S 0x00001608
+# define NV20_TCL_PRIMITIVE_3D_VERTEX_TX3_2F_T 0x0000160c
+# define NV20_TCL_PRIMITIVE_3D_VERTEX_TX3_2I 0x00001610 /* Parameters: t s */
+# define NV20_TCL_PRIMITIVE_3D_VERTEX_TX3_4F_S 0x00001620
+# define NV20_TCL_PRIMITIVE_3D_VERTEX_TX3_4F_T 0x00001624
+# define NV20_TCL_PRIMITIVE_3D_VERTEX_TX3_4F_R 0x00001628
+# define NV20_TCL_PRIMITIVE_3D_VERTEX_TX3_4F_Q 0x0000162c
+# define NV20_TCL_PRIMITIVE_3D_VERTEX_TX3_4I_ST 0x00001630 /* Parameters: t s */
+# define NV20_TCL_PRIMITIVE_3D_VERTEX_TX3_4I_RQ 0x00001634 /* Parameters: q r */
+# define NV20_TCL_PRIMITIVE_3D_VERTEX_FOG_1F 0x00001698
+# define NV20_TCL_PRIMITIVE_3D_EDGE_FLAG 0x000016bc
+# define NV20_TCL_PRIMITIVE_3D_VB_POINTER_ATTR0_POS 0x00001720 /* Parameters: enabled? offset */
+# define NV20_TCL_PRIMITIVE_3D_VB_POINTER_ATTR1_WGH 0x00001724 /* Parameters: enabled? offset */
+# define NV20_TCL_PRIMITIVE_3D_VB_POINTER_ATTR2_NOR 0x00001728 /* Parameters: enabled? offset */
+# define NV20_TCL_PRIMITIVE_3D_VB_POINTER_ATTR3_COL 0x0000172c /* Parameters: enabled? offset */
+# define NV20_TCL_PRIMITIVE_3D_VB_POINTER_ATTR4_COL2 0x00001730 /* Parameters: enabled? offset */
+# define NV20_TCL_PRIMITIVE_3D_VB_POINTER_ATTR5_FOG 0x00001734 /* Parameters: enabled? offset */
+# define NV20_TCL_PRIMITIVE_3D_VB_POINTER_ATTR6 0x00001738 /* Parameters: enabled? offset */
+# define NV20_TCL_PRIMITIVE_3D_VB_POINTER_ATTR7 0x0000173c /* Parameters: enabled? offset */
+# define NV20_TCL_PRIMITIVE_3D_VB_POINTER_ATTR8_TX0 0x00001740 /* Parameters: enabled? offset */
+# define NV20_TCL_PRIMITIVE_3D_VB_POINTER_ATTR9_TX1 0x00001744 /* Parameters: enabled? offset */
+# define NV20_TCL_PRIMITIVE_3D_VB_POINTER_ATTR10_TX2 0x00001748 /* Parameters: enabled? offset */
+# define NV20_TCL_PRIMITIVE_3D_VB_POINTER_ATTR11_TX3 0x0000174c /* Parameters: enabled? offset */
+# define NV20_TCL_PRIMITIVE_3D_VB_POINTER_ATTR12_TX4 0x00001750 /* Parameters: enabled? offset */
+# define NV20_TCL_PRIMITIVE_3D_VB_POINTER_ATTR13_TX5 0x00001754 /* Parameters: enabled? offset */
+# define NV20_TCL_PRIMITIVE_3D_VB_POINTER_ATTR14_TX6 0x00001758 /* Parameters: enabled? offset */
+# define NV20_TCL_PRIMITIVE_3D_VB_POINTER_ATTR15_TX7 0x0000175c /* Parameters: enabled? offset */
+# define NV20_TCL_PRIMITIVE_3D_VERTEX_ATTR( d) (0x00001760 + d * 0x0004)
+# define NV20_TCL_PRIMITIVE_3D_VERTEX_ATTR0_POS 0x00001760 /* Parameters: stride fields type */
+# define NV20_TCL_PRIMITIVE_3D_VERTEX_ATTR1_WGH 0x00001764 /* Parameters: stride fields type */
+# define NV20_TCL_PRIMITIVE_3D_VERTEX_ATTR2_NOR 0x00001768 /* Parameters: stride fields type */
+# define NV20_TCL_PRIMITIVE_3D_VERTEX_ATTR3_COL 0x0000176c /* Parameters: stride fields type */
+# define NV20_TCL_PRIMITIVE_3D_VERTEX_ATTR4_COL2 0x00001770 /* Parameters: stride fields type */
+# define NV20_TCL_PRIMITIVE_3D_VERTEX_ATTR5_FOG 0x00001774 /* Parameters: stride fields type */
+# define NV20_TCL_PRIMITIVE_3D_VERTEX_ATTR6 0x00001778 /* Parameters: stride fields type */
+# define NV20_TCL_PRIMITIVE_3D_VERTEX_ATTR7 0x0000177c /* Parameters: stride fields type */
+# define NV20_TCL_PRIMITIVE_3D_VERTEX_ATTR8_TX0 0x00001780 /* Parameters: stride fields type */
+# define NV20_TCL_PRIMITIVE_3D_VERTEX_ATTR9_TX1 0x00001784 /* Parameters: stride fields type */
+# define NV20_TCL_PRIMITIVE_3D_VERTEX_ATTR10_TX2 0x00001788 /* Parameters: stride fields type */
+# define NV20_TCL_PRIMITIVE_3D_VERTEX_ATTR11_TX3 0x0000178c /* Parameters: stride fields type */
+# define NV20_TCL_PRIMITIVE_3D_VERTEX_ATTR12_TX4 0x00001790 /* Parameters: stride fields type */
+# define NV20_TCL_PRIMITIVE_3D_VERTEX_ATTR13_TX5 0x00001794 /* Parameters: stride fields type */
+# define NV20_TCL_PRIMITIVE_3D_VERTEX_ATTR14_TX6 0x00001798 /* Parameters: stride fields type */
+# define NV20_TCL_PRIMITIVE_3D_VERTEX_ATTR15_TX7 0x0000179c /* Parameters: stride fields type */
+# define NV20_TCL_PRIMITIVE_3D_LIGHT_MODEL_BACK_SIDE_PRODUCT_AMBIENT_PLUS_EMISSION_R 0x000017a0
+# define NV20_TCL_PRIMITIVE_3D_LIGHT_MODEL_BACK_SIDE_PRODUCT_AMBIENT_PLUS_EMISSION_G 0x000017a4
+# define NV20_TCL_PRIMITIVE_3D_LIGHT_MODEL_BACK_SIDE_PRODUCT_AMBIENT_PLUS_EMISSION_B 0x000017a8
+# define NV20_TCL_PRIMITIVE_3D_COLOR_MATERIAL_BACK_A 0x000017ac
+# define NV20_TCL_PRIMITIVE_3D_COLOR_MATERIAL_BACK_R 0x000017b0
+# define NV20_TCL_PRIMITIVE_3D_COLOR_MATERIAL_BACK_G 0x000017b4
+# define NV20_TCL_PRIMITIVE_3D_COLOR_MATERIAL_BACK_B 0x000017b8
+# define NV20_TCL_PRIMITIVE_3D_COLOR_LOGIC_OP_ENABLE 0x000017bc
+# define NV20_TCL_PRIMITIVE_3D_COLOR_LOGIC_OP_OP 0x000017c0
+# define NV20_TCL_PRIMITIVE_3D_LIGHT_MODEL_TWO_SIDE_ENABLE 0x000017c4
+# define NV20_TCL_PRIMITIVE_3D_BEGIN_END 0x000017fc
+# define NV20_TCL_PRIMITIVE_3D_SCISSOR_X2_X1 0x00001c30 /* Parameters: x2 x1 */
+# define NV20_TCL_PRIMITIVE_3D_SCISSOR_Y2_Y1 0x00001c50 /* Parameters: y2 y1 */
+# define NV20_TCL_PRIMITIVE_3D_CLEAR_VALUE_DEPTH 0x00001d8c
+# define NV20_TCL_PRIMITIVE_3D_CLEAR_VALUE_ARGB 0x00001d90
+# define NV20_TCL_PRIMITIVE_3D_CLEAR_WHICH_BUFFERS 0x00001d94 /* Parameters: clear color a clear color b clear color g clear color r clear depth clear stencil */
+# define NV20_TCL_PRIMITIVE_3D_INDEX_DATA 0x00001800 /* Parameters: index1 index0 */
+# define NV20_TCL_PRIMITIVE_3D_VB_VERTEX_BATCH 0x00001810 /* Parameters: count_vertices offset_vertices */
+# define NV20_TCL_PRIMITIVE_3D_VERTEX_DATA 0x00001818
+# define NV20_TCL_PRIMITIVE_3D_VIEWPORT_ORIGIN_X 0x00001f00
+# define NV20_TCL_PRIMITIVE_3D_VIEWPORT_ORIGIN_Y 0x00001f04
+# define NV20_TCL_PRIMITIVE_3D_VIEWPORT_ORIGIN_Z 0x00001f08
+# define NV20_TCL_PRIMITIVE_3D_VIEWPORT_ORIGIN_W 0x00001f0c
+
+/******************************************
+Object NV30_TCL_PRIMITIVE_3D used on: NV30 NV40 G70
+*/
+#define NV30_TCL_PRIMITIVE_3D 0x00000097
+# define NV30_TCL_PRIMITIVE_3D_SET_OBJECT0 0x00000180
+# define NV30_TCL_PRIMITIVE_3D_SET_OBJECT1 0x00000184
+# define NV30_TCL_PRIMITIVE_3D_SET_OBJECT2 0x00000188
+# define NV30_TCL_PRIMITIVE_3D_SET_OBJECT3 0x0000018c
+# define NV30_TCL_PRIMITIVE_3D_SET_OBJECT4 0x00000194
+# define NV30_TCL_PRIMITIVE_3D_SET_OBJECT5 0x00000198
+# define NV30_TCL_PRIMITIVE_3D_SET_OBJECT6 0x000001a4
+# define NV30_TCL_PRIMITIVE_3D_SET_OBJECT7 0x000001a8
+# define NV30_TCL_PRIMITIVE_3D_SET_OBJECT8 0x000001ac
+# define NV30_TCL_PRIMITIVE_3D_SET_OBJECT9 0x000001b4
+# define NV30_TCL_PRIMITIVE_3D_SET_OBJECT10 0x000001b8
+# define NV30_TCL_PRIMITIVE_3D_SET_VB_SRC0_OBJECT 0x0000019c
+# define NV30_TCL_PRIMITIVE_3D_SET_VB_SRC1_OBJECT 0x000001a0
+# define NV30_TCL_PRIMITIVE_3D_BUFFER0_PITCH 0x0000020c /* Parameters: depth/stencil buffer pitch color0 buffer pitch */
+# define NV30_TCL_PRIMITIVE_3D_COLOR0_OFFSET 0x00000210
+# define NV30_TCL_PRIMITIVE_3D_DEPTH_OFFSET 0x00000214
+# define NV30_TCL_PRIMITIVE_3D_COLOR1_OFFSET 0x00000218
+# define NV30_TCL_PRIMITIVE_3D_BUFFER1_PITCH 0x0000021c /* Parameters: color1 buffer pitch */
+# define NV30_TCL_PRIMITIVE_3D_LMA_DEPTH_BUFFER_PITCH 0x0000022c /* Parameters: pitch */
+# define NV30_TCL_PRIMITIVE_3D_LMA_DEPTH_BUFFER_OFFSET 0x00000230
+# define NV30_TCL_PRIMITIVE_3D_TX_MATRIX_ENABLE(d) (0x00000240 + d * 0x0004)
+# define NV30_TCL_PRIMITIVE_3D_BUFFER2_PITCH 0x00000280
+# define NV30_TCL_PRIMITIVE_3D_BUFFER3_PITCH 0x00000284
+# define NV30_TCL_PRIMITIVE_3D_BUFFER2_OFFSET 0x00000288
+# define NV30_TCL_PRIMITIVE_3D_BUFFER3_OFFSET 0x0000028c
+# define NV30_TCL_PRIMITIVE_3D_DITHER_ENABLE 0x00000300
+# define NV30_TCL_PRIMITIVE_3D_ALPHA_FUNC_ENABLE 0x00000304
+# define NV30_TCL_PRIMITIVE_3D_ALPHA_FUNC_FUNC 0x00000308
+# define NV30_TCL_PRIMITIVE_3D_ALPHA_FUNC_REF 0x0000030c
+# define NV30_TCL_PRIMITIVE_3D_BLEND_FUNC_ENABLE 0x00000310
+# define NV30_TCL_PRIMITIVE_3D_BLEND_FUNC_SRC 0x00000314
+# define NV30_TCL_PRIMITIVE_3D_BLEND_FUNC_DST 0x00000318
+# define NV30_TCL_PRIMITIVE_3D_BLEND_COLOR 0x0000031c /* Parameters: a r g b */
+# define NV30_TCL_PRIMITIVE_3D_BLEND_EQUATION 0x00000320
+# define NV30_TCL_PRIMITIVE_3D_COLOR_MASK 0x00000324 /* Parameters: a r g b */
+# define NV30_TCL_PRIMITIVE_3D_STENCIL_BACK_ENABLE 0x00000328
+# define NV30_TCL_PRIMITIVE_3D_STENCIL_BACK_MASK 0x0000032c
+# define NV30_TCL_PRIMITIVE_3D_STENCIL_BACK_FUNC_FUNC 0x00000330
+# define NV30_TCL_PRIMITIVE_3D_STENCIL_BACK_FUNC_REF 0x00000334
+# define NV30_TCL_PRIMITIVE_3D_STENCIL_BACK_FUNC_MASK 0x00000338
+# define NV30_TCL_PRIMITIVE_3D_STENCIL_BACK_OP_FAIL 0x0000033c
+# define NV30_TCL_PRIMITIVE_3D_STENCIL_BACK_OP_ZFAIL 0x00000340
+# define NV30_TCL_PRIMITIVE_3D_STENCIL_BACK_OP_ZPASS 0x00000344
+# define NV30_TCL_PRIMITIVE_3D_STENCIL_FRONT_ENABLE 0x00000348
+# define NV30_TCL_PRIMITIVE_3D_STENCIL_FRONT_MASK 0x0000034c
+# define NV30_TCL_PRIMITIVE_3D_STENCIL_FRONT_FUNC_FUNC 0x00000350
+# define NV30_TCL_PRIMITIVE_3D_STENCIL_FRONT_FUNC_REF 0x00000354
+# define NV30_TCL_PRIMITIVE_3D_STENCIL_FRONT_FUNC_MASK 0x00000358
+# define NV30_TCL_PRIMITIVE_3D_STENCIL_FRONT_OP_FAIL 0x0000035c
+# define NV30_TCL_PRIMITIVE_3D_STENCIL_FRONT_OP_ZFAIL 0x00000360
+# define NV30_TCL_PRIMITIVE_3D_STENCIL_FRONT_OP_ZPASS 0x00000364
+# define NV30_TCL_PRIMITIVE_3D_SHADE_MODEL 0x00000368
+# define NV30_TCL_PRIMITIVE_3D_FOG_ENABLE 0x0000036c
+# define NV30_TCL_PRIMITIVE_3D_FOG_COLOR 0x00000370
+# define NV40_TCL_PRIMITIVE_3D_COLOR_MASK_BUFFER123 0x00000370 /* Parameters: buffer3 b buffer3 g buffer3 r buffer3 a buffer2 b buffer2 g buffer2 r buffer2 a buffer1 b buffer1 g buffer1 r buffer1 a */
+# define NV30_TCL_PRIMITIVE_3D_NORMALIZE_ENABLE 0x0000037c
+# define NV30_TCL_PRIMITIVE_3D_DEPTH_RANGE_NEAR 0x00000394
+# define NV30_TCL_PRIMITIVE_3D_DEPTH_RANGE_FAR 0x00000398
+# define NV30_TCL_PRIMITIVE_3D_COLOR_MATERIAL_FRONT_R 0x000003a0
+# define NV30_TCL_PRIMITIVE_3D_COLOR_MATERIAL_FRONT_G 0x000003a4
+# define NV30_TCL_PRIMITIVE_3D_COLOR_MATERIAL_FRONT_B 0x000003a8
+# define NV30_TCL_PRIMITIVE_3D_COLOR_MATERIAL_FRONT_A 0x000003b4
+# define NV30_TCL_PRIMITIVE_3D_LINE_WIDTH_SMOOTH 0x000003b8
+# define NV30_TCL_PRIMITIVE_3D_LINE_SMOOTH_ENABLE 0x000003bc
+# define NV30_TCL_PRIMITIVE_3D_CLIP_PLANE_ENABLE(d) (0x00000400 + d * 0x0004)
+# define NV30_TCL_PRIMITIVE_3D_MODELVIEW_MATRIX( d) (0x00000480 + d * 0x0004)
+# define NV30_TCL_PRIMITIVE_3D_INVERSE_MODELVIEW_MATRIX( d) (0x00000580 + d * 0x0004)
+# define NV30_TCL_PRIMITIVE_3D_PROJECTION_MATRIX( d) (0x00000680 + d * 0x0004)
+# define NV30_TCL_PRIMITIVE_3D_TX_MATRIX(x,y) (0x000006c0 + y * 0x0010 + x * 0x0004)
+# define NV30_TCL_PRIMITIVE_3D_FP_ACTIVE_PROGRAM 0x000008e4
+# define NV30_TCL_PRIMITIVE_3D_FOG_COORD_DIST 0x000008c8
+# define NV30_TCL_PRIMITIVE_3D_FOG_MODE 0x000008cc
+# define NV30_TCL_PRIMITIVE_3D_FOG_EQUATION_CONSTANT 0x000008d0
+# define NV30_TCL_PRIMITIVE_3D_FOG_EQUATION_LINEAR 0x000008d4
+# define NV30_TCL_PRIMITIVE_3D_FOG_EQUATION_QUADRATIC 0x000008d8
+# define NV30_TCL_PRIMITIVE_3D_RC_COLOR0 0x000008ec /* Parameters: a r g b */
+# define NV30_TCL_PRIMITIVE_3D_RC_COLOR1 0x000008f0 /* Parameters: a r g b */
+# define NV30_TCL_PRIMITIVE_3D_RC_FINAL0 0x000008f4 /* Parameters: vara_mapping vara_component_usage vara_input varb_mapping varb_component_usage varb_input varc_mapping varc_component_usage varc_input vard_mapping vard_component_usage vard_input */
+# define NV30_TCL_PRIMITIVE_3D_RC_FINAL1 0x000008f8 /* Parameters: vare_mapping vare_component_usage vare_input varf_mapping varf_component_usage varf_input varg_mapping varg_component_usage varg_input color_sum_clamp */
+# define NV30_TCL_PRIMITIVE_3D_RC_ENABLE 0x000008fc /* Parameters: number of rc enabled */
+# define NV30_TCL_PRIMITIVE_3D_RC_IN_ALPHA(d) (0x00000900 + d * 0x0020) /* Parameters: vara_mapping vara_component_usage vara_input varb_mapping varb_component_usage varb_input varc_mapping varc_component_usage varc_input vard_mapping vard_component_usage vard_input */
+# define NV30_TCL_PRIMITIVE_3D_RC_IN_RGB(d) (0x00000904 + d * 0x0020) /* Parameters: vara_mapping vara_component_usage vara_input varb_mapping varb_component_usage varb_input varc_mapping varc_component_usage varc_input vard_mapping vard_component_usage vard_input */
+# define NV30_TCL_PRIMITIVE_3D_RC_CONSTANT_COLOR0(d) (0x00000908 + d * 0x0020) /* Parameters: a r g b */
+# define NV30_TCL_PRIMITIVE_3D_RC_CONSTANT_COLOR1(d) (0x0000090c + d * 0x0020) /* Parameters: a r g b */
+# define NV30_TCL_PRIMITIVE_3D_RC_OUT_ALPHA(d) (0x00000910 + d * 0x0020) /* Parameters: scale bias mux_sum ab_dot_product cd_dot_product sum_output ab_output cd_output */
+# define NV30_TCL_PRIMITIVE_3D_RC_OUT_RGB(d) (0x00000914 + d * 0x0020) /* Parameters: scale bias mux_sum ab_dot_product cd_dot_product sum_output ab_output cd_output */
+# define NV30_TCL_PRIMITIVE_3D_VIEWPORT_COLOR_BUFFER_DIM0 0x00000200 /* Parameters: width x_offset */
+# define NV30_TCL_PRIMITIVE_3D_VIEWPORT_COLOR_BUFFER_DIM1 0x00000204 /* Parameters: height y_offset */
+# define NV30_TCL_PRIMITIVE_3D_VIEWPORT_COLOR_BUFFER_OFS0 0x000002c0 /* Parameters: width x_offset */
+# define NV30_TCL_PRIMITIVE_3D_VIEWPORT_COLOR_BUFFER_OFS1 0x000002c4 /* Parameters: height y_offset */
+# define NV30_TCL_PRIMITIVE_3D_VIEWPORT_DIMS_0 0x00000a00 /* Parameters: width x_offset */
+# define NV30_TCL_PRIMITIVE_3D_VIEWPORT_DIMS_1 0x00000a04 /* Parameters: height y_offset */
+# define NV30_TCL_PRIMITIVE_3D_LIGHT_MODEL_FRONT_SIDE_PRODUCT_AMBIENT_PLUS_EMISSION_R 0x00000a10
+# define NV30_TCL_PRIMITIVE_3D_LIGHT_MODEL_FRONT_SIDE_PRODUCT_AMBIENT_PLUS_EMISSION_G 0x00000a14
+# define NV30_TCL_PRIMITIVE_3D_LIGHT_MODEL_FRONT_SIDE_PRODUCT_AMBIENT_PLUS_EMISSION_B 0x00000a18
+# define NV30_TCL_PRIMITIVE_3D_SCISSOR_WIDTH_XPOS 0x000008c0 /* Parameters: width x_offset */
+# define NV30_TCL_PRIMITIVE_3D_SCISSOR_HEIGHT_YPOS 0x000008c4 /* Parameters: height y_offset */
+# define NV30_TCL_PRIMITIVE_3D_POINT_SPRITE 0x00001ee8 /* Parameters: coord_replace r_mode enable */
+# define NV30_TCL_PRIMITIVE_3D_POINT_SIZE 0x00001ee0
+# define NV30_TCL_PRIMITIVE_3D_POINT_PARAMETER_A 0x00001ec0
+# define NV30_TCL_PRIMITIVE_3D_POINT_PARAMETER_B 0x00001ec4
+# define NV30_TCL_PRIMITIVE_3D_POINT_PARAMETER_C 0x00001ec8
+# define NV30_TCL_PRIMITIVE_3D_POINT_PARAMETER_D 0x00001ecc
+# define NV30_TCL_PRIMITIVE_3D_POINT_PARAMETER_E 0x00001ed0
+# define NV30_TCL_PRIMITIVE_3D_POINT_PARAMETER_F 0x00001ed4
+# define NV30_TCL_PRIMITIVE_3D_POINT_PARAMETER_G 0x00001ed8
+# define NV30_TCL_PRIMITIVE_3D_POINT_PARAMETER_H 0x00001edc
+# define NV30_TCL_PRIMITIVE_3D_POINT_PARAMETERS_ENABLE 0x00001ee4
+# define NV30_TCL_PRIMITIVE_3D_VIEWPORT_XFRM_OX 0x00000a20
+# define NV30_TCL_PRIMITIVE_3D_VIEWPORT_XFRM_OY 0x00000a24
+# define NV30_TCL_PRIMITIVE_3D_VIEWPORT_XFRM_NPF_DIV2 0x00000a28
+# define NV30_TCL_PRIMITIVE_3D_VIEWPORT_XFRM_UNK0_0x0 0x00000a2c
+# define NV30_TCL_PRIMITIVE_3D_VIEWPORT_XFRM_PX_DIV2 0x00000a30
+# define NV30_TCL_PRIMITIVE_3D_VIEWPORT_XFRM_PY_DIV2 0x00000a34
+# define NV30_TCL_PRIMITIVE_3D_VIEWPORT_XFRM_FMN_DIV2 0x00000a38
+# define NV30_TCL_PRIMITIVE_3D_VIEWPORT_XFRM_UNK1_0x0 0x00000a3c
+# define NV30_TCL_PRIMITIVE_3D_POLYGON_OFFSET_FILL_ENABLE 0x00000a60
+# define NV30_TCL_PRIMITIVE_3D_POLYGON_OFFSET_LINE_ENABLE 0x00000a64
+# define NV30_TCL_PRIMITIVE_3D_POLYGON_OFFSET_POINT_ENABLE 0x00000a68
+# define NV30_TCL_PRIMITIVE_3D_DEPTH_FUNC 0x00000a6c
+# define NV30_TCL_PRIMITIVE_3D_DEPTH_WRITE_ENABLE 0x00000a70
+# define NV30_TCL_PRIMITIVE_3D_DEPTH_TEST_ENABLE 0x00000a74
+# define NV30_TCL_PRIMITIVE_3D_POLYGON_OFFSET_FACTOR 0x00000a78
+# define NV30_TCL_PRIMITIVE_3D_POLYGON_OFFSET_UNITS 0x00000a7c
+# define NV30_TCL_PRIMITIVE_3D_VP_UPLOAD_INST0 0x00000b80
+# define NV30_TCL_PRIMITIVE_3D_VP_UPLOAD_INST1 0x00000b84
+# define NV30_TCL_PRIMITIVE_3D_VP_UPLOAD_INST2 0x00000b88
+# define NV30_TCL_PRIMITIVE_3D_VP_UPLOAD_INST3 0x00000b8c
+# define NV30_TCL_PRIMITIVE_3D_COLOR_MATERIAL_BACK_R 0x000017b0
+# define NV30_TCL_PRIMITIVE_3D_COLOR_MATERIAL_BACK_G 0x000017b4
+# define NV30_TCL_PRIMITIVE_3D_COLOR_MATERIAL_BACK_B 0x000017b8
+# define NV30_TCL_PRIMITIVE_3D_COLOR_MATERIAL_BACK_A 0x000017c0
+# define NV30_TCL_PRIMITIVE_3D_OCC_QUERY_OR_COLOR_BUFF_ENABLE 0x000017c8
+# define NV30_TCL_PRIMITIVE_3D_STORE_RESULT 0x00001800
+# define NV30_TCL_PRIMITIVE_3D_CLIP_PLANE_A(d) (0x00000e00 + d * 0x0010)
+# define NV30_TCL_PRIMITIVE_3D_CLIP_PLANE_B(d) (0x00000e04 + d * 0x0010)
+# define NV30_TCL_PRIMITIVE_3D_CLIP_PLANE_C(d) (0x00000e08 + d * 0x0010)
+# define NV30_TCL_PRIMITIVE_3D_CLIP_PLANE_D(d) (0x00000e0c + d * 0x0010)
+# define NV30_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_AMBIENT_R(d) (0x00001000 + d * 0x0040)
+# define NV30_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_AMBIENT_G(d) (0x00001004 + d * 0x0040)
+# define NV30_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_AMBIENT_B(d) (0x00001008 + d * 0x0040)
+# define NV30_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_DIFFUSE_R(d) (0x0000100c + d * 0x0040)
+# define NV30_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_DIFFUSE_G(d) (0x00001010 + d * 0x0040)
+# define NV30_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_DIFFUSE_B(d) (0x00001014 + d * 0x0040)
+# define NV30_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_SPECULAR_R(d) (0x00001018 + d * 0x0040)
+# define NV30_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_SPECULAR_G(d) (0x0000101c + d * 0x0040)
+# define NV30_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_SPECULAR_B(d) (0x00001020 + d * 0x0040)
+# define NV30_TCL_PRIMITIVE_3D_LIGHT_HALF_VECTOR_X(d) (0x00001028 + d * 0x0080)
+# define NV30_TCL_PRIMITIVE_3D_LIGHT_HALF_VECTOR_Y(d) (0x0000102c + d * 0x0080)
+# define NV30_TCL_PRIMITIVE_3D_LIGHT_HALF_VECTOR_Z(d) (0x00001030 + d * 0x0080)
+# define NV30_TCL_PRIMITIVE_3D_LIGHT_DIRECTION_X(d) (0x00001034 + d * 0x0080)
+# define NV30_TCL_PRIMITIVE_3D_LIGHT_DIRECTION_Y(d) (0x00001038 + d * 0x0080)
+# define NV30_TCL_PRIMITIVE_3D_LIGHT_DIRECTION_Z(d) (0x0000103c + d * 0x0080)
+# define NV30_TCL_PRIMITIVE_3D_LIGHT_CONSTANT_ATTENUATION(d) (0x00001228 + d * 0x0040)
+# define NV30_TCL_PRIMITIVE_3D_LIGHT_LINEAR_ATTENUATION(d) (0x0000122c + d * 0x0040)
+# define NV30_TCL_PRIMITIVE_3D_LIGHT_QUADRATIC_ATTENUATION(d) (0x00001230 + d * 0x0040)
+# define NV30_TCL_PRIMITIVE_3D_LIGHT_SPOT_CUTOFF_A(d) (0x00001200 + d * 0x0040)
+# define NV30_TCL_PRIMITIVE_3D_LIGHT_SPOT_EXPONENT(d) (0x00001204 + d * 0x0040)
+# define NV30_TCL_PRIMITIVE_3D_LIGHT_SPOT_CUTOFF_B(d) (0x00001208 + d * 0x0040)
+# define NV30_TCL_PRIMITIVE_3D_LIGHT_SPOT_DIR_X(d) (0x0000120c + d * 0x0040)
+# define NV30_TCL_PRIMITIVE_3D_LIGHT_SPOT_DIR_Y(d) (0x00001210 + d * 0x0040)
+# define NV30_TCL_PRIMITIVE_3D_LIGHT_SPOT_DIR_Z(d) (0x00001214 + d * 0x0040)
+# define NV30_TCL_PRIMITIVE_3D_LIGHT_SPOT_CUTOFF_C(d) (0x00001218 + d * 0x0040)
+# define NV30_TCL_PRIMITIVE_3D_LIGHT_POSITION_X(d) (0x0000121c + d * 0x0040)
+# define NV30_TCL_PRIMITIVE_3D_LIGHT_POSITION_Y(d) (0x00001220 + d * 0x0040)
+# define NV30_TCL_PRIMITIVE_3D_LIGHT_POSITION_Z(d) (0x00001224 + d * 0x0040)
+# define NV30_TCL_PRIMITIVE_3D_FRONT_MATERIAL_SHININESS_A 0x00001400
+# define NV30_TCL_PRIMITIVE_3D_FRONT_MATERIAL_SHININESS_B 0x00001404
+# define NV30_TCL_PRIMITIVE_3D_FRONT_MATERIAL_SHININESS_C 0x00001408
+# define NV30_TCL_PRIMITIVE_3D_FRONT_MATERIAL_SHININESS_D 0x0000140c
+# define NV30_TCL_PRIMITIVE_3D_FRONT_MATERIAL_SHININESS_E 0x00001410
+# define NV30_TCL_PRIMITIVE_3D_FRONT_MATERIAL_SHININESS_F 0x00001414
+# define NV30_TCL_PRIMITIVE_3D_ENABLED_LIGHTS 0x00001420 /* Parameters: light 7 light 6 light 5 light 4 light 3 light 2 light 1 light 0 */
+# define NV30_TCL_PRIMITIVE_3D_UNK1D6C_OFFSET 0x00001d6c
+# define NV30_TCL_PRIMITIVE_3D_UNK1D70_VALUE 0x00001d70
+# define NV30_TCL_PRIMITIVE_3D_LINE_STIPPLE_ENABLE 0x00001db4
+# define NV30_TCL_PRIMITIVE_3D_LINE_STIPPLE_PATTERN 0x00001db8 /* Parameters: factor pattern */
+# define NV30_TCL_PRIMITIVE_3D_BEGIN_END 0x00001808
+# define NV30_TCL_PRIMITIVE_3D_CULL_FACE 0x00001830
+# define NV30_TCL_PRIMITIVE_3D_FRONT_FACE 0x00001834
+# define NV30_TCL_PRIMITIVE_3D_POLYGON_SMOOTH_ENABLE 0x00001838
+# define NV30_TCL_PRIMITIVE_3D_CULL_FACE_ENABLE 0x0000183c
+# define NV30_TCL_PRIMITIVE_3D_CLEAR_VALUE_DEPTH 0x00001d8c
+# define NV30_TCL_PRIMITIVE_3D_CLEAR_VALUE_ARGB 0x00001d90 /* Parameters: a r g b */
+# define NV30_TCL_PRIMITIVE_3D_CLEAR_WHICH_BUFFERS 0x00001d94
+# define NV30_TCL_PRIMITIVE_3D_BACK_MATERIAL_SHININESS_A 0x00001e20
+# define NV30_TCL_PRIMITIVE_3D_BACK_MATERIAL_SHININESS_B 0x00001e24
+# define NV30_TCL_PRIMITIVE_3D_BACK_MATERIAL_SHININESS_C 0x00001e28
+# define NV30_TCL_PRIMITIVE_3D_BACK_MATERIAL_SHININESS_D 0x00001e2c
+# define NV30_TCL_PRIMITIVE_3D_BACK_MATERIAL_SHININESS_E 0x00001e30
+# define NV30_TCL_PRIMITIVE_3D_BACK_MATERIAL_SHININESS_F 0x00001e34
+# define NV30_TCL_PRIMITIVE_3D_DO_VERTICES 0x00001dac
+# define NV30_TCL_PRIMITIVE_3D_VP_UPLOAD_FROM_ID 0x00001e9c
+# define NV30_TCL_PRIMITIVE_3D_VP_PROGRAM_START_ID 0x00001ea0
+# define NV30_TCL_PRIMITIVE_3D_VP_UPLOAD_CONST_ID 0x00001efc
+# define NV30_TCL_PRIMITIVE_3D_VP_UPLOAD_CONST_P0_X 0x00001f00
+# define NV30_TCL_PRIMITIVE_3D_VP_UPLOAD_CONST_P0_Y 0x00001f04
+# define NV30_TCL_PRIMITIVE_3D_VP_UPLOAD_CONST_P0_Z 0x00001f08
+# define NV30_TCL_PRIMITIVE_3D_VP_UPLOAD_CONST_P0_W 0x00001f0c
+# define NV30_TCL_PRIMITIVE_3D_VP_UPLOAD_CONST_P1_X 0x00001f10
+# define NV30_TCL_PRIMITIVE_3D_VP_UPLOAD_CONST_P1_Y 0x00001f14
+# define NV30_TCL_PRIMITIVE_3D_VP_UPLOAD_CONST_P1_Z 0x00001f18
+# define NV30_TCL_PRIMITIVE_3D_VP_UPLOAD_CONST_P1_W 0x00001f1c
+# define NV30_TCL_PRIMITIVE_3D_VP_UPLOAD_CONST_P2_X 0x00001f20
+# define NV30_TCL_PRIMITIVE_3D_VP_UPLOAD_CONST_P2_Y 0x00001f24
+# define NV30_TCL_PRIMITIVE_3D_VP_UPLOAD_CONST_P2_Z 0x00001f28
+# define NV30_TCL_PRIMITIVE_3D_VP_UPLOAD_CONST_P2_W 0x00001f2c
+# define NV30_TCL_PRIMITIVE_3D_VP_UPLOAD_CONST_P3_X 0x00001f30
+# define NV30_TCL_PRIMITIVE_3D_VP_UPLOAD_CONST_P3_Y 0x00001f34
+# define NV30_TCL_PRIMITIVE_3D_VP_UPLOAD_CONST_P3_Z 0x00001f38
+# define NV30_TCL_PRIMITIVE_3D_VP_UPLOAD_CONST_P3_W 0x00001f3c
+# define NV30_TCL_PRIMITIVE_3D_VTX_ATTR_3X(d) (0x00001500 + d * 0x0010)
+# define NV30_TCL_PRIMITIVE_3D_VTX_ATTR_3Y(d) (0x00001504 + d * 0x0010)
+# define NV30_TCL_PRIMITIVE_3D_VTX_ATTR_3Z(d) (0x00001508 + d * 0x0010)
+# define NV30_TCL_PRIMITIVE_3D_VTX_ATTR_3W(d) (0x0000150c + d * 0x0010)
+# define NV30_TCL_PRIMITIVE_3D_VTX_ATTR_4X(d) (0x00001c00 + d * 0x0010)
+# define NV30_TCL_PRIMITIVE_3D_VTX_ATTR_4Y(d) (0x00001c04 + d * 0x0010)
+# define NV30_TCL_PRIMITIVE_3D_VTX_ATTR_4Z(d) (0x00001c08 + d * 0x0010)
+# define NV30_TCL_PRIMITIVE_3D_VTX_ATTR_4W(d) (0x00001c0c + d * 0x0010)
+# define NV30_TCL_PRIMITIVE_3D_VB_POINTER_ATTR(d) (0x00001680 + d * 0x0004) /* Parameters: source: offset */
+# define NV30_TCL_PRIMITIVE_3D_VERTEX_NOR_3I_XY 0x00000a90 /* Parameters: y x */
+# define NV30_TCL_PRIMITIVE_3D_VERTEX_NOR_3I_Z 0x00000a94 /* Parameters: z */
+# define NV30_TCL_PRIMITIVE_3D_VERTEX_TX0_2F_S 0x000018c0
+# define NV30_TCL_PRIMITIVE_3D_VERTEX_TX0_2F_T 0x000018c4
+# define NV30_TCL_PRIMITIVE_3D_VERTEX_TX1_2F_S 0x000018c8
+# define NV30_TCL_PRIMITIVE_3D_VERTEX_TX1_2F_T 0x000018cc
+# define NV30_TCL_PRIMITIVE_3D_VERTEX_TX2_2F_S 0x000018d0
+# define NV30_TCL_PRIMITIVE_3D_VERTEX_TX2_2F_T 0x000018d4
+# define NV30_TCL_PRIMITIVE_3D_VERTEX_TX3_2F_S 0x000018d8
+# define NV30_TCL_PRIMITIVE_3D_VERTEX_TX3_2F_T 0x000018dc
+# define NV30_TCL_PRIMITIVE_3D_VERTEX_TX0_2I 0x00001920 /* Parameters: t s */
+# define NV30_TCL_PRIMITIVE_3D_VERTEX_TX1_2I 0x00001924 /* Parameters: t s */
+# define NV30_TCL_PRIMITIVE_3D_VERTEX_TX2_2I 0x00001928 /* Parameters: t s */
+# define NV30_TCL_PRIMITIVE_3D_VERTEX_TX3_2I 0x0000192c /* Parameters: t s */
+# define NV30_TCL_PRIMITIVE_3D_VERTEX_COL_4I 0x0000194c /* Parameters: a b g r */
+# define NV30_TCL_PRIMITIVE_3D_VERTEX_COL2_3I 0x00001950 /* Parameters: a b g r */
+# define NV30_TCL_PRIMITIVE_3D_VERTEX_TX0_4I_ST 0x000019c0 /* Parameters: t s */
+# define NV30_TCL_PRIMITIVE_3D_VERTEX_TX0_4I_RQ 0x000019c4 /* Parameters: q r */
+# define NV30_TCL_PRIMITIVE_3D_VERTEX_TX1_4I_ST 0x000019c8 /* Parameters: t s */
+# define NV30_TCL_PRIMITIVE_3D_VERTEX_TX1_4I_RQ 0x000019cc /* Parameters: q r */
+# define NV30_TCL_PRIMITIVE_3D_VERTEX_TX2_4I_ST 0x000019d0 /* Parameters: t s */
+# define NV30_TCL_PRIMITIVE_3D_VERTEX_TX2_4I_RQ 0x000019d4 /* Parameters: q r */
+# define NV30_TCL_PRIMITIVE_3D_VERTEX_TX3_4I_ST 0x000019d8 /* Parameters: t s */
+# define NV30_TCL_PRIMITIVE_3D_VERTEX_TX3_4I_RQ 0x000019dc /* Parameters: q r */
+# define NV30_TCL_PRIMITIVE_3D_VERTEX_FOG_1F 0x00001e54
+# define NV30_TCL_PRIMITIVE_3D_VERTEX_UNK_0 0x00001718
+# define NV30_TCL_PRIMITIVE_3D_VERTEX_ATTR( d) (0x00001740 + d * 0x0004)
+# define NV30_TCL_PRIMITIVE_3D_VERTEX_ATTR0_POS 0x00001740 /* Parameters: stride fields type */
+# define NV30_TCL_PRIMITIVE_3D_VERTEX_ATTR1_WGH 0x00001744 /* Parameters: stride fields type */
+# define NV30_TCL_PRIMITIVE_3D_VERTEX_ATTR2_NOR 0x00001748 /* Parameters: stride fields type */
+# define NV30_TCL_PRIMITIVE_3D_VERTEX_ATTR3_COL 0x0000174c /* Parameters: stride fields type */
+# define NV30_TCL_PRIMITIVE_3D_VERTEX_ATTR4_COL2 0x00001750 /* Parameters: stride fields type */
+# define NV30_TCL_PRIMITIVE_3D_VERTEX_ATTR5_FOG 0x00001754 /* Parameters: stride fields type */
+# define NV30_TCL_PRIMITIVE_3D_VERTEX_ATTR6 0x00001758 /* Parameters: stride fields type */
+# define NV30_TCL_PRIMITIVE_3D_VERTEX_ATTR7 0x0000175c /* Parameters: stride fields type */
+# define NV30_TCL_PRIMITIVE_3D_VERTEX_ATTR8_TX0 0x00001760 /* Parameters: stride fields type */
+# define NV30_TCL_PRIMITIVE_3D_VERTEX_ATTR9_TX1 0x00001764 /* Parameters: stride fields type */
+# define NV30_TCL_PRIMITIVE_3D_VERTEX_ATTR10_TX2 0x00001768 /* Parameters: stride fields type */
+# define NV30_TCL_PRIMITIVE_3D_VERTEX_ATTR11_TX3 0x0000176c /* Parameters: stride fields type */
+# define NV30_TCL_PRIMITIVE_3D_VERTEX_ATTR12_TX4 0x00001770 /* Parameters: stride fields type */
+# define NV30_TCL_PRIMITIVE_3D_VERTEX_ATTR13_TX5 0x00001774 /* Parameters: stride fields type */
+# define NV30_TCL_PRIMITIVE_3D_VERTEX_ATTR14_TX6 0x00001778 /* Parameters: stride fields type */
+# define NV30_TCL_PRIMITIVE_3D_VERTEX_ATTR15_TX7 0x0000177c /* Parameters: stride fields type */
+# define NV30_TCL_PRIMITIVE_3D_LIGHT_MODEL_BACK_SIDE_PRODUCT_AMBIENT_PLUS_EMISSION_R 0x000017a0
+# define NV30_TCL_PRIMITIVE_3D_LIGHT_MODEL_BACK_SIDE_PRODUCT_AMBIENT_PLUS_EMISSION_G 0x000017a4
+# define NV30_TCL_PRIMITIVE_3D_LIGHT_MODEL_BACK_SIDE_PRODUCT_AMBIENT_PLUS_EMISSION_B 0x000017a8
+# define NV30_TCL_PRIMITIVE_3D_FP_ACTIVE_PROGRAM 0x000008e4
+# define NV30_TCL_PRIMITIVE_3D_TX_ADDRESS_UNIT(d) (0x00001a00 + d * 0x0020)
+# define NV30_TCL_PRIMITIVE_3D_TX_FORMAT_UNIT(d) (0x00001a04 + d * 0x0020) /* Parameters: mipmap type format ncomp cubic */
+# define NV30_TCL_PRIMITIVE_3D_TX_WRAP_UNIT(d) (0x00001a08 + d * 0x0020) /* Parameters: wrap_s wrap_t wrap_r */
+# define NV30_TCL_PRIMITIVE_3D_TX_ENABLE_UNIT(d) (0x00001a0c + d * 0x0020) /* Parameters: nv40_enable nv30_enable anisotropy */
+# define NV30_TCL_PRIMITIVE_3D_TX_SWIZZLE_UNIT(d) (0x00001a10 + d * 0x0020)
+# define NV30_TCL_PRIMITIVE_3D_TX_FILTER_UNIT(d) (0x00001a14 + d * 0x0020) /* Parameters: filter_min filter_mag */
+# define NV30_TCL_PRIMITIVE_3D_TX_XY_DIM_UNIT(d) (0x00001a18 + d * 0x0020) /* Parameters: width height */
+# define NV30_TCL_PRIMITIVE_3D_TX_UNK07_UNIT(d) (0x00001a1c + d * 0x0020)
+# define NV30_TCL_PRIMITIVE_3D_TX_DEPTH_UNIT(d) (0x00001840 + d * 0x0004) /* Parameters: depth NPOT pitch */
+# define NV30_TCL_PRIMITIVE_3D_VB_VERTEX_BATCH 0x00001814 /* Parameters: count_vertices offset_vertices */
+# define NV30_TCL_PRIMITIVE_3D_VB_ELEMENT_U16 0x0000180c /* Parameters: 1: 0: */
+# define NV30_TCL_PRIMITIVE_3D_VB_ELEMENT_U32 0x00001810
+# define NV30_TCL_PRIMITIVE_3D_VERTEX_DATA 0x00001818
+# define NV30_TCL_PRIMITIVE_3D_COLOR_LOGIC_OP_ENABLE 0x00000374
+# define NV30_TCL_PRIMITIVE_3D_COLOR_LOGIC_OP_OP 0x00000378
+# define NV30_TCL_PRIMITIVE_3D_SET_DISPLAY_LIST_MEM_OFFSET 0x0000181c
+# define NV30_TCL_PRIMITIVE_3D_EXECUTE_DISPLAY_LIST 0x00001824 /* Parameters: length start offset */
+# define NV30_TCL_PRIMITIVE_3D_POLYGON_MODE_FRONT 0x00001828
+# define NV30_TCL_PRIMITIVE_3D_POLYGON_MODE_BACK 0x0000182c
+# define NV30_TCL_PRIMITIVE_3D_POLYGON_STIPPLE_ENABLE 0x0000147c
+# define NV30_TCL_PRIMITIVE_3D_POLYGON_STIPPLE_PATTERN( d) (0x00001480 + d * 0x0004)
+# define NV30_TCL_PRIMITIVE_3D_SET_CLIPPING_PLANES 0x00001478
+# define NV30_TCL_PRIMITIVE_3D_VP_IN_REG 0x00001ff0 /* Parameters: vertex pos weight normal primary color secondary color fogcoord texture coords 0 texture ccords 1 texture coords 2 texture coords 3 texture coords 4 texture coords 5 texture coords 6 texture coords 7 */
+# define NV30_TCL_PRIMITIVE_3D_VP_OUT_REG 0x00001ff4 /* Parameters: primary color secondary color backface primary color backface secondary color fogcoord pointsize clip plane 0 clip plane 1 clip plane 2 clip plane 3 clip plane 4 clip plane 5 texture coords 0 texture coords 1 texture coords 2 texture coords 3 texture coords 4 texture coords 5 texture coords 6 texture coords 7 */
+
+/******************************************
+Object NV30_CLEAR_BUFFER used on: NV30 NV40 G70
+*/
+#define NV30_CLEAR_BUFFER 0x00000066
+# define NV30_CLEAR_BUFFER_SET_DMA_NOTIFY 0x00000180
+# define NV30_CLEAR_BUFFER_SET_IMAGE_PATTERN 0x00000188
+# define NV30_CLEAR_BUFFER_SET_RASTER_OP 0x0000018c
+# define NV30_CLEAR_BUFFER_SET_CONTEXT_SURFACE_2D 0x00000198
+# define NV30_CLEAR_BUFFER_UNK002fc 0x000002fc
+
+/******************************************
+Object NV50_TCL_PRIMITIVE_3D used on:
+*/
+#define NV50_TCL_PRIMITIVE_3D 0x00000097
+# define NV50_TCL_PRIMITIVE_3D_SET_OBJECT_0( d) (0x00000180 + d * 0x0004)
+# define NV50_TCL_PRIMITIVE_3D_SET_OBJECT_1( d) (0x000001c0 + d * 0x0004)
+# define NV50_TCL_PRIMITIVE_3D_VERTEX_FOG_1F 0x00000314
+# define NV50_TCL_PRIMITIVE_3D_VERTEX_POS_2F_X 0x00000380
+# define NV50_TCL_PRIMITIVE_3D_VERTEX_POS_2F_Y 0x00000384
+# define NV50_TCL_PRIMITIVE_3D_VERTEX_TX0_2F_S 0x000003c0
+# define NV50_TCL_PRIMITIVE_3D_VERTEX_TX0_2F_T 0x000003c4
+# define NV50_TCL_PRIMITIVE_3D_VERTEX_TX1_2F_S 0x000003c8
+# define NV50_TCL_PRIMITIVE_3D_VERTEX_TX1_2F_T 0x000003cc
+# define NV50_TCL_PRIMITIVE_3D_VERTEX_TX2_2F_S 0x000003d0
+# define NV50_TCL_PRIMITIVE_3D_VERTEX_TX2_2F_T 0x000003d4
+# define NV50_TCL_PRIMITIVE_3D_VERTEX_TX3_2F_S 0x000003d8
+# define NV50_TCL_PRIMITIVE_3D_VERTEX_TX3_2F_T 0x000003dc
+# define NV50_TCL_PRIMITIVE_3D_VERTEX_POS_3F_X 0x00000400
+# define NV50_TCL_PRIMITIVE_3D_VERTEX_POS_3F_Y 0x00000404
+# define NV50_TCL_PRIMITIVE_3D_VERTEX_POS_3F_Z 0x00000408
+# define NV50_TCL_PRIMITIVE_3D_VERTEX_NOR_3F_X 0x00000420
+# define NV50_TCL_PRIMITIVE_3D_VERTEX_NOR_3F_Y 0x00000424
+# define NV50_TCL_PRIMITIVE_3D_VERTEX_NOR_3F_Z 0x00000428
+# define NV50_TCL_PRIMITIVE_3D_VERTEX_COL_3F_R 0x00000430
+# define NV50_TCL_PRIMITIVE_3D_VERTEX_COL_3F_G 0x00000434
+# define NV50_TCL_PRIMITIVE_3D_VERTEX_COL_3F_B 0x00000438
+# define NV50_TCL_PRIMITIVE_3D_VERTEX_COL2_3F_R 0x00000440
+# define NV50_TCL_PRIMITIVE_3D_VERTEX_COL2_3F_G 0x00000444
+# define NV50_TCL_PRIMITIVE_3D_VERTEX_COL2_3F_B 0x00000448
+# define NV50_TCL_PRIMITIVE_3D_VERTEX_POS_4F_X 0x00000500
+# define NV50_TCL_PRIMITIVE_3D_VERTEX_POS_4F_Y 0x00000504
+# define NV50_TCL_PRIMITIVE_3D_VERTEX_POS_4F_Z 0x00000508
+# define NV50_TCL_PRIMITIVE_3D_VERTEX_POS_4F_W 0x0000050c
+# define NV50_TCL_PRIMITIVE_3D_VERTEX_COL_4F_R 0x00000530
+# define NV50_TCL_PRIMITIVE_3D_VERTEX_COL_4F_G 0x00000534
+# define NV50_TCL_PRIMITIVE_3D_VERTEX_COL_4F_B 0x00000538
+# define NV50_TCL_PRIMITIVE_3D_VERTEX_COL_4F_A 0x0000053c
+# define NV50_TCL_PRIMITIVE_3D_VERTEX_TX0_4F_S 0x00000580
+# define NV50_TCL_PRIMITIVE_3D_VERTEX_TX0_4F_T 0x00000584
+# define NV50_TCL_PRIMITIVE_3D_VERTEX_TX0_4F_R 0x00000588
+# define NV50_TCL_PRIMITIVE_3D_VERTEX_TX0_4F_Q 0x0000058c
+# define NV50_TCL_PRIMITIVE_3D_VERTEX_TX1_4F_S 0x00000590
+# define NV50_TCL_PRIMITIVE_3D_VERTEX_TX1_4F_T 0x00000594
+# define NV50_TCL_PRIMITIVE_3D_VERTEX_TX1_4F_R 0x00000598
+# define NV50_TCL_PRIMITIVE_3D_VERTEX_TX1_4F_Q 0x0000059c
+# define NV50_TCL_PRIMITIVE_3D_VERTEX_TX2_4F_S 0x000005a0
+# define NV50_TCL_PRIMITIVE_3D_VERTEX_TX2_4F_T 0x000005a4
+# define NV50_TCL_PRIMITIVE_3D_VERTEX_TX2_4F_R 0x000005a8
+# define NV50_TCL_PRIMITIVE_3D_VERTEX_TX2_4F_Q 0x000005ac
+# define NV50_TCL_PRIMITIVE_3D_VERTEX_TX3_4F_S 0x000005b0
+# define NV50_TCL_PRIMITIVE_3D_VERTEX_TX3_4F_T 0x000005b4
+# define NV50_TCL_PRIMITIVE_3D_VERTEX_TX3_4F_R 0x000005b8
+# define NV50_TCL_PRIMITIVE_3D_VERTEX_TX3_4F_Q 0x000005bc
+# define NV50_TCL_PRIMITIVE_3D_VERTEX_TX0_2I 0x000006a0 /* Parameters: t s */
+# define NV50_TCL_PRIMITIVE_3D_VERTEX_TX1_2I 0x000006a4 /* Parameters: t s */
+# define NV50_TCL_PRIMITIVE_3D_VERTEX_TX2_2I 0x000006a8 /* Parameters: t s */
+# define NV50_TCL_PRIMITIVE_3D_VERTEX_TX3_2I 0x000006ac /* Parameters: t s */
+# define NV50_TCL_PRIMITIVE_3D_VERTEX_POS_4I_XY 0x00000700 /* Parameters: y x */
+# define NV50_TCL_PRIMITIVE_3D_VERTEX_POS_4I_ZW 0x00000704 /* Parameters: w z */
+# define NV50_TCL_PRIMITIVE_3D_VERTEX_TX0_4I_ST 0x00000740 /* Parameters: t s */
+# define NV50_TCL_PRIMITIVE_3D_VERTEX_TX0_4I_RQ 0x00000744 /* Parameters: q r */
+# define NV50_TCL_PRIMITIVE_3D_VERTEX_TX1_4I_ST 0x00000748 /* Parameters: t s */
+# define NV50_TCL_PRIMITIVE_3D_VERTEX_TX1_4I_RQ 0x0000074c /* Parameters: q r */
+# define NV50_TCL_PRIMITIVE_3D_VERTEX_TX2_4I_ST 0x00000750 /* Parameters: t s */
+# define NV50_TCL_PRIMITIVE_3D_VERTEX_TX2_4I_RQ 0x00000754 /* Parameters: q r */
+# define NV50_TCL_PRIMITIVE_3D_VERTEX_TX3_4I_ST 0x00000758 /* Parameters: t s */
+# define NV50_TCL_PRIMITIVE_3D_VERTEX_TX3_4I_RQ 0x0000075c /* Parameters: q r */
+# define NV50_TCL_PRIMITIVE_3D_VERTEX_NOR_3I_XY 0x00000790 /* Parameters: y x */
+# define NV50_TCL_PRIMITIVE_3D_VERTEX_NOR_3I_Z 0x00000794 /* Parameters: z */
+# define NV50_TCL_PRIMITIVE_3D_VERTEX_COL_4I 0x0000088c /* Parameters: a b g r */
+# define NV50_TCL_PRIMITIVE_3D_VERTEX_COL2_3I 0x00000890 /* Parameters: a b g r */
+# define NV50_TCL_PRIMITIVE_3D_VIEWPORT_UNK0_X 0x00000a00
+# define NV50_TCL_PRIMITIVE_3D_VIEWPORT_UNK0_Y 0x00000a04
+# define NV50_TCL_PRIMITIVE_3D_VIEWPORT_UNK0_Z 0x00000a08
+# define NV50_TCL_PRIMITIVE_3D_VIEWPORT_UNK1_X 0x00000a0c
+# define NV50_TCL_PRIMITIVE_3D_VIEWPORT_UNK1_Y 0x00000a10
+# define NV50_TCL_PRIMITIVE_3D_VIEWPORT_UNK1_Z 0x00000a14
+# define NV50_TCL_PRIMITIVE_3D_DEPTH_RANGE_NEAR 0x00000c08
+# define NV50_TCL_PRIMITIVE_3D_DEPTH_RANGE_FAR 0x00000c0c
+# define NV50_TCL_PRIMITIVE_3D_VIEWPORT_CLIP_HORIZ(d) (0x00000d00 + d * 0x0008) /* Parameters: x2 x1 */
+# define NV50_TCL_PRIMITIVE_3D_VIEWPORT_CLIP_VERT(d) (0x00000d04 + d * 0x0008) /* Parameters: y2 y1 */
+# define NV50_TCL_PRIMITIVE_3D_VERTEX_BUFFER_FIRST 0x00000d74
+# define NV50_TCL_PRIMITIVE_3D_VERTEX_BUFFER_COUNT 0x00000d78
+# define NV50_TCL_PRIMITIVE_3D_CLEAR_COLOR_R 0x00000d80
+# define NV50_TCL_PRIMITIVE_3D_CLEAR_COLOR_G 0x00000d84
+# define NV50_TCL_PRIMITIVE_3D_CLEAR_COLOR_B 0x00000d88
+# define NV50_TCL_PRIMITIVE_3D_CLEAR_COLOR_A 0x00000d8c
+# define NV50_TCL_PRIMITIVE_3D_CLEAR_DEPTH 0x00000d90
+# define NV50_TCL_PRIMITIVE_3D_CLEAR_STENCIL 0x00000da0
+# define NV50_TCL_PRIMITIVE_3D_POLYGON_MODE_FRONT 0x00000dac
+# define NV50_TCL_PRIMITIVE_3D_POLYGON_MODE_BACK 0x00000db0
+# define NV50_TCL_PRIMITIVE_3D_POLYGON_SMOOTH_ENABLE 0x00000db4
+# define NV50_TCL_PRIMITIVE_3D_POLYGON_OFFSET_POINT_ENABLE 0x00000dc0
+# define NV50_TCL_PRIMITIVE_3D_POLYGON_OFFSET_LINE_ENABLE 0x00000dc4
+# define NV50_TCL_PRIMITIVE_3D_POLYGON_OFFSET_FILL_ENABLE 0x00000dc8
+# define NV50_TCL_PRIMITIVE_3D_SCISSOR_WIDTH_XPOS 0x00000e04 /* Parameters: w x */
+# define NV50_TCL_PRIMITIVE_3D_SCISSOR_HEIGHT_YPOS 0x00000e08 /* Parameters: h y */
+# define NV50_TCL_PRIMITIVE_3D_VP_UPLOAD_CONST_ID 0x00000f00
+# define NV50_TCL_PRIMITIVE_3D_VP_UPLOAD_CONST_X 0x00000f04
+# define NV50_TCL_PRIMITIVE_3D_VP_UPLOAD_CONST_Y 0x00000f08
+# define NV50_TCL_PRIMITIVE_3D_VP_UPLOAD_CONST_Z 0x00000f0c
+# define NV50_TCL_PRIMITIVE_3D_VP_UPLOAD_CONST_W 0x00000f10
+# define NV50_TCL_PRIMITIVE_3D_STENCIL_FRONT_FUNC_REF 0x00000f54
+# define NV50_TCL_PRIMITIVE_3D_STENCIL_FRONT_MASK 0x00000f58
+# define NV50_TCL_PRIMITIVE_3D_STENCIL_FRONT_FUNC_MASK 0x00000f5c
+# define NV50_TCL_PRIMITIVE_3D_DEPTH_TEST_ENABLE 0x000012cc
+# define NV50_TCL_PRIMITIVE_3D_SHADE_MODEL 0x000012d4
+# define NV50_TCL_PRIMITIVE_3D_DEPTH_WRITE_ENABLE 0x000012e8
+# define NV50_TCL_PRIMITIVE_3D_ALPHA_FUNC_ENABLE 0x000012ec
+# define NV50_TCL_PRIMITIVE_3D_DEPTH_FUNC 0x0000130c
+# define NV50_TCL_PRIMITIVE_3D_ALPHA_FUNC_REF 0x00001310
+# define NV50_TCL_PRIMITIVE_3D_ALPHA_FUNC_FUNC 0x00001314
+# define NV50_TCL_PRIMITIVE_3D_BLEND_COLOR_R 0x0000131c
+# define NV50_TCL_PRIMITIVE_3D_BLEND_COLOR_G 0x00001320
+# define NV50_TCL_PRIMITIVE_3D_BLEND_COLOR_B 0x00001324
+# define NV50_TCL_PRIMITIVE_3D_BLEND_COLOR_A 0x00001328
+# define NV50_TCL_PRIMITIVE_3D_BLEND_EQUATION_RGB 0x00001340
+# define NV50_TCL_PRIMITIVE_3D_BLEND_FUNC_SRC_RGB 0x00001344
+# define NV50_TCL_PRIMITIVE_3D_BLEND_FUNC_DST_RGB 0x00001348
+# define NV50_TCL_PRIMITIVE_3D_BLEND_EQUATION_ALPHA 0x0000134c
+# define NV50_TCL_PRIMITIVE_3D_BLEND_FUNC_SRC_ALPHA 0x00001350
+# define NV50_TCL_PRIMITIVE_3D_BLEND_FUNC_DST_ALPHA 0x00001358
+# define NV50_TCL_PRIMITIVE_3D_STENCIL_BACK_ENABLE 0x00001380
+# define NV50_TCL_PRIMITIVE_3D_STENCIL_BACK_OP_FAIL 0x00001384
+# define NV50_TCL_PRIMITIVE_3D_STENCIL_BACK_OP_ZFAIL 0x00001388
+# define NV50_TCL_PRIMITIVE_3D_STENCIL_BACK_OP_ZPASS 0x0000138c
+# define NV50_TCL_PRIMITIVE_3D_STENCIL_BACK_FUNC_FUNC 0x00001390
+# define NV50_TCL_PRIMITIVE_3D_STENCIL_BACK_FUNC_REF 0x00001394
+# define NV50_TCL_PRIMITIVE_3D_STENCIL_BACK_MASK 0x00001398
+# define NV50_TCL_PRIMITIVE_3D_STENCIL_BACK_FUNC_MASK 0x0000139c
+# define NV50_TCL_PRIMITIVE_3D_LINE_WIDTH 0x000013b0
+# define NV50_TCL_PRIMITIVE_3D_POINT_SIZE 0x00001518
+# define NV50_TCL_PRIMITIVE_3D_POLYGON_OFFSET_FACTOR 0x0000156c
+# define NV50_TCL_PRIMITIVE_3D_LINE_SMOOTH_ENABLE 0x00001570
+# define NV50_TCL_PRIMITIVE_3D_STENCIL_FRONT_ENABLE 0x00001594
+# define NV50_TCL_PRIMITIVE_3D_STENCIL_FRONT_OP_FAIL 0x00001598
+# define NV50_TCL_PRIMITIVE_3D_STENCIL_FRONT_OP_ZFAIL 0x0000159c
+# define NV50_TCL_PRIMITIVE_3D_STENCIL_FRONT_OP_ZPASS 0x000015a0
+# define NV50_TCL_PRIMITIVE_3D_STENCIL_FRONT_FUNC_FUNC 0x000015a4
+# define NV50_TCL_PRIMITIVE_3D_POLYGON_OFFSET_UNITS 0x000015bc
+# define NV50_TCL_PRIMITIVE_3D_VERTEX_BEGIN 0x000015dc
+# define NV50_TCL_PRIMITIVE_3D_VERTEX_END 0x000015e0
+# define NV50_TCL_PRIMITIVE_3D_VERTEX_DATA 0x00001640
+# define NV50_TCL_PRIMITIVE_3D_LINE_STIPPLE_ENABLE 0x0000166c
+# define NV50_TCL_PRIMITIVE_3D_LINE_STIPPLE_PATTERN 0x00001680 /* Parameters: pattern factor */
+# define NV50_TCL_PRIMITIVE_3D_POLYGON_STIPPLE_ENABLE 0x0000168c
+# define NV50_TCL_PRIMITIVE_3D_POLYGON_STIPPLE_PATTERN( d) (0x00001700 + d * 0x0004)
+# define NV50_TCL_PRIMITIVE_3D_CULL_FACE_ENABLE 0x00001918
+# define NV50_TCL_PRIMITIVE_3D_FRONT_FACE 0x0000191c
+# define NV50_TCL_PRIMITIVE_3D_CULL_FACE 0x00001920
+# define NV50_TCL_PRIMITIVE_3D_LOGIC_OP_ENABLE 0x000019c4
+# define NV50_TCL_PRIMITIVE_3D_LOGIC_OP_OP 0x000019c8
+# define NV50_TCL_PRIMITIVE_3D_CLEAR_BUFFERS 0x000019d0 /* Parameters: color stencil depth */
+# define NV50_TCL_PRIMITIVE_3D_COLOR_MASK( d) (0x00001a00 + d * 0x0004) /* Parameters: a b g r */
+
+/******************************************
+Object NV_DMA_FROM_MEMORY used on: NV03 NV04 NV10 NV15 NV20 NV30 NV40 G70
+*/
+#define NV_DMA_FROM_MEMORY 0x00000002
+
+/******************************************
+Object NV_DMA_TO_MEMORY used on: NV03 NV04 NV10 NV15 NV20 NV30 NV40 G70
+*/
+#define NV_DMA_TO_MEMORY 0x00000003
+
+/******************************************
+Object NV_DMA_IN_MEMORY used on: NV03 NV04 NV10 NV15 NV20 NV30 NV40 G70
+*/
+#define NV_DMA_IN_MEMORY 0x0000003d
+
+/******************************************
+Object NvType0046 used on: NV04
+*/
+#define NvType0046 0x00000046
+# define NvType0046_DMA_NOTIFY 0x00000180
+# define NvType0046_DMA_MEM_1 0x00000184
+# define NvType0046_DMA_MEM_2 0x00000188
+# define NvType0046_DMA_3 0x0000018c
+# define NvType0046_DMA_4 0x00000190
+# define NvType0046_OBJ_5 0x00000194
+# define NvType0046_OBJ_6 0x00000198
+# define NvType0046_PITCH1 0x00000304
+# define NvType0046_PITCH2 0x0000030c
+# define NvType0046_SIZE 0x00000340 /* Parameters: width height */
+# define NvType0046_WIDTH 0x00000344 /* Parameters: visible_width blank_width */
+# define NvType0046_HSYNC 0x00000348 /* Parameters: hsync_start hsync_len */
+# define NvType0046_HEIGHT 0x0000034c /* Parameters: visible_height blank_height */
+# define NvType0046_VSYNC 0x00000350 /* Parameters: vsync_start vsync_len */
+# define NvType0046_FULL_SIZE 0x00000354 /* Parameters: full_width full_height */
+# define NvType0046_PIXEL_CLK 0x00000358
+# define NvType0046_FLAGS 0x0000035c /* Parameters: doublescan -hsync -vsync depth */
+
+/******************************************
+Object NvType0047 used on: NV04
+*/
+#define NvType0047 0x00000047
+# define NvType0047_DMA_NOTIFY 0x00000180
+# define NvType0047_UNK19C 0x0000019c
+# define NvType0047_UNK1A0 0x000001a0
+
+/******************************************
+Object NvType0049 used on: NV04
+*/
+#define NvType0049 0x00000049
+# define NvType0049_DMA_NOTIFY 0x00000180
+# define NvType0049_DMA_MEM_1 0x00000184
+# define NvType0049_DMA_MEM_2 0x00000188
+
+/******************************************
+Object NvType004D used on: NV04
+*/
+#define NvType004D 0x0000004d
+# define NvType004D_DMA_NOTIFY 0x00000180
+# define NvType004D_DMA_MEM_1 0x00000184
+# define NvType004D_DMA_MEM_2 0x00000188
+# define NvType004D_DMA_MEM_3 0x0000018c
+# define NvType004D_DMA_MEM_4 0x00000190
+
+#endif /* _NOUVEAU_REG_H */
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_screen.c b/src/mesa/drivers/dri/nouveau/nouveau_screen.c
new file mode 100644
index 0000000000..ab7742df14
--- /dev/null
+++ b/src/mesa/drivers/dri/nouveau/nouveau_screen.c
@@ -0,0 +1,376 @@
+/**************************************************************************
+
+Copyright 2006 Stephane Marchesin
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+#include "glheader.h"
+#include "imports.h"
+#include "mtypes.h"
+#include "framebuffer.h"
+#include "renderbuffer.h"
+
+#include "nouveau_context.h"
+#include "nouveau_screen.h"
+#include "nouveau_object.h"
+#include "nouveau_span.h"
+
+#include "utils.h"
+#include "context.h"
+#include "vblank.h"
+#include "drirenderbuffer.h"
+
+#include "GL/internal/dri_interface.h"
+
+#include "xmlpool.h"
+
+PUBLIC const char __driConfigOptions[] =
+DRI_CONF_BEGIN
+ DRI_CONF_SECTION_DEBUG
+ DRI_CONF_NO_RAST(false)
+ DRI_CONF_SECTION_END
+DRI_CONF_END;
+static const GLuint __driNConfigOptions = 1;
+
+extern const struct dri_extension common_extensions[];
+extern const struct dri_extension nv10_extensions[];
+extern const struct dri_extension nv20_extensions[];
+extern const struct dri_extension nv30_extensions[];
+extern const struct dri_extension nv40_extensions[];
+extern const struct dri_extension nv50_extensions[];
+
+static nouveauScreenPtr nouveauCreateScreen(__DRIscreenPrivate *sPriv)
+{
+ nouveauScreenPtr screen;
+ NOUVEAUDRIPtr dri_priv=(NOUVEAUDRIPtr)sPriv->pDevPriv;
+
+ /* allocate screen */
+ screen = (nouveauScreenPtr) CALLOC( sizeof(*screen) );
+ if ( !screen ) {
+ __driUtilMessage("%s: Could not allocate memory for screen structure",__FUNCTION__);
+ return NULL;
+ }
+
+ screen->card=nouveau_card_lookup(dri_priv->device_id);
+ if (!screen->card) {
+ __driUtilMessage("%s: Unknown card type 0x%04x:0x%04x\n",
+ __func__, dri_priv->device_id >> 16, dri_priv->device_id & 0xFFFF);
+ FREE(screen);
+ return NULL;
+ }
+
+ /* parse information in __driConfigOptions */
+ driParseOptionInfo (&screen->optionCache,__driConfigOptions, __driNConfigOptions);
+
+ screen->fbFormat = dri_priv->bpp / 8;
+ screen->frontOffset = dri_priv->front_offset;
+ screen->frontPitch = dri_priv->front_pitch;
+ screen->backOffset = dri_priv->back_offset;
+ screen->backPitch = dri_priv->back_pitch;
+ screen->depthOffset = dri_priv->depth_offset;
+ screen->depthPitch = dri_priv->depth_pitch;
+
+ screen->driScreen = sPriv;
+ return screen;
+}
+
+static void
+nouveauDestroyScreen(__DRIscreenPrivate *sPriv)
+{
+ nouveauScreenPtr screen = (nouveauScreenPtr)sPriv->private;
+
+ if (!screen) return;
+
+ /* free all option information */
+ driDestroyOptionInfo (&screen->optionCache);
+
+ FREE(screen);
+ sPriv->private = NULL;
+}
+
+static GLboolean nouveauInitDriver(__DRIscreenPrivate *sPriv)
+{
+ sPriv->private = (void *) nouveauCreateScreen( sPriv );
+ if ( !sPriv->private ) {
+ nouveauDestroyScreen( sPriv );
+ return GL_FALSE;
+ }
+
+ return GL_TRUE;
+}
+
+/**
+ * Create the Mesa framebuffer and renderbuffers for a given window/drawable.
+ *
+ * \todo This function (and its interface) will need to be updated to support
+ * pbuffers.
+ */
+static GLboolean
+nouveauCreateBuffer(__DRIscreenPrivate *driScrnPriv,
+ __DRIdrawablePrivate *driDrawPriv,
+ const __GLcontextModes *mesaVis,
+ GLboolean isPixmap)
+{
+ nouveauScreenPtr screen = (nouveauScreenPtr) driScrnPriv->private;
+ nouveau_renderbuffer *nrb;
+ struct gl_framebuffer *fb;
+ const GLboolean swAccum = mesaVis->accumRedBits > 0;
+ const GLboolean swStencil = mesaVis->stencilBits > 0 && mesaVis->depthBits != 24;
+ GLenum color_format = screen->fbFormat == 4 ? GL_RGBA8 : GL_RGB5;
+
+ if (isPixmap)
+ return GL_FALSE; /* not implemented */
+
+ fb = _mesa_create_framebuffer(mesaVis);
+ if (!fb)
+ return GL_FALSE;
+
+ /* Front buffer */
+ nrb = nouveau_renderbuffer_new(color_format,
+ driScrnPriv->pFB + screen->frontOffset,
+ screen->frontOffset,
+ screen->frontPitch * screen->fbFormat,
+ driDrawPriv);
+ nouveauSpanSetFunctions(nrb, mesaVis);
+ _mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, &nrb->mesa);
+
+ if (0 /* unified buffers if we choose to support them.. */) {
+ } else {
+ if (mesaVis->doubleBufferMode) {
+ nrb = nouveau_renderbuffer_new(color_format, NULL,
+ 0, 0,
+ NULL);
+ nouveauSpanSetFunctions(nrb, mesaVis);
+ _mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, &nrb->mesa);
+ }
+
+ if (mesaVis->depthBits == 24 && mesaVis->stencilBits == 8) {
+ nrb = nouveau_renderbuffer_new(GL_DEPTH24_STENCIL8_EXT, NULL,
+ 0, 0,
+ NULL);
+ nouveauSpanSetFunctions(nrb, mesaVis);
+ _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &nrb->mesa);
+ _mesa_add_renderbuffer(fb, BUFFER_STENCIL, &nrb->mesa);
+ } else if (mesaVis->depthBits == 24) {
+ nrb = nouveau_renderbuffer_new(GL_DEPTH_COMPONENT24, NULL,
+ 0, 0,
+ NULL);
+ nouveauSpanSetFunctions(nrb, mesaVis);
+ _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &nrb->mesa);
+ } else if (mesaVis->depthBits == 16) {
+ nrb = nouveau_renderbuffer_new(GL_DEPTH_COMPONENT16, NULL,
+ 0, 0,
+ NULL);
+ nouveauSpanSetFunctions(nrb, mesaVis);
+ _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &nrb->mesa);
+ }
+ }
+
+ _mesa_add_soft_renderbuffers(fb,
+ GL_FALSE, /* color */
+ GL_FALSE, /* depth */
+ swStencil,
+ swAccum,
+ GL_FALSE, /* alpha */
+ GL_FALSE /* aux */);
+
+ driDrawPriv->driverPrivate = (void *) fb;
+ return (driDrawPriv->driverPrivate != NULL);
+}
+
+
+static void
+nouveauDestroyBuffer(__DRIdrawablePrivate *driDrawPriv)
+{
+ _mesa_destroy_framebuffer((GLframebuffer *) (driDrawPriv->driverPrivate));
+}
+
+static int
+nouveauGetSwapInfo(__DRIdrawablePrivate *dpriv, __DRIswapInfo *sInfo)
+{
+ return -1;
+}
+
+static const struct __DriverAPIRec nouveauAPI = {
+ .InitDriver = nouveauInitDriver,
+ .DestroyScreen = nouveauDestroyScreen,
+ .CreateContext = nouveauCreateContext,
+ .DestroyContext = nouveauDestroyContext,
+ .CreateBuffer = nouveauCreateBuffer,
+ .DestroyBuffer = nouveauDestroyBuffer,
+ .SwapBuffers = nouveauSwapBuffers,
+ .MakeCurrent = nouveauMakeCurrent,
+ .UnbindContext = nouveauUnbindContext,
+ .GetSwapInfo = nouveauGetSwapInfo,
+ .GetMSC = driGetMSC32,
+ .WaitForMSC = driWaitForMSC32,
+ .WaitForSBC = NULL,
+ .SwapBuffersMSC = NULL,
+ .CopySubBuffer = nouveauCopySubBuffer
+};
+
+
+static __GLcontextModes *
+nouveauFillInModes( unsigned pixel_bits, unsigned depth_bits,
+ unsigned stencil_bits, GLboolean have_back_buffer )
+{
+ __GLcontextModes * modes;
+ __GLcontextModes * m;
+ unsigned num_modes;
+ unsigned depth_buffer_factor;
+ unsigned back_buffer_factor;
+ int i;
+
+ static const struct {
+ GLenum format;
+ GLenum type;
+ } fb_format_array[] = {
+ { GL_RGB , GL_UNSIGNED_SHORT_5_6_5 },
+ { GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV },
+ { GL_BGR , GL_UNSIGNED_INT_8_8_8_8_REV },
+ };
+
+ /* GLX_SWAP_COPY_OML is only supported because the Intel driver doesn't
+ * support pageflipping at all.
+ */
+ static const GLenum back_buffer_modes[] = {
+ GLX_NONE, GLX_SWAP_UNDEFINED_OML, GLX_SWAP_COPY_OML
+ };
+
+ u_int8_t depth_bits_array[4] = { 0, 16, 24, 24 };
+ u_int8_t stencil_bits_array[4] = { 0, 0, 0, 8 };
+
+ depth_buffer_factor = 4;
+ back_buffer_factor = (have_back_buffer) ? 3 : 1;
+
+ num_modes = ((pixel_bits==16) ? 1 : 2) *
+ depth_buffer_factor * back_buffer_factor * 4;
+ modes = (*dri_interface->createContextModes)(num_modes,
+ sizeof(__GLcontextModes));
+ m = modes;
+
+ for (i=((pixel_bits==16)?0:1);i<((pixel_bits==16)?1:3);i++) {
+ if (!driFillInModes(&m, fb_format_array[i].format,
+ fb_format_array[i].type,
+ depth_bits_array,
+ stencil_bits_array,
+ depth_buffer_factor,
+ back_buffer_modes,
+ back_buffer_factor,
+ GLX_TRUE_COLOR)) {
+ fprintf( stderr, "[%s:%u] Error creating FBConfig!\n",
+ __func__, __LINE__ );
+ return NULL;
+ }
+
+ if (!driFillInModes(&m, fb_format_array[i].format,
+ fb_format_array[i].type,
+ depth_bits_array,
+ stencil_bits_array,
+ depth_buffer_factor,
+ back_buffer_modes,
+ back_buffer_factor,
+ GLX_DIRECT_COLOR)) {
+ fprintf( stderr, "[%s:%u] Error creating FBConfig!\n",
+ __func__, __LINE__ );
+ return NULL;
+ }
+ }
+
+ return modes;
+}
+
+
+/**
+ * This is the bootstrap function for the driver. libGL supplies all of the
+ * requisite information about the system, and the driver initializes itself.
+ * This routine also fills in the linked list pointed to by \c driver_modes
+ * with the \c __GLcontextModes that the driver can support for windows or
+ * pbuffers.
+ *
+ * \return A pointer to a \c __DRIscreenPrivate on success, or \c NULL on
+ * failure.
+ */
+PUBLIC
+void * __driCreateNewScreen_20050727( __DRInativeDisplay *dpy, int scrn, __DRIscreen *psc,
+ const __GLcontextModes * modes,
+ const __DRIversion * ddx_version,
+ const __DRIversion * dri_version,
+ const __DRIversion * drm_version,
+ const __DRIframebuffer * frame_buffer,
+ drmAddress pSAREA, int fd,
+ int internal_api_version,
+ const __DRIinterfaceMethods * interface,
+ __GLcontextModes ** driver_modes)
+
+{
+ __DRIscreenPrivate *psp;
+ static const __DRIversion ddx_expected = { 1, 2, 0 };
+ static const __DRIversion dri_expected = { 4, 0, 0 };
+ static const __DRIversion drm_expected = { 0, 0, 2 };
+
+ dri_interface = interface;
+
+ if (!driCheckDriDdxDrmVersions2("nouveau",
+ dri_version, & dri_expected,
+ ddx_version, & ddx_expected,
+ drm_version, & drm_expected)) {
+ return NULL;
+ }
+
+ // temporary lock step versioning
+ if (drm_expected.patch!=drm_version->patch)
+ return NULL;
+
+ psp = __driUtilCreateNewScreen(dpy, scrn, psc, NULL,
+ ddx_version, dri_version, drm_version,
+ frame_buffer, pSAREA, fd,
+ internal_api_version, &nouveauAPI);
+ if ( psp != NULL ) {
+ NOUVEAUDRIPtr dri_priv = (NOUVEAUDRIPtr)psp->pDevPriv;
+
+ *driver_modes = nouveauFillInModes(dri_priv->bpp,
+ (dri_priv->bpp == 16) ? 16 : 24,
+ (dri_priv->bpp == 16) ? 0 : 8,
+ 1
+ );
+
+ /* Calling driInitExtensions here, with a NULL context pointer, does not actually
+ * enable the extensions. It just makes sure that all the dispatch offsets for all
+ * the extensions that *might* be enables are known. This is needed because the
+ * dispatch offsets need to be known when _mesa_context_create is called, but we can't
+ * enable the extensions until we have a context pointer.
+ *
+ * Hello chicken. Hello egg. How are you two today?
+ */
+ driInitExtensions( NULL, common_extensions, GL_FALSE );
+ driInitExtensions( NULL, nv10_extensions, GL_FALSE );
+ driInitExtensions( NULL, nv10_extensions, GL_FALSE );
+ driInitExtensions( NULL, nv30_extensions, GL_FALSE );
+ driInitExtensions( NULL, nv40_extensions, GL_FALSE );
+ driInitExtensions( NULL, nv50_extensions, GL_FALSE );
+ }
+
+ return (void *) psp;
+}
+
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_screen.h b/src/mesa/drivers/dri/nouveau/nouveau_screen.h
new file mode 100644
index 0000000000..decdafa86d
--- /dev/null
+++ b/src/mesa/drivers/dri/nouveau/nouveau_screen.h
@@ -0,0 +1,61 @@
+/**************************************************************************
+
+Copyright 2006 Stephane Marchesin
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+
+#ifndef __NOUVEAU_SCREEN_H__
+#define __NOUVEAU_SCREEN_H__
+
+#include "xmlconfig.h"
+
+#include "nouveau_dri.h"
+#include "nouveau_card.h"
+
+typedef struct {
+ nouveau_card* card;
+ u_int32_t bus_type;
+ u_int32_t agp_mode;
+
+ GLint fbFormat;
+
+ GLuint frontOffset;
+ GLuint frontPitch;
+ GLuint backOffset;
+ GLuint backPitch;
+
+ GLuint depthOffset;
+ GLuint depthPitch;
+ GLuint spanOffset;
+
+ __DRIscreenPrivate *driScreen;
+ unsigned int sarea_priv_offset;
+
+ /* Configuration cache with default values for all contexts */
+ driOptionCache optionCache;
+
+} nouveauScreenRec, *nouveauScreenPtr;
+
+
+#endif /* __NOUVEAU_SCREEN_H__ */
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_shader.c b/src/mesa/drivers/dri/nouveau/nouveau_shader.c
new file mode 100644
index 0000000000..dc366b36c0
--- /dev/null
+++ b/src/mesa/drivers/dri/nouveau/nouveau_shader.c
@@ -0,0 +1,798 @@
+/*
+ * Copyright (C) 2006 Ben Skeggs.
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+/*
+ * Authors:
+ * Ben Skeggs <darktama@iinet.net.au>
+ */
+
+#include "glheader.h"
+#include "macros.h"
+#include "enums.h"
+#include "extensions.h"
+
+#include "program.h"
+#include "tnl/tnl.h"
+#include "shader/arbprogparse.h"
+
+#include "nouveau_context.h"
+#include "nouveau_shader.h"
+
+/*****************************************************************************
+ * Mesa entry points
+ */
+static void
+nouveauBindProgram(GLcontext *ctx, GLenum target, struct gl_program *prog)
+{
+}
+
+static struct gl_program *
+nouveauNewProgram(GLcontext *ctx, GLenum target, GLuint id)
+{
+ nouveauShader *nvs;
+
+ nvs = CALLOC_STRUCT(_nouveauShader);
+ switch (target) {
+ case GL_VERTEX_PROGRAM_ARB:
+ return _mesa_init_vertex_program(ctx, &nvs->mesa.vp, target, id);
+ case GL_FRAGMENT_PROGRAM_ARB:
+ return _mesa_init_fragment_program(ctx, &nvs->mesa.fp, target, id);
+ default:
+ _mesa_problem(ctx, "Unsupported shader target");
+ break;
+ }
+
+ FREE(nvs);
+ return NULL;
+}
+
+static void
+nouveauDeleteProgram(GLcontext *ctx, struct gl_program *prog)
+{
+ nouveauShader *nvs = (nouveauShader *)prog;
+
+ if (nvs->translated)
+ FREE(nvs->program);
+ _mesa_delete_program(ctx, prog);
+}
+
+static void
+nouveauProgramStringNotify(GLcontext *ctx, GLenum target,
+ struct gl_program *prog)
+{
+ nouveauShader *nvs = (nouveauShader *)prog;
+
+ if (nvs->translated)
+ FREE(nvs->program);
+ nvs->translated = 0;
+
+ _tnl_program_string(ctx, target, prog);
+}
+
+static GLboolean
+nouveauIsProgramNative(GLcontext * ctx, GLenum target, struct gl_program *prog)
+{
+ nouveauShader *nvs = (nouveauShader *)prog;
+
+ return nvs->translated;
+}
+
+GLboolean
+nvsUpdateShader(GLcontext *ctx, nouveauShader *nvs)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ struct gl_program_parameter_list *plist;
+ int i;
+
+ /* Translate to HW format now if necessary */
+ if (!nvs->translated) {
+ /* Mesa ASM shader -> nouveauShader */
+ if (!nouveau_shader_pass0_arb(ctx, nvs))
+ return GL_FALSE;
+ /* Basic dead code elimination + register usage info */
+ if (!nouveau_shader_pass1(nvs))
+ return GL_FALSE;
+ /* nouveauShader -> HW bytecode, HW register alloc */
+ if (!nouveau_shader_pass2(nvs))
+ return GL_FALSE;
+ assert(nvs->translated);
+ assert(nvs->program);
+ }
+
+ /* Update state parameters */
+ plist = nvs->mesa.vp.Base.Parameters;
+ _mesa_load_state_parameters(ctx, plist);
+ for (i=0; i<plist->NumParameters; i++) {
+ if (!nvs->on_hardware) {
+ /* if we've been kicked off the hardware there's no guarantee our
+ * consts are still there.. reupload them all
+ */
+ nvs->func->UpdateConst(ctx, nvs, i);
+ } else if (plist->Parameters[i].Type == PROGRAM_STATE_VAR) {
+ if (!nvs->params[i].source_val) /* this is a workaround when consts aren't alloc'd from id=0.. */
+ continue;
+ /* update any changed state parameters */
+ if (!TEST_EQ_4V(nvs->params[i].val, nvs->params[i].source_val))
+ nvs->func->UpdateConst(ctx, nvs, i);
+ }
+ }
+
+ /* Upload program to hardware, this must come after state param update
+ * as >=NV30 fragprogs inline consts into the bytecode.
+ */
+ if (!nvs->on_hardware) {
+ nouveauShader **current;
+
+ if (nvs->mesa.vp.Base.Target == GL_VERTEX_PROGRAM_ARB)
+ current = &nmesa->current_vertprog;
+ else
+ current = &nmesa->current_fragprog;
+ if (*current) (*current)->on_hardware = 0;
+
+ nvs->func->UploadToHW(ctx, nvs);
+ nvs->on_hardware = 1;
+
+ *current = nvs;
+ }
+
+ return GL_TRUE;
+}
+
+nouveauShader *
+nvsBuildTextShader(GLcontext *ctx, GLenum target, const char *text)
+{
+ nouveauShader *nvs;
+
+ nvs = CALLOC_STRUCT(_nouveauShader);
+ if (!nvs)
+ return NULL;
+
+ if (target == GL_VERTEX_PROGRAM_ARB) {
+ _mesa_init_vertex_program(ctx, &nvs->mesa.vp, GL_VERTEX_PROGRAM_ARB, 0);
+ _mesa_parse_arb_vertex_program(ctx,
+ GL_VERTEX_PROGRAM_ARB,
+ text,
+ strlen(text),
+ &nvs->mesa.vp);
+ } else if (target == GL_FRAGMENT_PROGRAM_ARB) {
+ _mesa_init_fragment_program(ctx, &nvs->mesa.fp, GL_VERTEX_PROGRAM_ARB, 0);
+ _mesa_parse_arb_fragment_program(ctx,
+ GL_FRAGMENT_PROGRAM_ARB,
+ text,
+ strlen(text),
+ &nvs->mesa.fp);
+ }
+
+ nouveau_shader_pass0_arb(ctx, nvs);
+ nouveau_shader_pass1(nvs);
+ nouveau_shader_pass2(nvs);
+
+ return nvs;
+}
+
+static void
+nvsBuildPassthroughVP(GLcontext *ctx)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+
+ const char *vp_text =
+ "!!ARBvp1.0\n"
+ "OPTION ARB_position_invariant;"
+ ""
+ "MOV result.color, vertex.color;\n"
+ "MOV result.texcoord[0], vertex.texcoord[0];\n"
+ "MOV result.texcoord[1], vertex.texcoord[1];\n"
+ "MOV result.texcoord[2], vertex.texcoord[2];\n"
+ "MOV result.texcoord[3], vertex.texcoord[3];\n"
+ "MOV result.texcoord[4], vertex.texcoord[4];\n"
+ "MOV result.texcoord[5], vertex.texcoord[5];\n"
+ "MOV result.texcoord[6], vertex.texcoord[6];\n"
+ "MOV result.texcoord[7], vertex.texcoord[7];\n"
+ "END";
+
+ nmesa->passthrough_vp = nvsBuildTextShader(ctx,
+ GL_VERTEX_PROGRAM_ARB,
+ vp_text);
+}
+
+void
+nouveauShaderInitFuncs(GLcontext * ctx)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+
+ switch (nmesa->screen->card->type) {
+ case NV_20:
+ NV20VPInitShaderFuncs(&nmesa->VPfunc);
+ break;
+ case NV_30:
+ NV30VPInitShaderFuncs(&nmesa->VPfunc);
+ NV30FPInitShaderFuncs(&nmesa->FPfunc);
+ break;
+ case NV_40:
+ case NV_44:
+ NV40VPInitShaderFuncs(&nmesa->VPfunc);
+ NV40FPInitShaderFuncs(&nmesa->FPfunc);
+ break;
+ case NV_50:
+ default:
+ return;
+ }
+
+ /* Build a vertex program that simply passes through all attribs.
+ * Needed to do swtcl on nv40
+ */
+ if (nmesa->screen->card->type >= NV_40)
+ nvsBuildPassthroughVP(ctx);
+
+ ctx->Const.VertexProgram.MaxNativeInstructions = nmesa->VPfunc.MaxInst;
+ ctx->Const.VertexProgram.MaxNativeAluInstructions = nmesa->VPfunc.MaxInst;
+ ctx->Const.VertexProgram.MaxNativeTexInstructions = nmesa->VPfunc.MaxInst;
+ ctx->Const.VertexProgram.MaxNativeTexIndirections =
+ ctx->Const.VertexProgram.MaxNativeTexInstructions;
+ ctx->Const.VertexProgram.MaxNativeAttribs = nmesa->VPfunc.MaxAttrib;
+ ctx->Const.VertexProgram.MaxNativeTemps = nmesa->VPfunc.MaxTemp;
+ ctx->Const.VertexProgram.MaxNativeAddressRegs = nmesa->VPfunc.MaxAddress;
+ ctx->Const.VertexProgram.MaxNativeParameters = nmesa->VPfunc.MaxConst;
+
+ if (nmesa->screen->card->type >= NV_30) {
+ ctx->Const.FragmentProgram.MaxNativeInstructions = nmesa->FPfunc.MaxInst;
+ ctx->Const.FragmentProgram.MaxNativeAluInstructions = nmesa->FPfunc.MaxInst;
+ ctx->Const.FragmentProgram.MaxNativeTexInstructions = nmesa->FPfunc.MaxInst;
+ ctx->Const.FragmentProgram.MaxNativeTexIndirections =
+ ctx->Const.FragmentProgram.MaxNativeTexInstructions;
+ ctx->Const.FragmentProgram.MaxNativeAttribs = nmesa->FPfunc.MaxAttrib;
+ ctx->Const.FragmentProgram.MaxNativeTemps = nmesa->FPfunc.MaxTemp;
+ ctx->Const.FragmentProgram.MaxNativeAddressRegs = nmesa->FPfunc.MaxAddress;
+ ctx->Const.FragmentProgram.MaxNativeParameters = nmesa->FPfunc.MaxConst;
+ }
+
+ ctx->Driver.NewProgram = nouveauNewProgram;
+ ctx->Driver.BindProgram = nouveauBindProgram;
+ ctx->Driver.DeleteProgram = nouveauDeleteProgram;
+ ctx->Driver.ProgramStringNotify = nouveauProgramStringNotify;
+ ctx->Driver.IsProgramNative = nouveauIsProgramNative;
+}
+
+
+/*****************************************************************************
+ * Disassembly support structs
+ */
+#define CHECK_RANGE(idx, arr) ((idx)<sizeof(_##arr)/sizeof(const char *)) \
+ ? _##arr[(idx)] : #arr"_OOB"
+
+#define NODS (1<<0)
+#define BRANCH_TR (1<<1)
+#define BRANCH_EL (1<<2)
+#define BRANCH_EN (1<<3)
+#define BRANCH_RE (1<<4)
+#define BRANCH_ALL (BRANCH_TR|BRANCH_EL|BRANCH_EN)
+#define COUNT_INC (1<<4)
+#define COUNT_IND (1<<5)
+#define COUNT_NUM (1<<6)
+#define COUNT_ALL (COUNT_INC|COUNT_IND|COUNT_NUM)
+#define TI_UNIT (1<<7)
+struct _opcode_info
+{
+ const char *name;
+ int numsrc;
+ int flags;
+};
+
+static struct _opcode_info ops[] = {
+ [NVS_OP_ABS] = {"ABS", 1, 0},
+ [NVS_OP_ADD] = {"ADD", 2, 0},
+ [NVS_OP_ARA] = {"ARA", 1, 0},
+ [NVS_OP_ARL] = {"ARL", 1, 0},
+ [NVS_OP_ARR] = {"ARR", 1, 0},
+ [NVS_OP_BRA] = {"BRA", 0, NODS | BRANCH_TR},
+ [NVS_OP_BRK] = {"BRK", 0, NODS},
+ [NVS_OP_CAL] = {"CAL", 0, NODS | BRANCH_TR},
+ [NVS_OP_CMP] = {"CMP", 2, 0},
+ [NVS_OP_COS] = {"COS", 1, 0},
+ [NVS_OP_DIV] = {"DIV", 2, 0},
+ [NVS_OP_DDX] = {"DDX", 1, 0},
+ [NVS_OP_DDY] = {"DDY", 1, 0},
+ [NVS_OP_DP2] = {"DP2", 2, 0},
+ [NVS_OP_DP2A] = {"DP2A", 3, 0},
+ [NVS_OP_DP3] = {"DP3", 2, 0},
+ [NVS_OP_DP4] = {"DP4", 2, 0},
+ [NVS_OP_DPH] = {"DPH", 2, 0},
+ [NVS_OP_DST] = {"DST", 2, 0},
+ [NVS_OP_EX2] = {"EX2", 1, 0},
+ [NVS_OP_EXP] = {"EXP", 1, 0},
+ [NVS_OP_FLR] = {"FLR", 1, 0},
+ [NVS_OP_FRC] = {"FRC", 1, 0},
+ [NVS_OP_IF] = {"IF", 0, NODS | BRANCH_EL | BRANCH_EN},
+ [NVS_OP_KIL] = {"KIL", 1, 0},
+ [NVS_OP_LG2] = {"LG2", 1, 0},
+ [NVS_OP_LIT] = {"LIT", 1, 0},
+ [NVS_OP_LOG] = {"LOG", 1, 0},
+ [NVS_OP_LOOP] = {"LOOP", 0, NODS | COUNT_ALL | BRANCH_EN},
+ [NVS_OP_LRP] = {"LRP", 3, 0},
+ [NVS_OP_MAD] = {"MAD", 3, 0},
+ [NVS_OP_MAX] = {"MAX", 2, 0},
+ [NVS_OP_MIN] = {"MIN", 2, 0},
+ [NVS_OP_MOV] = {"MOV", 1, 0},
+ [NVS_OP_MUL] = {"MUL", 2, 0},
+ [NVS_OP_NRM] = {"NRM", 1, 0},
+ [NVS_OP_PK2H] = {"PK2H", 1, 0},
+ [NVS_OP_PK2US] = {"PK2US", 1, 0},
+ [NVS_OP_PK4B] = {"PK4B", 1, 0},
+ [NVS_OP_PK4UB] = {"PK4UB", 1, 0},
+ [NVS_OP_POW] = {"POW", 2, 0},
+ [NVS_OP_POPA] = {"POPA", 0, 0},
+ [NVS_OP_PUSHA] = {"PUSHA", 1, NODS},
+ [NVS_OP_RCC] = {"RCC", 1, 0},
+ [NVS_OP_RCP] = {"RCP", 1, 0},
+ [NVS_OP_REP] = {"REP", 0, NODS | BRANCH_EN | COUNT_NUM},
+ [NVS_OP_RET] = {"RET", 0, NODS},
+ [NVS_OP_RFL] = {"RFL", 1, 0},
+ [NVS_OP_RSQ] = {"RSQ", 1, 0},
+ [NVS_OP_SCS] = {"SCS", 1, 0},
+ [NVS_OP_SEQ] = {"SEQ", 2, 0},
+ [NVS_OP_SFL] = {"SFL", 2, 0},
+ [NVS_OP_SGE] = {"SGE", 2, 0},
+ [NVS_OP_SGT] = {"SGT", 2, 0},
+ [NVS_OP_SIN] = {"SIN", 1, 0},
+ [NVS_OP_SLE] = {"SLE", 2, 0},
+ [NVS_OP_SLT] = {"SLT", 2, 0},
+ [NVS_OP_SNE] = {"SNE", 2, 0},
+ [NVS_OP_SSG] = {"SSG", 1, 0},
+ [NVS_OP_STR] = {"STR", 2, 0},
+ [NVS_OP_SUB] = {"SUB", 2, 0},
+ [NVS_OP_TEX] = {"TEX", 1, TI_UNIT},
+ [NVS_OP_TXB] = {"TXB", 1, TI_UNIT},
+ [NVS_OP_TXD] = {"TXD", 3, TI_UNIT},
+ [NVS_OP_TXL] = {"TXL", 1, TI_UNIT},
+ [NVS_OP_TXP] = {"TXP", 1, TI_UNIT},
+ [NVS_OP_UP2H] = {"UP2H", 1, 0},
+ [NVS_OP_UP2US] = {"UP2US", 1, 0},
+ [NVS_OP_UP4B] = {"UP4B", 1, 0},
+ [NVS_OP_UP4UB] = {"UP4UB", 1, 0},
+ [NVS_OP_X2D] = {"X2D", 3, 0},
+ [NVS_OP_XPD] = {"XPD", 2, 0},
+ [NVS_OP_NOP] = {"NOP", 0, NODS},
+};
+
+static struct _opcode_info *
+_get_op_info(int op)
+{
+ if (op >= (sizeof(ops) / sizeof(struct _opcode_info)))
+ return NULL;
+ if (ops[op].name == NULL)
+ return NULL;
+ return &ops[op];
+}
+
+static const char *_SFR_STRING[] = {
+ [NVS_FR_POSITION] = "position",
+ [NVS_FR_WEIGHT] = "weight",
+ [NVS_FR_NORMAL] = "normal",
+ [NVS_FR_COL0] = "color",
+ [NVS_FR_COL1] = "color.secondary",
+ [NVS_FR_BFC0] = "bfc",
+ [NVS_FR_BFC1] = "bfc.secondary",
+ [NVS_FR_FOGCOORD] = "fogcoord",
+ [NVS_FR_POINTSZ] = "pointsize",
+ [NVS_FR_TEXCOORD0] = "texcoord[0]",
+ [NVS_FR_TEXCOORD1] = "texcoord[1]",
+ [NVS_FR_TEXCOORD2] = "texcoord[2]",
+ [NVS_FR_TEXCOORD3] = "texcoord[3]",
+ [NVS_FR_TEXCOORD4] = "texcoord[4]",
+ [NVS_FR_TEXCOORD5] = "texcoord[5]",
+ [NVS_FR_TEXCOORD6] = "texcoord[6]",
+ [NVS_FR_TEXCOORD7] = "texcoord[7]",
+ [NVS_FR_FRAGDATA0] = "data[0]",
+ [NVS_FR_FRAGDATA1] = "data[1]",
+ [NVS_FR_FRAGDATA2] = "data[2]",
+ [NVS_FR_FRAGDATA3] = "data[3]",
+ [NVS_FR_CLIP0] = "clip_plane[0]",
+ [NVS_FR_CLIP1] = "clip_plane[1]",
+ [NVS_FR_CLIP2] = "clip_plane[2]",
+ [NVS_FR_CLIP3] = "clip_plane[3]",
+ [NVS_FR_CLIP4] = "clip_plane[4]",
+ [NVS_FR_CLIP5] = "clip_plane[5]",
+ [NVS_FR_CLIP6] = "clip_plane[6]",
+ [NVS_FR_FACING] = "facing",
+};
+
+#define SFR_STRING(idx) CHECK_RANGE((idx), SFR_STRING)
+
+static const char *_SWZ_STRING[] = {
+ [NVS_SWZ_X] = "x",
+ [NVS_SWZ_Y] = "y",
+ [NVS_SWZ_Z] = "z",
+ [NVS_SWZ_W] = "w"
+};
+
+#define SWZ_STRING(idx) CHECK_RANGE((idx), SWZ_STRING)
+
+static const char *_NVS_PREC_STRING[] = {
+ [NVS_PREC_FLOAT32] = "R",
+ [NVS_PREC_FLOAT16] = "H",
+ [NVS_PREC_FIXED12] = "X",
+ [NVS_PREC_UNKNOWN] = "?"
+};
+
+#define NVS_PREC_STRING(idx) CHECK_RANGE((idx), NVS_PREC_STRING)
+
+static const char *_NVS_COND_STRING[] = {
+ [NVS_COND_FL] = "FL",
+ [NVS_COND_LT] = "LT",
+ [NVS_COND_EQ] = "EQ",
+ [NVS_COND_LE] = "LE",
+ [NVS_COND_GT] = "GT",
+ [NVS_COND_NE] = "NE",
+ [NVS_COND_GE] = "GE",
+ [NVS_COND_TR] = "TR",
+ [NVS_COND_UNKNOWN] = "??"
+};
+
+#define NVS_COND_STRING(idx) CHECK_RANGE((idx), NVS_COND_STRING)
+
+/*****************************************************************************
+ * ShaderFragment dumping
+ */
+static void
+nvsDumpIndent(int lvl)
+{
+ while (lvl--)
+ printf(" ");
+}
+
+static void
+nvsDumpSwizzle(nvsSwzComp *swz)
+{
+ printf(".%s%s%s%s",
+ SWZ_STRING(swz[0]),
+ SWZ_STRING(swz[1]), SWZ_STRING(swz[2]), SWZ_STRING(swz[3])
+ );
+}
+
+static void
+nvsDumpReg(nvsInstruction * inst, nvsRegister * reg)
+{
+ if (reg->negate)
+ printf("-");
+ if (reg->abs)
+ printf("abs(");
+
+ switch (reg->file) {
+ case NVS_FILE_TEMP:
+ printf("R%d", reg->index);
+ nvsDumpSwizzle(reg->swizzle);
+ break;
+ case NVS_FILE_ATTRIB:
+ printf("attrib.%s", SFR_STRING(reg->index));
+ nvsDumpSwizzle(reg->swizzle);
+ break;
+ case NVS_FILE_ADDRESS:
+ printf("A%d", reg->index);
+ break;
+ case NVS_FILE_CONST:
+ if (reg->indexed)
+ printf("const[A%d.%s + %d]",
+ reg->addr_reg, SWZ_STRING(reg->addr_comp), reg->index);
+ else
+ printf("const[%d]", reg->index);
+ nvsDumpSwizzle(reg->swizzle);
+ break;
+ default:
+ printf("UNKNOWN_FILE");
+ break;
+ }
+
+ if (reg->abs)
+ printf(")");
+}
+
+static void
+nvsDumpInstruction(nvsInstruction * inst, int slot, int lvl)
+{
+ struct _opcode_info *opr = &ops[inst->op];
+ int i;
+
+ nvsDumpIndent(lvl);
+ printf("%s ", opr->name);
+
+ if (!opr->flags & NODS) {
+ switch (inst->dest.file) {
+ case NVS_FILE_RESULT:
+ printf("result.%s", SFR_STRING(inst->dest.index));
+ break;
+ case NVS_FILE_TEMP:
+ printf("R%d", inst->dest.index);
+ break;
+ case NVS_FILE_ADDRESS:
+ printf("A%d", inst->dest.index);
+ break;
+ default:
+ printf("UNKNOWN_DST_FILE");
+ break;
+ }
+
+ if (inst->mask != SMASK_ALL) {
+ printf(".");
+ if (inst->mask & SMASK_X)
+ printf("x");
+ if (inst->mask & SMASK_Y)
+ printf("y");
+ if (inst->mask & SMASK_Z)
+ printf("z");
+ if (inst->mask & SMASK_W)
+ printf("w");
+ }
+
+ if (opr->numsrc)
+ printf(", ");
+ }
+
+ for (i = 0; i < opr->numsrc; i++) {
+ nvsDumpReg(inst, &inst->src[i]);
+ if (i != opr->numsrc - 1)
+ printf(", ");
+ }
+ if (opr->flags & TI_UNIT)
+ printf(", texture[%d]", inst->tex_unit);
+
+ printf("\n");
+}
+
+void
+nvsDumpFragmentList(nvsFragmentList *f, int lvl)
+{
+ while (f) {
+ switch (f->fragment->type) {
+ case NVS_INSTRUCTION:
+ nvsDumpInstruction((nvsInstruction*)f->fragment, 0, lvl);
+ break;
+ default:
+ fprintf(stderr, "%s: Only NVS_INSTRUCTION fragments can be in"
+ "nvsFragmentList!\n", __func__);
+ return;
+ }
+ f = f->next;
+ }
+}
+
+/*****************************************************************************
+ * HW shader disassembly
+ */
+static void
+nvsDisasmHWShaderOp(nvsFunc * shader, int merged)
+{
+ struct _opcode_info *opi;
+ nvsOpcode op;
+ nvsRegFile file;
+ nvsSwzComp swz[4];
+ int i;
+
+ op = shader->GetOpcode(shader, merged);
+ opi = _get_op_info(op);
+ if (!opi) {
+ printf("NO OPINFO!");
+ return;
+ }
+
+ printf("%s", opi->name);
+ if (shader->GetPrecision &&
+ (!(opi->flags & BRANCH_ALL)) && (!(opi->flags * NODS)) &&
+ (op != NVS_OP_NOP))
+ printf("%s", NVS_PREC_STRING(shader->GetPrecision(shader)));
+ if (shader->SupportsConditional && shader->SupportsConditional(shader)) {
+ if (shader->GetConditionUpdate(shader)) {
+ printf("C%d", shader->GetCondRegID(shader));
+ }
+ }
+ if (shader->GetSaturate && shader->GetSaturate(shader))
+ printf("_SAT");
+
+ if (!(opi->flags & NODS)) {
+ int mask = shader->GetDestMask(shader, merged);
+
+ switch (shader->GetDestFile(shader, merged)) {
+ case NVS_FILE_ADDRESS:
+ printf(" A%d", shader->GetDestID(shader, merged));
+ break;
+ case NVS_FILE_TEMP:
+ printf(" R%d", shader->GetDestID(shader, merged));
+ break;
+ case NVS_FILE_RESULT:
+ printf(" result.%s", (SFR_STRING(shader->GetDestID(shader, merged))));
+ break;
+ default:
+ printf(" BAD_RESULT_FILE");
+ break;
+ }
+
+ if (mask != SMASK_ALL) {
+ printf(".");
+ if (mask & SMASK_X) printf("x");
+ if (mask & SMASK_Y) printf("y");
+ if (mask & SMASK_Z) printf("z");
+ if (mask & SMASK_W) printf("w");
+ }
+ }
+
+ if (shader->SupportsConditional && shader->SupportsConditional(shader) &&
+ shader->GetConditionTest(shader)) {
+ shader->GetCondRegSwizzle(shader, swz);
+
+ printf(" (%s%d.%s%s%s%s)",
+ NVS_COND_STRING(shader->GetCondition(shader)),
+ shader->GetCondRegID(shader),
+ SWZ_STRING(swz[NVS_SWZ_X]),
+ SWZ_STRING(swz[NVS_SWZ_Y]),
+ SWZ_STRING(swz[NVS_SWZ_Z]),
+ SWZ_STRING(swz[NVS_SWZ_W])
+ );
+ }
+
+ /* looping */
+ if (opi->flags & COUNT_ALL) {
+ printf(" { ");
+ if (opi->flags & COUNT_NUM) {
+ printf("%d", shader->GetLoopCount(shader));
+ }
+ if (opi->flags & COUNT_IND) {
+ printf(", %d", shader->GetLoopInitial(shader));
+ }
+ if (opi->flags & COUNT_INC) {
+ printf(", %d", shader->GetLoopIncrement(shader));
+ }
+ printf(" }");
+ }
+
+ /* branching */
+ if (opi->flags & BRANCH_TR)
+ printf(" %d", shader->GetBranch(shader));
+ if (opi->flags & BRANCH_EL)
+ printf(" ELSE %d", shader->GetBranchElse(shader));
+ if (opi->flags & BRANCH_EN)
+ printf(" END %d", shader->GetBranchEnd(shader));
+
+ if (!(opi->flags & NODS) && opi->numsrc)
+ printf(",");
+ printf(" ");
+
+ for (i = 0; i < opi->numsrc; i++) {
+ if (shader->GetSourceAbs(shader, merged, i))
+ printf("abs(");
+ if (shader->GetSourceNegate(shader, merged, i))
+ printf("-");
+
+ file = shader->GetSourceFile(shader, merged, i);
+ switch (file) {
+ case NVS_FILE_TEMP:
+ printf("R%d", shader->GetSourceID(shader, merged, i));
+ break;
+ case NVS_FILE_CONST:
+ if (shader->GetSourceIndexed(shader, merged, i)) {
+ printf("c[A%d.%s + 0x%x]",
+ shader->GetRelAddressRegID(shader),
+ SWZ_STRING(shader->GetRelAddressSwizzle(shader)),
+ shader->GetSourceID(shader, merged, i)
+ );
+ } else {
+ float val[4];
+
+ if (shader->GetSourceConstVal) {
+ shader->GetSourceConstVal(shader, merged, i, val);
+ printf("{ %.02f, %.02f, %.02f, %.02f }",
+ val[0], val[1], val[2], val[3]);
+ } else {
+ printf("c[0x%x]", shader->GetSourceID(shader, merged, i));
+ }
+ }
+ break;
+ case NVS_FILE_ATTRIB:
+ if (shader->GetSourceIndexed(shader, merged, i)) {
+ printf("attrib[A%d.%s + %d]",
+ shader->GetRelAddressRegID(shader),
+ SWZ_STRING(shader->GetRelAddressSwizzle(shader)),
+ shader->GetSourceID(shader, merged, i)
+ );
+ }
+ else {
+ printf("attrib.%s",
+ SFR_STRING(shader->GetSourceID(shader, merged, i))
+ );
+ }
+ break;
+ case NVS_FILE_ADDRESS:
+ printf("A%d", shader->GetRelAddressRegID(shader));
+ break;
+ default:
+ printf("UNKNOWN_SRC_FILE");
+ break;
+ }
+
+ shader->GetSourceSwizzle(shader, merged, i, swz);
+ if (file != NVS_FILE_ADDRESS &&
+ (swz[NVS_SWZ_X] != NVS_SWZ_X || swz[NVS_SWZ_Y] != NVS_SWZ_Y ||
+ swz[NVS_SWZ_Z] != NVS_SWZ_Z || swz[NVS_SWZ_W] != NVS_SWZ_W)) {
+ printf(".%s%s%s%s", SWZ_STRING(swz[NVS_SWZ_X]),
+ SWZ_STRING(swz[NVS_SWZ_Y]),
+ SWZ_STRING(swz[NVS_SWZ_Z]),
+ SWZ_STRING(swz[NVS_SWZ_W]));
+ }
+
+ if (shader->GetSourceAbs(shader, merged, i))
+ printf(")");
+ if (shader->GetSourceScale) {
+ int scale = shader->GetSourceScale(shader, merged, i);
+ if (scale > 1)
+ printf("{scaled %dx}", scale);
+ }
+ if (i < (opi->numsrc - 1))
+ printf(", ");
+ }
+
+ if (shader->IsLastInst(shader))
+ printf(" + END");
+}
+
+void
+nvsDisasmHWShader(nvsPtr nvs)
+{
+ nvsFunc *shader = nvs->func;
+ unsigned int iaddr = 0;
+
+ if (!nvs->program) {
+ fprintf(stderr, "No HW program present");
+ return;
+ }
+
+ shader->inst = nvs->program;
+ while (1) {
+ if (shader->inst >= (nvs->program + nvs->program_size)) {
+ fprintf(stderr, "Reached end of program, but HW inst has no END");
+ break;
+ }
+
+ printf("\t0x%08x:\n", shader->inst[0]);
+ printf("\t0x%08x:\n", shader->inst[1]);
+ printf("\t0x%08x:\n", shader->inst[2]);
+ printf("\t0x%08x:", shader->inst[3]);
+
+ printf("\n\t\tINST %d.0: ", iaddr);
+ nvsDisasmHWShaderOp(shader, 0);
+ if (shader->HasMergedInst(shader)) {
+ printf("\n\t\tINST %d.1: ", iaddr);
+ nvsDisasmHWShaderOp(shader, 1);
+ }
+ printf("\n");
+
+ if (shader->IsLastInst(shader))
+ break;
+
+ shader->inst += shader->GetOffsetNext(shader);
+ iaddr++;
+ }
+
+ printf("\n");
+}
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_shader.h b/src/mesa/drivers/dri/nouveau/nouveau_shader.h
new file mode 100644
index 0000000000..08cb7817cf
--- /dev/null
+++ b/src/mesa/drivers/dri/nouveau/nouveau_shader.h
@@ -0,0 +1,374 @@
+#ifndef __SHADER_COMMON_H__
+#define __SHADER_COMMON_H__
+
+#include "mtypes.h"
+#include "bufferobj.h"
+
+typedef struct _nvsFunc nvsFunc;
+
+#define NVS_MAX_TEMPS 32
+#define NVS_MAX_ATTRIBS 16
+#define NVS_MAX_CONSTS 256
+#define NVS_MAX_ADDRESS 2
+#define NVS_MAX_INSNS 4096
+
+typedef struct {
+ enum {
+ NVS_INSTRUCTION,
+ } type;
+ int position;
+} nvsFragmentHeader;
+
+typedef struct _nvs_fragment_list {
+ struct _nvs_fragment_list *prev;
+ struct _nvs_fragment_list *next;
+ nvsFragmentHeader *fragment;
+} nvsFragmentList;
+
+typedef struct _nouveauShader {
+ union {
+ struct gl_vertex_program vp;
+ struct gl_fragment_program fp;
+ } mesa;
+ GLcontext *ctx;
+ nvsFunc *func;
+
+ /* State of the final program */
+ GLboolean translated;
+ GLboolean on_hardware;
+ unsigned int *program;
+ unsigned int program_size;
+ unsigned int program_alloc_size;
+ unsigned int program_start_id;
+ unsigned int program_current;
+ struct gl_buffer_object *program_buffer;
+ unsigned int inputs_read;
+ unsigned int outputs_written;
+ int inst_count;
+
+ struct {
+ GLfloat *source_val; /* NULL if invariant */
+ float val[4];
+ /* Hardware-specific tracking, currently only nv30_fragprog
+ * makes use of it.
+ */
+ int *hw_index;
+ int hw_index_cnt;
+ } params[NVS_MAX_CONSTS];
+
+ struct {
+ int last_use;
+ } temps[NVS_MAX_TEMPS];
+
+ /* Pass-private data */
+ void *pass_rec;
+
+ nvsFragmentList *list_head;
+ nvsFragmentList *list_tail;
+} nouveauShader, *nvsPtr;
+
+typedef enum {
+ NVS_FILE_NONE,
+ NVS_FILE_TEMP,
+ NVS_FILE_ATTRIB,
+ NVS_FILE_CONST,
+ NVS_FILE_RESULT,
+ NVS_FILE_ADDRESS,
+ NVS_FILE_UNKNOWN
+} nvsRegFile;
+
+typedef enum {
+ NVS_OP_UNKNOWN = 0,
+ NVS_OP_NOP,
+ NVS_OP_ABS, NVS_OP_ADD, NVS_OP_ARA, NVS_OP_ARL, NVS_OP_ARR,
+ NVS_OP_BRA, NVS_OP_BRK,
+ NVS_OP_CAL, NVS_OP_CMP, NVS_OP_COS,
+ NVS_OP_DDX, NVS_OP_DDY, NVS_OP_DIV, NVS_OP_DP2, NVS_OP_DP2A, NVS_OP_DP3,
+ NVS_OP_DP4, NVS_OP_DPH, NVS_OP_DST,
+ NVS_OP_EX2, NVS_OP_EXP,
+ NVS_OP_FLR, NVS_OP_FRC,
+ NVS_OP_IF,
+ NVS_OP_KIL,
+ NVS_OP_LG2, NVS_OP_LIT, NVS_OP_LOG, NVS_OP_LOOP, NVS_OP_LRP,
+ NVS_OP_MAD, NVS_OP_MAX, NVS_OP_MIN, NVS_OP_MOV, NVS_OP_MUL,
+ NVS_OP_NRM,
+ NVS_OP_PK2H, NVS_OP_PK2US, NVS_OP_PK4B, NVS_OP_PK4UB, NVS_OP_POW,
+ NVS_OP_POPA, NVS_OP_PUSHA,
+ NVS_OP_RCC, NVS_OP_RCP, NVS_OP_REP, NVS_OP_RET, NVS_OP_RFL, NVS_OP_RSQ,
+ NVS_OP_SCS, NVS_OP_SEQ, NVS_OP_SFL, NVS_OP_SGE, NVS_OP_SGT, NVS_OP_SIN,
+ NVS_OP_SLE, NVS_OP_SLT, NVS_OP_SNE, NVS_OP_SSG, NVS_OP_STR, NVS_OP_SUB,
+ NVS_OP_SWZ,
+ NVS_OP_TEX, NVS_OP_TXB, NVS_OP_TXD, NVS_OP_TXL, NVS_OP_TXP,
+ NVS_OP_UP2H, NVS_OP_UP2US, NVS_OP_UP4B, NVS_OP_UP4UB,
+ NVS_OP_X2D, NVS_OP_XPD,
+ NVS_OP_EMUL
+} nvsOpcode;
+
+typedef enum {
+ NVS_PREC_FLOAT32,
+ NVS_PREC_FLOAT16,
+ NVS_PREC_FIXED12,
+ NVS_PREC_UNKNOWN
+} nvsPrecision;
+
+typedef enum {
+ NVS_SWZ_X = 0,
+ NVS_SWZ_Y = 1,
+ NVS_SWZ_Z = 2,
+ NVS_SWZ_W = 3
+} nvsSwzComp;
+
+typedef enum {
+ NVS_FR_POSITION,
+ NVS_FR_WEIGHT,
+ NVS_FR_NORMAL,
+ NVS_FR_COL0,
+ NVS_FR_COL1,
+ NVS_FR_BFC0,
+ NVS_FR_BFC1,
+ NVS_FR_FOGCOORD,
+ NVS_FR_POINTSZ,
+ NVS_FR_TEXCOORD0,
+ NVS_FR_TEXCOORD1,
+ NVS_FR_TEXCOORD2,
+ NVS_FR_TEXCOORD3,
+ NVS_FR_TEXCOORD4,
+ NVS_FR_TEXCOORD5,
+ NVS_FR_TEXCOORD6,
+ NVS_FR_TEXCOORD7,
+ NVS_FR_FRAGDATA0,
+ NVS_FR_FRAGDATA1,
+ NVS_FR_FRAGDATA2,
+ NVS_FR_FRAGDATA3,
+ NVS_FR_CLIP0,
+ NVS_FR_CLIP1,
+ NVS_FR_CLIP2,
+ NVS_FR_CLIP3,
+ NVS_FR_CLIP4,
+ NVS_FR_CLIP5,
+ NVS_FR_CLIP6,
+ NVS_FR_FACING,
+ NVS_FR_UNKNOWN
+} nvsFixedReg;
+
+typedef enum {
+ NVS_COND_FL, NVS_COND_LT, NVS_COND_EQ, NVS_COND_LE, NVS_COND_GT,
+ NVS_COND_NE, NVS_COND_GE, NVS_COND_TR, NVS_COND_UN,
+ NVS_COND_UNKNOWN
+} nvsCond;
+
+typedef struct {
+ nvsRegFile file;
+ unsigned int index;
+
+ unsigned int indexed;
+ unsigned int addr_reg;
+ nvsSwzComp addr_comp;
+
+ nvsSwzComp swizzle[4];
+ int negate;
+ int abs;
+} nvsRegister;
+
+static const nvsRegister nvr_unused = {
+ .file = NVS_FILE_ATTRIB,
+ .index = 0,
+ .indexed = 0,
+ .addr_reg = 0,
+ .addr_comp = NVS_SWZ_X,
+ .swizzle = {NVS_SWZ_X, NVS_SWZ_Y, NVS_SWZ_Z, NVS_SWZ_W},
+ .negate = 0,
+ .abs = 0,
+};
+
+typedef enum {
+ NVS_TEX_TARGET_1D,
+ NVS_TEX_TARGET_2D,
+ NVS_TEX_TARGET_3D,
+ NVS_TEX_TARGET_CUBE,
+ NVS_TEX_TARGET_RECT,
+ NVS_TEX_TARGET_UNKNOWN = 0
+} nvsTexTarget;
+
+typedef struct {
+ nvsFragmentHeader header;
+
+ nvsOpcode op;
+ unsigned int saturate;
+
+ nvsRegister dest;
+ unsigned int mask;
+
+ nvsRegister src[3];
+
+ unsigned int tex_unit;
+ nvsTexTarget tex_target;
+
+ nvsCond cond;
+ nvsSwzComp cond_swizzle[4];
+ int cond_reg;
+ int cond_test;
+ int cond_update;
+} nvsInstruction;
+
+#define SMASK_X (1<<0)
+#define SMASK_Y (1<<1)
+#define SMASK_Z (1<<2)
+#define SMASK_W (1<<3)
+#define SMASK_ALL (SMASK_X|SMASK_Y|SMASK_Z|SMASK_W)
+
+#define SPOS_ADDRESS 3
+struct _op_xlat {
+ unsigned int NV;
+ nvsOpcode SOP;
+ int srcpos[3];
+};
+#define MOD_OPCODE(t,hw,sop,s0,s1,s2) do { \
+ t[hw].NV = hw; \
+ t[hw].SOP = sop; \
+ t[hw].srcpos[0] = s0; \
+ t[hw].srcpos[1] = s1; \
+ t[hw].srcpos[2] = s2; \
+} while(0)
+
+extern unsigned int NVVP_TX_VOP_COUNT;
+extern unsigned int NVVP_TX_NVS_OP_COUNT;
+extern struct _op_xlat NVVP_TX_VOP[];
+extern struct _op_xlat NVVP_TX_SOP[];
+
+extern unsigned int NVFP_TX_AOP_COUNT;
+extern unsigned int NVFP_TX_BOP_COUNT;
+extern struct _op_xlat NVFP_TX_AOP[];
+extern struct _op_xlat NVFP_TX_BOP[];
+
+extern void NV20VPTXSwizzle(int hwswz, nvsSwzComp *swz);
+extern nvsSwzComp NV20VP_TX_SWIZZLE[4];
+
+#define SCAP_SRC_ABS (1<<0)
+
+struct _nvsFunc {
+ unsigned int MaxInst;
+ unsigned int MaxAttrib;
+ unsigned int MaxTemp;
+ unsigned int MaxAddress;
+ unsigned int MaxConst;
+ unsigned int caps;
+
+ unsigned int *inst;
+ void (*UploadToHW) (GLcontext *, nouveauShader *);
+ void (*UpdateConst) (GLcontext *, nouveauShader *, int);
+
+ struct _op_xlat*(*GetOPTXRec) (nvsFunc *, int merged);
+ struct _op_xlat*(*GetOPTXFromSOP) (nvsOpcode, int *id);
+
+ void (*InitInstruction) (nvsFunc *);
+ int (*SupportsOpcode) (nvsFunc *, nvsOpcode);
+ void (*SetOpcode) (nvsFunc *, unsigned int opcode,
+ int slot);
+ void (*SetCCUpdate) (nvsFunc *);
+ void (*SetCondition) (nvsFunc *, int on, nvsCond, int reg,
+ nvsSwzComp *swizzle);
+ void (*SetResult) (nvsFunc *, nvsRegister *,
+ unsigned int mask, int slot);
+ void (*SetSource) (nvsFunc *, nvsRegister *, int pos);
+ void (*SetTexImageUnit) (nvsFunc *, int unit);
+ void (*SetSaturate) (nvsFunc *);
+ void (*SetLastInst) (nvsFunc *);
+
+ int (*HasMergedInst) (nvsFunc *);
+ int (*IsLastInst) (nvsFunc *);
+ int (*GetOffsetNext) (nvsFunc *);
+
+ int (*GetOpcodeSlot) (nvsFunc *, int merged);
+ unsigned int (*GetOpcodeHW) (nvsFunc *, int slot);
+ nvsOpcode (*GetOpcode) (nvsFunc *, int merged);
+
+ nvsPrecision (*GetPrecision) (nvsFunc *);
+ int (*GetSaturate) (nvsFunc *);
+
+ nvsRegFile (*GetDestFile) (nvsFunc *, int merged);
+ unsigned int (*GetDestID) (nvsFunc *, int merged);
+ unsigned int (*GetDestMask) (nvsFunc *, int merged);
+
+ unsigned int (*GetSourceHW) (nvsFunc *, int merged, int pos);
+ nvsRegFile (*GetSourceFile) (nvsFunc *, int merged, int pos);
+ int (*GetSourceID) (nvsFunc *, int merged, int pos);
+ int (*GetTexImageUnit) (nvsFunc *);
+ int (*GetSourceNegate) (nvsFunc *, int merged, int pos);
+ int (*GetSourceAbs) (nvsFunc *, int merged, int pos);
+ void (*GetSourceSwizzle) (nvsFunc *, int merged, int pos,
+ nvsSwzComp *swz);
+ int (*GetSourceIndexed) (nvsFunc *, int merged, int pos);
+ void (*GetSourceConstVal) (nvsFunc *, int merged, int pos,
+ float *val);
+ int (*GetSourceScale) (nvsFunc *, int merged, int pos);
+
+ int (*GetRelAddressRegID) (nvsFunc *);
+ nvsSwzComp (*GetRelAddressSwizzle) (nvsFunc *);
+
+ int (*SupportsConditional) (nvsFunc *);
+ int (*GetConditionUpdate) (nvsFunc *);
+ int (*GetConditionTest) (nvsFunc *);
+ nvsCond (*GetCondition) (nvsFunc *);
+ void (*GetCondRegSwizzle) (nvsFunc *, nvsSwzComp *swz);
+ int (*GetCondRegID) (nvsFunc *);
+ int (*GetBranch) (nvsFunc *);
+ int (*GetBranchElse) (nvsFunc *);
+ int (*GetBranchEnd) (nvsFunc *);
+
+ int (*GetLoopCount) (nvsFunc *);
+ int (*GetLoopInitial) (nvsFunc *);
+ int (*GetLoopIncrement) (nvsFunc *);
+};
+
+static inline nvsRegister
+nvsNegate(nvsRegister reg)
+{
+ reg.negate = !reg.negate;
+ return reg;
+}
+
+static inline nvsRegister
+nvsAbs(nvsRegister reg)
+{
+ reg.abs = 1;
+ return reg;
+}
+
+static inline nvsRegister
+nvsSwizzle(nvsRegister reg, nvsSwzComp x, nvsSwzComp y,
+ nvsSwzComp z, nvsSwzComp w)
+{
+ nvsSwzComp sc[4] = { x, y, z, w };
+ nvsSwzComp oc[4];
+ int i;
+
+ for (i=0;i<4;i++)
+ oc[i] = reg.swizzle[i];
+ for (i=0;i<4;i++)
+ reg.swizzle[i] = oc[sc[i]];
+ return reg;
+}
+
+extern GLboolean nvsUpdateShader(GLcontext *ctx, nouveauShader *nvs);
+extern void nvsDisasmHWShader(nvsPtr);
+extern void nvsDumpFragmentList(nvsFragmentList *f, int lvl);
+extern nouveauShader *nvsBuildTextShader(GLcontext *ctx, GLenum target,
+ const char *text);
+
+extern void NV20VPInitShaderFuncs(nvsFunc *);
+extern void NV30VPInitShaderFuncs(nvsFunc *);
+extern void NV40VPInitShaderFuncs(nvsFunc *);
+
+extern void NV30FPInitShaderFuncs(nvsFunc *);
+extern void NV40FPInitShaderFuncs(nvsFunc *);
+
+extern void nouveauShaderInitFuncs(GLcontext *ctx);
+
+extern GLboolean nouveau_shader_pass0_arb(GLcontext *ctx, nouveauShader *nvs);
+extern GLboolean nouveau_shader_pass0_slang(GLcontext *ctx, nouveauShader *nvs);
+extern GLboolean nouveau_shader_pass1(nvsPtr nvs);
+extern GLboolean nouveau_shader_pass2(nvsPtr nvs);
+
+#endif
+
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_shader_0_arb.c b/src/mesa/drivers/dri/nouveau/nouveau_shader_0_arb.c
new file mode 100644
index 0000000000..afb889d421
--- /dev/null
+++ b/src/mesa/drivers/dri/nouveau/nouveau_shader_0_arb.c
@@ -0,0 +1,710 @@
+/*
+ * Copyright (C) 2006 Ben Skeggs.
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+/*
+ * Authors:
+ * Ben Skeggs <darktama@iinet.net.au>
+ */
+
+#include "glheader.h"
+#include "macros.h"
+#include "enums.h"
+
+#include "program.h"
+#include "programopt.h"
+#include "program_instruction.h"
+
+#include "nouveau_context.h"
+#include "nouveau_shader.h"
+
+static nvsFixedReg _tx_mesa_vp_dst_reg[VERT_RESULT_MAX] = {
+ NVS_FR_POSITION, NVS_FR_COL0, NVS_FR_COL1, NVS_FR_FOGCOORD,
+ NVS_FR_TEXCOORD0, NVS_FR_TEXCOORD1, NVS_FR_TEXCOORD2, NVS_FR_TEXCOORD3,
+ NVS_FR_TEXCOORD4, NVS_FR_TEXCOORD5, NVS_FR_TEXCOORD6, NVS_FR_TEXCOORD7,
+ NVS_FR_POINTSZ, NVS_FR_BFC0, NVS_FR_BFC1, NVS_FR_UNKNOWN /* EDGE */
+};
+
+static nvsFixedReg _tx_mesa_fp_dst_reg[FRAG_RESULT_MAX] = {
+ NVS_FR_FRAGDATA0 /* COLR */, NVS_FR_FRAGDATA0 /* COLH */,
+ NVS_FR_UNKNOWN /* DEPR */
+};
+
+static nvsFixedReg _tx_mesa_vp_src_reg[VERT_ATTRIB_MAX] = {
+ NVS_FR_POSITION, NVS_FR_WEIGHT, NVS_FR_NORMAL, NVS_FR_COL0, NVS_FR_COL1,
+ NVS_FR_FOGCOORD, NVS_FR_UNKNOWN /* COLOR_INDEX */, NVS_FR_UNKNOWN,
+ NVS_FR_TEXCOORD0, NVS_FR_TEXCOORD1, NVS_FR_TEXCOORD2, NVS_FR_TEXCOORD3,
+ NVS_FR_TEXCOORD4, NVS_FR_TEXCOORD5, NVS_FR_TEXCOORD6, NVS_FR_TEXCOORD7,
+/* Generic attribs 0-15, aliased to the above */
+ NVS_FR_POSITION, NVS_FR_WEIGHT, NVS_FR_NORMAL, NVS_FR_COL0, NVS_FR_COL1,
+ NVS_FR_FOGCOORD, NVS_FR_UNKNOWN /* COLOR_INDEX */, NVS_FR_UNKNOWN,
+ NVS_FR_TEXCOORD0, NVS_FR_TEXCOORD1, NVS_FR_TEXCOORD2, NVS_FR_TEXCOORD3,
+ NVS_FR_TEXCOORD4, NVS_FR_TEXCOORD5, NVS_FR_TEXCOORD6, NVS_FR_TEXCOORD7
+};
+
+static nvsFixedReg _tx_mesa_fp_src_reg[FRAG_ATTRIB_MAX] = {
+ NVS_FR_POSITION, NVS_FR_COL0, NVS_FR_COL1, NVS_FR_FOGCOORD,
+ NVS_FR_TEXCOORD0, NVS_FR_TEXCOORD1, NVS_FR_TEXCOORD2, NVS_FR_TEXCOORD3,
+ NVS_FR_TEXCOORD4, NVS_FR_TEXCOORD5, NVS_FR_TEXCOORD6, NVS_FR_TEXCOORD7
+};
+
+static nvsSwzComp _tx_mesa_swizzle[4] = {
+ NVS_SWZ_X, NVS_SWZ_Y, NVS_SWZ_Z, NVS_SWZ_W
+};
+
+static nvsOpcode _tx_mesa_opcode[] = {
+ [OPCODE_ABS] = NVS_OP_ABS, [OPCODE_ADD] = NVS_OP_ADD,
+ [OPCODE_ARA] = NVS_OP_ARA, [OPCODE_ARL] = NVS_OP_ARL,
+ [OPCODE_ARL_NV] = NVS_OP_ARL, [OPCODE_ARR] = NVS_OP_ARR,
+ [OPCODE_CMP] = NVS_OP_CMP, [OPCODE_COS] = NVS_OP_COS,
+ [OPCODE_DDX] = NVS_OP_DDX, [OPCODE_DDY] = NVS_OP_DDY,
+ [OPCODE_DP3] = NVS_OP_DP3, [OPCODE_DP4] = NVS_OP_DP4,
+ [OPCODE_DPH] = NVS_OP_DPH, [OPCODE_DST] = NVS_OP_DST,
+ [OPCODE_EX2] = NVS_OP_EX2, [OPCODE_EXP] = NVS_OP_EXP,
+ [OPCODE_FLR] = NVS_OP_FLR, [OPCODE_FRC] = NVS_OP_FRC,
+ [OPCODE_KIL] = NVS_OP_EMUL, [OPCODE_KIL_NV] = NVS_OP_KIL,
+ [OPCODE_LG2] = NVS_OP_LG2, [OPCODE_LIT] = NVS_OP_LIT,
+ [OPCODE_LOG] = NVS_OP_LOG,
+ [OPCODE_LRP] = NVS_OP_LRP,
+ [OPCODE_MAD] = NVS_OP_MAD, [OPCODE_MAX] = NVS_OP_MAX,
+ [OPCODE_MIN] = NVS_OP_MIN, [OPCODE_MOV] = NVS_OP_MOV,
+ [OPCODE_MUL] = NVS_OP_MUL,
+ [OPCODE_PK2H] = NVS_OP_PK2H, [OPCODE_PK2US] = NVS_OP_PK2US,
+ [OPCODE_PK4B] = NVS_OP_PK4B, [OPCODE_PK4UB] = NVS_OP_PK4UB,
+ [OPCODE_POW] = NVS_OP_POW, [OPCODE_POPA] = NVS_OP_POPA,
+ [OPCODE_PUSHA] = NVS_OP_PUSHA,
+ [OPCODE_RCC] = NVS_OP_RCC, [OPCODE_RCP] = NVS_OP_RCP,
+ [OPCODE_RFL] = NVS_OP_RFL, [OPCODE_RSQ] = NVS_OP_RSQ,
+ [OPCODE_SCS] = NVS_OP_SCS, [OPCODE_SEQ] = NVS_OP_SEQ,
+ [OPCODE_SFL] = NVS_OP_SFL, [OPCODE_SGE] = NVS_OP_SGE,
+ [OPCODE_SGT] = NVS_OP_SGT, [OPCODE_SIN] = NVS_OP_SIN,
+ [OPCODE_SLE] = NVS_OP_SLE, [OPCODE_SLT] = NVS_OP_SLT,
+ [OPCODE_SNE] = NVS_OP_SNE, [OPCODE_SSG] = NVS_OP_SSG,
+ [OPCODE_STR] = NVS_OP_STR, [OPCODE_SUB] = NVS_OP_SUB,
+ [OPCODE_SWZ] = NVS_OP_MOV,
+ [OPCODE_TEX] = NVS_OP_TEX, [OPCODE_TXB] = NVS_OP_TXB,
+ [OPCODE_TXD] = NVS_OP_TXD,
+ [OPCODE_TXL] = NVS_OP_TXL, [OPCODE_TXP] = NVS_OP_TXP,
+ [OPCODE_TXP_NV] = NVS_OP_TXP,
+ [OPCODE_UP2H] = NVS_OP_UP2H, [OPCODE_UP2US] = NVS_OP_UP2US,
+ [OPCODE_UP4B] = NVS_OP_UP4B, [OPCODE_UP4UB] = NVS_OP_UP4UB,
+ [OPCODE_X2D] = NVS_OP_X2D,
+ [OPCODE_XPD] = NVS_OP_XPD
+};
+
+static nvsCond _tx_mesa_condmask[] = {
+ NVS_COND_UNKNOWN, NVS_COND_GT, NVS_COND_LT, NVS_COND_UN, NVS_COND_GE,
+ NVS_COND_LE, NVS_COND_NE, NVS_COND_NE, NVS_COND_TR, NVS_COND_FL
+};
+
+struct pass0_rec {
+ int nvs_ipos;
+ int next_temp;
+ int swzconst_done;
+ int swzconst_id;
+ nvsRegister const_half;
+};
+
+#define X NVS_SWZ_X
+#define Y NVS_SWZ_Y
+#define Z NVS_SWZ_Z
+#define W NVS_SWZ_W
+
+static void
+pass0_append_fragment(nouveauShader *nvs, nvsFragmentHeader *fragment)
+{
+ nvsFragmentList *list = calloc(1, sizeof(nvsFragmentList));
+ if (!list)
+ return;
+
+ list->fragment = fragment;
+ list->prev = nvs->list_tail;
+ if ( nvs->list_tail)
+ nvs->list_tail->next = list;
+ if (!nvs->list_head)
+ nvs->list_head = list;
+ nvs->list_tail = list;
+
+ nvs->inst_count++;
+}
+
+static void
+pass0_make_reg(nouveauShader *nvs, nvsRegister *reg,
+ nvsRegFile file, unsigned int index)
+{
+ struct pass0_rec *rec = nvs->pass_rec;
+
+ /* defaults */
+ *reg = nvr_unused;
+ /* -1 == quick-and-dirty temp alloc */
+ if (file == NVS_FILE_TEMP && index == -1) {
+ index = rec->next_temp++;
+ assert(index < NVS_MAX_TEMPS);
+ }
+ reg->file = file;
+ reg->index = index;
+}
+
+static void
+pass0_make_swizzle(nvsSwzComp *swz, unsigned int mesa)
+{
+ int i;
+
+ for (i=0;i<4;i++)
+ swz[i] = _tx_mesa_swizzle[GET_SWZ(mesa, i)];
+}
+
+static nvsOpcode
+pass0_make_opcode(enum prog_opcode op)
+{
+ if (op > MAX_OPCODE)
+ return NVS_OP_UNKNOWN;
+ return _tx_mesa_opcode[op];
+}
+
+static nvsCond
+pass0_make_condmask(GLuint mesa)
+{
+ if (mesa > COND_FL)
+ return NVS_COND_UNKNOWN;
+ return _tx_mesa_condmask[mesa];
+}
+
+static unsigned int
+pass0_make_mask(GLuint mesa_mask)
+{
+ unsigned int mask = 0;
+
+ if (mesa_mask & WRITEMASK_X) mask |= SMASK_X;
+ if (mesa_mask & WRITEMASK_Y) mask |= SMASK_Y;
+ if (mesa_mask & WRITEMASK_Z) mask |= SMASK_Z;
+ if (mesa_mask & WRITEMASK_W) mask |= SMASK_W;
+
+ return mask;
+}
+
+static nvsTexTarget
+pass0_make_tex_target(GLuint mesa)
+{
+ switch (mesa) {
+ case TEXTURE_1D_INDEX: return NVS_TEX_TARGET_1D;
+ case TEXTURE_2D_INDEX: return NVS_TEX_TARGET_2D;
+ case TEXTURE_3D_INDEX: return NVS_TEX_TARGET_3D;
+ case TEXTURE_CUBE_INDEX: return NVS_TEX_TARGET_CUBE;
+ case TEXTURE_RECT_INDEX: return NVS_TEX_TARGET_RECT;
+ default:
+ return NVS_TEX_TARGET_UNKNOWN;
+ }
+}
+
+static void
+pass0_make_dst_reg(nvsPtr nvs, nvsRegister *reg,
+ struct prog_dst_register *dst)
+{
+ struct gl_program *mesa = (struct gl_program*)&nvs->mesa.vp;
+ nvsFixedReg sfr;
+
+ switch (dst->File) {
+ case PROGRAM_OUTPUT:
+ if (mesa->Target == GL_VERTEX_PROGRAM_ARB) {
+ sfr = (dst->Index < VERT_RESULT_MAX) ?
+ _tx_mesa_vp_dst_reg[dst->Index] : NVS_FR_UNKNOWN;
+ } else {
+ sfr = (dst->Index < FRAG_RESULT_MAX) ?
+ _tx_mesa_fp_dst_reg[dst->Index] : NVS_FR_UNKNOWN;
+ }
+ pass0_make_reg(nvs, reg, NVS_FILE_RESULT, sfr);
+ break;
+ case PROGRAM_TEMPORARY:
+ pass0_make_reg(nvs, reg, NVS_FILE_TEMP, dst->Index);
+ break;
+ case PROGRAM_ADDRESS:
+ pass0_make_reg(nvs, reg, NVS_FILE_ADDRESS, dst->Index);
+ break;
+ default:
+ fprintf(stderr, "Unknown dest file %d\n", dst->File);
+ assert(0);
+ }
+}
+
+static void
+pass0_make_src_reg(nvsPtr nvs, nvsRegister *reg, struct prog_src_register *src)
+{
+ struct gl_program *mesa = (struct gl_program *)&nvs->mesa.vp.Base;
+ struct gl_program_parameter_list *p = mesa->Parameters;
+
+ *reg = nvr_unused;
+
+ switch (src->File) {
+ case PROGRAM_INPUT:
+ reg->file = NVS_FILE_ATTRIB;
+ if (mesa->Target == GL_VERTEX_PROGRAM_ARB) {
+ reg->index = (src->Index < VERT_ATTRIB_MAX) ?
+ _tx_mesa_vp_src_reg[src->Index] : NVS_FR_UNKNOWN;
+ } else {
+ reg->index = (src->Index < FRAG_ATTRIB_MAX) ?
+ _tx_mesa_fp_src_reg[src->Index] : NVS_FR_UNKNOWN;
+ }
+ break;
+ /* All const types seem to get shoved into here, not really sure why */
+ case PROGRAM_STATE_VAR:
+ switch (p->Parameters[src->Index].Type) {
+ case PROGRAM_NAMED_PARAM:
+ case PROGRAM_CONSTANT:
+ nvs->params[src->Index].source_val = NULL;
+ COPY_4V(nvs->params[src->Index].val, p->ParameterValues[src->Index]);
+ break;
+ case PROGRAM_STATE_VAR:
+ nvs->params[src->Index].source_val = p->ParameterValues[src->Index];
+ break;
+ default:
+ fprintf(stderr, "Unknown parameter type %d\n",
+ p->Parameters[src->Index].Type);
+ assert(0);
+ break;
+ }
+
+ if (src->RelAddr) {
+ reg->indexed = 1;
+ reg->addr_reg = 0;
+ reg->addr_comp = NVS_SWZ_X;
+ } else
+ reg->indexed = 0;
+ reg->file = NVS_FILE_CONST;
+ reg->index = src->Index;
+ break;
+ case PROGRAM_TEMPORARY:
+ reg->file = NVS_FILE_TEMP;
+ reg->index = src->Index;
+ break;
+ default:
+ fprintf(stderr, "Unknown source type %d\n", src->File);
+ assert(0);
+ }
+
+ /* per-component negate handled elsewhere */
+ reg->negate = src->NegateBase != 0;
+ reg->abs = src->Abs;
+ pass0_make_swizzle(reg->swizzle, src->Swizzle);
+}
+
+static nvsInstruction *
+pass0_emit(nouveauShader *nvs, nvsOpcode op, nvsRegister dst,
+ unsigned int mask, int saturate,
+ nvsRegister src0, nvsRegister src1, nvsRegister src2)
+{
+ struct pass0_rec *rec = nvs->pass_rec;
+ nvsInstruction *sif = NULL;
+
+ /* Seems mesa doesn't explicitly 0 this.. */
+ if (nvs->mesa.vp.Base.Target == GL_VERTEX_PROGRAM_ARB)
+ saturate = 0;
+
+ sif = calloc(1, sizeof(nvsInstruction));
+ if (sif) {
+ sif->header.type = NVS_INSTRUCTION;
+ sif->header.position = rec->nvs_ipos++;
+ sif->op = op;
+ sif->saturate = saturate;
+ sif->dest = dst;
+ sif->mask = mask;
+ sif->src[0] = src0;
+ sif->src[1] = src1;
+ sif->src[2] = src2;
+ sif->cond = COND_TR;
+ sif->cond_reg = 0;
+ sif->cond_test = 0;
+ sif->cond_update = 0;
+ pass0_make_swizzle(sif->cond_swizzle, SWIZZLE_NOOP);
+ pass0_append_fragment(nvs, (nvsFragmentHeader *)sif);
+ }
+
+ return sif;
+}
+
+static void
+pass0_fixup_swizzle(nvsPtr nvs,
+ struct prog_src_register *src,
+ unsigned int sm1,
+ unsigned int sm2)
+{
+ static const float sc[4] = { 1.0, 0.0, -1.0, 0.0 };
+ struct pass0_rec *rec = nvs->pass_rec;
+ int fixup_1, fixup_2;
+ nvsRegister sr, dr = nvr_unused;
+ nvsRegister sm1const, sm2const;
+
+ if (!rec->swzconst_done) {
+ struct gl_program *prog = &nvs->mesa.vp.Base;
+ rec->swzconst_id = _mesa_add_unnamed_constant(prog->Parameters, sc, 4);
+ rec->swzconst_done = 1;
+ COPY_4V(nvs->params[rec->swzconst_id].val, sc);
+ }
+
+ fixup_1 = (sm1 != MAKE_SWIZZLE4(0,0,0,0) && sm2 != MAKE_SWIZZLE4(2,2,2,2));
+ fixup_2 = (sm2 != MAKE_SWIZZLE4(2,2,2,2));
+
+ if (src->File != PROGRAM_TEMPORARY && src->File != PROGRAM_INPUT) {
+ /* We can't use more than one const in an instruction, so move the const
+ * into a temp, and swizzle from there.
+ *TODO: should just emit the swizzled const, instead of swizzling it
+ * in the shader.. would need to reswizzle any state params when they
+ * change however..
+ */
+ pass0_make_reg(nvs, &dr, NVS_FILE_TEMP, -1);
+ pass0_make_src_reg(nvs, &sr, src);
+ pass0_emit(nvs, NVS_OP_MOV, dr, SMASK_ALL, 0, sr, nvr_unused, nvr_unused);
+ pass0_make_reg(nvs, &sr, NVS_FILE_TEMP, dr.index);
+ } else {
+ if (fixup_1)
+ src->NegateBase = 0;
+ pass0_make_src_reg(nvs, &sr, src);
+ pass0_make_reg(nvs, &dr, NVS_FILE_TEMP, -1);
+ }
+
+ pass0_make_reg(nvs, &sm1const, NVS_FILE_CONST, rec->swzconst_id);
+ pass0_make_swizzle(sm1const.swizzle, sm1);
+ if (fixup_1 && fixup_2) {
+ /* Any combination with SWIZZLE_ONE */
+ pass0_make_reg(nvs, &sm2const, NVS_FILE_CONST, rec->swzconst_id);
+ pass0_make_swizzle(sm2const.swizzle, sm2);
+ pass0_emit(nvs, NVS_OP_MAD, dr, SMASK_ALL, 0, sr, sm1const, sm2const);
+ } else {
+ /* SWIZZLE_ZERO || arbitrary negate */
+ pass0_emit(nvs, NVS_OP_MUL, dr, SMASK_ALL, 0, sr, sm1const, nvr_unused);
+ }
+
+ src->File = PROGRAM_TEMPORARY;
+ src->Index = dr.index;
+ src->Swizzle = SWIZZLE_NOOP;
+}
+
+#define SET_SWZ(fs, cp, c) fs = (fs & ~(0x7<<(cp*3))) | (c<<(cp*3))
+static void
+pass0_check_sources(nvsPtr nvs, struct prog_instruction *inst)
+{
+ unsigned int insrc = -1, constsrc = -1;
+ int i;
+
+ for (i=0;i<_mesa_num_inst_src_regs(inst->Opcode);i++) {
+ struct prog_src_register *src = &inst->SrcReg[i];
+ unsigned int sm_1 = 0, sm_2 = 0;
+ nvsRegister sr, dr;
+ int do_mov = 0, c;
+
+ /* Build up swizzle masks as if we were going to use
+ * "MAD new, src, const1, const2" to support arbitrary negation
+ * and SWIZZLE_ZERO/SWIZZLE_ONE.
+ */
+ for (c=0;c<4;c++) {
+ if (GET_SWZ(src->Swizzle, c) == SWIZZLE_ZERO) {
+ SET_SWZ(sm_1, c, SWIZZLE_Y); /* 0.0 */
+ SET_SWZ(sm_2, c, SWIZZLE_Y);
+ SET_SWZ(src->Swizzle, c, SWIZZLE_X);
+ } else if (GET_SWZ(src->Swizzle, c) == SWIZZLE_ONE) {
+ SET_SWZ(sm_1, c, SWIZZLE_Y);
+ if (src->NegateBase & (1<<c))
+ SET_SWZ(sm_2, c, SWIZZLE_Z); /* -1.0 */
+ else
+ SET_SWZ(sm_2, c, SWIZZLE_X); /* 1.0 */
+ SET_SWZ(src->Swizzle, c, SWIZZLE_X);
+ } else {
+ if (src->NegateBase & (1<<c))
+ SET_SWZ(sm_1, c, SWIZZLE_Z); /* -[xyzw] */
+ else
+ SET_SWZ(sm_1, c, SWIZZLE_X); /* [xyzw] */
+ SET_SWZ(sm_2, c, SWIZZLE_Y);
+ }
+ }
+ /* Unless we're multiplying by 1.0 or -1.0 on all components, and we're
+ * adding nothing to any component we have to emulate the swizzle.
+ */
+ if ((sm_1 != MAKE_SWIZZLE4(0,0,0,0) && sm_1 != MAKE_SWIZZLE4(2,2,2,2)) ||
+ sm_2 != MAKE_SWIZZLE4(1,1,1,1)) {
+ pass0_fixup_swizzle(nvs, src, sm_1, sm_2);
+ /* The source is definitely in a temp now, so don't bother checking
+ * for multiple ATTRIB/CONST regs.
+ */
+ continue;
+ }
+
+ /* HW can't use more than one ATTRIB or PARAM in a single instruction */
+ switch (src->File) {
+ case PROGRAM_INPUT:
+ if (insrc != -1 && insrc != src->Index)
+ do_mov = 1;
+ else insrc = src->Index;
+ break;
+ case PROGRAM_STATE_VAR:
+ if (constsrc != -1 && constsrc != src->Index)
+ do_mov = 1;
+ else constsrc = src->Index;
+ break;
+ default:
+ break;
+ }
+
+ /* Emit any extra ATTRIB/CONST to a temp, and modify the Mesa instruction
+ * to point at the temp.
+ */
+ if (do_mov) {
+ pass0_make_src_reg(nvs, &sr, src);
+ pass0_make_reg(nvs, &dr, NVS_FILE_TEMP, -1);
+ pass0_emit(nvs, NVS_OP_MOV, dr, SMASK_ALL, 0,
+ sr, nvr_unused, nvr_unused);
+
+ src->File = PROGRAM_TEMPORARY;
+ src->Index = dr.index;
+ src->Swizzle= SWIZZLE_NOOP;
+ }
+ }
+}
+
+static GLboolean
+pass0_emulate_instruction(nouveauShader *nvs, struct prog_instruction *inst)
+{
+ nvsFunc *shader = nvs->func;
+ nvsRegister src[3], dest, temp;
+ nvsInstruction *nvsinst;
+ struct pass0_rec *rec = nvs->pass_rec;
+ unsigned int mask = pass0_make_mask(inst->DstReg.WriteMask);
+ int i, sat;
+
+ sat = (inst->SaturateMode == SATURATE_ZERO_ONE);
+
+ /* Build all the "real" regs for the instruction */
+ for (i=0; i<_mesa_num_inst_src_regs(inst->Opcode); i++)
+ pass0_make_src_reg(nvs, &src[i], &inst->SrcReg[i]);
+ if (inst->Opcode != OPCODE_KIL)
+ pass0_make_dst_reg(nvs, &dest, &inst->DstReg);
+
+ switch (inst->Opcode) {
+ case OPCODE_ABS:
+ if (shader->caps & SCAP_SRC_ABS)
+ pass0_emit(nvs, NVS_OP_MOV, dest, mask, sat,
+ nvsAbs(src[0]), nvr_unused, nvr_unused);
+ else
+ pass0_emit(nvs, NVS_OP_MAX, dest, mask, sat,
+ src[0], nvsNegate(src[0]), nvr_unused);
+ break;
+ case OPCODE_KIL:
+ /* This is only in ARB shaders, so we don't have to worry
+ * about clobbering a CC reg as they aren't supported anyway.
+ */
+ /* MOVC0 temp, src */
+ pass0_make_reg(nvs, &temp, NVS_FILE_TEMP, -1);
+ nvsinst = pass0_emit(nvs, NVS_OP_MOV, temp, SMASK_ALL, 0,
+ src[0], nvr_unused, nvr_unused);
+ nvsinst->cond_update = 1;
+ nvsinst->cond_reg = 0;
+ /* KIL_NV (LT0.xyzw) temp */
+ nvsinst = pass0_emit(nvs, NVS_OP_KIL, nvr_unused, 0, 0,
+ nvr_unused, nvr_unused, nvr_unused);
+ nvsinst->cond = COND_LT;
+ nvsinst->cond_reg = 0;
+ nvsinst->cond_test = 1;
+ pass0_make_swizzle(nvsinst->cond_swizzle, MAKE_SWIZZLE4(0,1,2,3));
+ break;
+ case OPCODE_LIT:
+ break;
+ case OPCODE_LRP:
+ pass0_make_reg(nvs, &temp, NVS_FILE_TEMP, -1);
+ pass0_emit(nvs, NVS_OP_MAD, temp, mask, 0,
+ nvsNegate(src[0]), src[2], src[2]);
+ pass0_emit(nvs, NVS_OP_MAD, dest, mask, sat,
+ src[0], src[1], temp);
+ break;
+ case OPCODE_POW:
+ if (shader->SupportsOpcode(shader, NVS_OP_LG2) &&
+ shader->SupportsOpcode(shader, NVS_OP_EX2)) {
+ pass0_make_reg(nvs, &temp, NVS_FILE_TEMP, -1);
+ /* LG2 temp.x, src0.c */
+ pass0_emit(nvs, NVS_OP_LG2, temp, SMASK_X, 0,
+ nvsSwizzle(src[0], X, X, X, X),
+ nvr_unused,
+ nvr_unused);
+ /* MUL temp.x, temp.x, src1.c */
+ pass0_emit(nvs, NVS_OP_MUL, temp, SMASK_X, 0,
+ nvsSwizzle(temp, X, X, X, X),
+ nvsSwizzle(src[1], X, X, X, X),
+ nvr_unused);
+ /* EX2 dest, temp.x */
+ pass0_emit(nvs, NVS_OP_EX2, dest, mask, sat,
+ nvsSwizzle(temp, X, X, X, X),
+ nvr_unused,
+ nvr_unused);
+ } else {
+ /* can we use EXP/LOG instead of EX2/LG2?? */
+ fprintf(stderr, "Implement POW for NV20 vtxprog!\n");
+ return GL_FALSE;
+ }
+ break;
+ case OPCODE_RSQ:
+ if (rec->const_half.file != NVS_FILE_CONST) {
+ GLfloat const_half[4] = { 0.5, 0.0, 0.0, 0.0 };
+ pass0_make_reg(nvs, &rec->const_half, NVS_FILE_CONST,
+ _mesa_add_unnamed_constant(nvs->mesa.vp.Base.Parameters,
+ const_half, 4));
+ COPY_4V(nvs->params[rec->const_half.index].val, const_half);
+ }
+ pass0_make_reg(nvs, &temp, NVS_FILE_TEMP, -1);
+ pass0_emit(nvs, NVS_OP_LG2, temp, SMASK_X, 0,
+ nvsAbs(nvsSwizzle(src[0], X, X, X, X)),
+ nvr_unused,
+ nvr_unused);
+ pass0_emit(nvs, NVS_OP_MUL, temp, SMASK_X, 0,
+ nvsSwizzle(temp, X, X, X, X),
+ nvsNegate(rec->const_half),
+ nvr_unused);
+ pass0_emit(nvs, NVS_OP_EX2, dest, mask, sat,
+ nvsSwizzle(temp, X, X, X, X),
+ nvr_unused,
+ nvr_unused);
+ break;
+ case OPCODE_SCS:
+ if (mask & SMASK_X)
+ pass0_emit(nvs, NVS_OP_COS, dest, SMASK_X, sat,
+ nvsSwizzle(src[0], X, X, X, X),
+ nvr_unused,
+ nvr_unused);
+ if (mask & SMASK_Y)
+ pass0_emit(nvs, NVS_OP_SIN, dest, SMASK_Y, sat,
+ nvsSwizzle(src[0], X, X, X, X),
+ nvr_unused,
+ nvr_unused);
+ break;
+ case OPCODE_SUB:
+ pass0_emit(nvs, NVS_OP_ADD, dest, mask, sat,
+ src[0], nvsNegate(src[1]), nvr_unused);
+ break;
+ case OPCODE_XPD:
+ pass0_make_reg(nvs, &temp, NVS_FILE_TEMP, -1);
+ pass0_emit(nvs, NVS_OP_MUL, temp, SMASK_ALL, 0,
+ nvsSwizzle(src[0], Z, X, Y, Y),
+ nvsSwizzle(src[1], Y, Z, X, X),
+ nvr_unused);
+ pass0_emit(nvs, NVS_OP_MAD, dest, (mask & ~SMASK_W), sat,
+ nvsSwizzle(src[0], Y, Z, X, X),
+ nvsSwizzle(src[1], Z, X, Y, Y),
+ nvsNegate(temp));
+ break;
+ default:
+ fprintf(stderr, "hw doesn't support opcode \"%s\", and no emulation found\n",
+ _mesa_opcode_string(inst->Opcode));
+ return GL_FALSE;
+ }
+
+ return GL_TRUE;
+}
+
+static GLboolean
+pass0_translate_instructions(nouveauShader *nvs)
+{
+ struct gl_program *prog = (struct gl_program *)&nvs->mesa.vp;
+ nvsFunc *shader = nvs->func;
+ int ipos;
+
+ for (ipos=0; ipos<prog->NumInstructions; ipos++) {
+ struct prog_instruction *inst = &prog->Instructions[ipos];
+
+ if (inst->Opcode == OPCODE_END)
+ break;
+
+ /* Deal with multiple ATTRIB/PARAM in a single instruction */
+ pass0_check_sources(nvs, inst);
+
+ /* Now it's safe to do the prog_instruction->nvsInstruction conversion */
+ if (shader->SupportsOpcode(shader, pass0_make_opcode(inst->Opcode))) {
+ nvsInstruction *nvsinst;
+ nvsRegister src[3], dest;
+ int i;
+
+ for (i=0; i<_mesa_num_inst_src_regs(inst->Opcode); i++)
+ pass0_make_src_reg(nvs, &src[i], &inst->SrcReg[i]);
+ pass0_make_dst_reg(nvs, &dest, &inst->DstReg);
+
+ nvsinst = pass0_emit(nvs,
+ pass0_make_opcode(inst->Opcode),
+ dest,
+ pass0_make_mask(inst->DstReg.WriteMask),
+ (inst->SaturateMode != SATURATE_OFF),
+ src[0], src[1], src[2]);
+ nvsinst->tex_unit = inst->TexSrcUnit;
+ nvsinst->tex_target = pass0_make_tex_target(inst->TexSrcTarget);
+ /* TODO when NV_fp/vp is implemented */
+ nvsinst->cond = COND_TR;
+ } else {
+ if (!pass0_emulate_instruction(nvs, inst))
+ return GL_FALSE;
+ }
+ }
+
+ return GL_TRUE;
+}
+
+GLboolean
+nouveau_shader_pass0_arb(GLcontext *ctx, nouveauShader *nvs)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ struct gl_program *prog = (struct gl_program*)nvs;
+ struct gl_vertex_program *vp = (struct gl_vertex_program *)prog;
+ struct gl_fragment_program *fp = (struct gl_fragment_program *)prog;
+ struct pass0_rec *rec;
+ int ret;
+
+ switch (prog->Target) {
+ case GL_VERTEX_PROGRAM_ARB:
+ nvs->func = &nmesa->VPfunc;
+ if (vp->IsPositionInvariant)
+ _mesa_insert_mvp_code(ctx, vp);
+#if 0
+ if (IS_FIXEDFUNCTION_PROG && CLIP_PLANES_USED)
+ pass0_insert_ff_clip_planes();
+#endif
+ break;
+ case GL_FRAGMENT_PROGRAM_ARB:
+ nvs->func = &nmesa->FPfunc;
+ if (fp->FogOption != GL_NONE)
+ _mesa_append_fog_code(ctx, fp);
+ break;
+ default:
+ fprintf(stderr, "Unknown program type %d", prog->Target);
+ return GL_FALSE;
+ }
+
+ rec = calloc(1, sizeof(struct pass0_rec));
+ rec->next_temp = prog->NumTemporaries;
+ nvs->pass_rec = rec;
+
+ ret = pass0_translate_instructions(nvs);
+ if (!ret) {
+ /* DESTROY list */
+ }
+
+ free(nvs->pass_rec);
+ return ret;
+}
+
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_shader_1.c b/src/mesa/drivers/dri/nouveau/nouveau_shader_1.c
new file mode 100644
index 0000000000..5de9017f58
--- /dev/null
+++ b/src/mesa/drivers/dri/nouveau/nouveau_shader_1.c
@@ -0,0 +1,318 @@
+/*
+ * Copyright (C) 2006 Ben Skeggs.
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+/*
+ * Authors:
+ * Ben Skeggs <darktama@iinet.net.au>
+ */
+
+#include "glheader.h"
+#include "macros.h"
+#include "enums.h"
+
+#include "nouveau_shader.h"
+
+#define PASS1_OK 0
+#define PASS1_KILL 1
+#define PASS1_FAIL 2
+
+struct pass1_rec {
+ unsigned int temp[NVS_MAX_TEMPS];
+ unsigned int result[NVS_MAX_ATTRIBS];
+ unsigned int address[NVS_MAX_ADDRESS];
+ unsigned int cc[2];
+};
+
+static void
+pass1_remove_fragment(nvsPtr nvs, nvsFragmentList *item)
+{
+ if (item->prev) item->prev->next = item->next;
+ if (item->next) item->next->prev = item->prev;
+ if (nvs->list_head == item) nvs->list_head = item->next;
+ if (nvs->list_tail == item) nvs->list_tail = item->prev;
+
+ nvs->inst_count--;
+}
+
+static int
+pass1_result_needed(struct pass1_rec *rec, nvsInstruction *inst)
+{
+ if (inst->cond_update && rec->cc[inst->cond_reg])
+ return 1;
+ /* Only write components that are read later */
+ if (inst->dest.file == NVS_FILE_TEMP)
+ return (inst->mask & rec->temp[inst->dest.index]);
+ if (inst->dest.file == NVS_FILE_ADDRESS)
+ return (inst->mask & rec->address[inst->dest.index]);
+ /* No point writing result components that are written later */
+ if (inst->dest.file == NVS_FILE_RESULT)
+ return (inst->mask & ~rec->result[inst->dest.index]);
+ assert(0);
+}
+
+static void
+pass1_track_result(struct pass1_rec *rec, nvsInstruction *inst)
+{
+ if (inst->cond_test)
+ rec->cc[inst->cond_reg] = 1;
+ if (inst->dest.file == NVS_FILE_TEMP) {
+ inst->mask &= rec->temp[inst->dest.index];
+ } else if (inst->dest.file == NVS_FILE_RESULT) {
+ inst->mask &= ~rec->result[inst->dest.index];
+ rec->result[inst->dest.index] |= inst->mask;
+ } else if (inst->dest.file == NVS_FILE_ADDRESS) {
+ inst->mask &= rec->address[inst->dest.index];
+ }
+}
+
+static void
+pass1_track_source(nouveauShader *nvs, nvsInstruction *inst, int pos,
+ unsigned int read)
+{
+ struct pass1_rec *rec = nvs->pass_rec;
+ nvsRegister *src = &inst->src[pos];
+ unsigned int really_read = 0;
+ int i,sc;
+
+ /* Account for swizzling */
+ for (i=0; i<4; i++)
+ if (read & (1<<i)) really_read |= (1 << src->swizzle[i]);
+
+ /* Track register reads */
+ if (src->file == NVS_FILE_TEMP) {
+ if (nvs->temps[src->index].last_use == -1)
+ nvs->temps[src->index].last_use = inst->header.position;
+ rec->temp [src->index] |= really_read;
+ } else if (src->indexed) {
+ rec->address[src->addr_reg] |= (1<<src->addr_comp);
+ }
+
+ /* Modify swizzle to only access read components */
+ /* Find a component that is used.. */
+ for (sc=0;sc<4;sc++)
+ if (really_read & (1<<sc))
+ break;
+ /* Now set all unused components to that value */
+ for (i=0;i<4;i++)
+ if (!(read & (1<<i))) src->swizzle[i] = sc;
+}
+
+static int
+pass1_check_instruction(nouveauShader *nvs, nvsInstruction *inst)
+{
+ struct pass1_rec *rec = nvs->pass_rec;
+ unsigned int read0, read1, read2;
+
+ if (inst->op != NVS_OP_KIL) {
+ if (!pass1_result_needed(rec, inst))
+ return PASS1_KILL;
+ }
+ pass1_track_result(rec, inst);
+
+ read0 = read1 = read2 = 0;
+
+ switch (inst->op) {
+ case NVS_OP_FLR:
+ case NVS_OP_FRC:
+ case NVS_OP_MOV:
+ case NVS_OP_SSG:
+ case NVS_OP_ARL:
+ read0 = inst->mask;
+ break;
+ case NVS_OP_ADD:
+ case NVS_OP_MAX:
+ case NVS_OP_MIN:
+ case NVS_OP_MUL:
+ case NVS_OP_SEQ:
+ case NVS_OP_SFL:
+ case NVS_OP_SGE:
+ case NVS_OP_SGT:
+ case NVS_OP_SLE:
+ case NVS_OP_SLT:
+ case NVS_OP_SNE:
+ case NVS_OP_STR:
+ case NVS_OP_SUB:
+ read0 = inst->mask;
+ read1 = inst->mask;
+ break;
+ case NVS_OP_CMP:
+ case NVS_OP_LRP:
+ case NVS_OP_MAD:
+ read0 = inst->mask;
+ read1 = inst->mask;
+ read2 = inst->mask;
+ break;
+ case NVS_OP_XPD:
+ if (inst->mask & SMASK_X) read0 |= SMASK_Y|SMASK_Z;
+ if (inst->mask & SMASK_Y) read0 |= SMASK_X|SMASK_Z;
+ if (inst->mask & SMASK_Z) read0 |= SMASK_X|SMASK_Y;
+ read1 = read0;
+ break;
+ case NVS_OP_COS:
+ case NVS_OP_EX2:
+ case NVS_OP_EXP:
+ case NVS_OP_LG2:
+ case NVS_OP_LOG:
+ case NVS_OP_RCC:
+ case NVS_OP_RCP:
+ case NVS_OP_RSQ:
+ case NVS_OP_SCS:
+ case NVS_OP_SIN:
+ read0 = SMASK_X;
+ break;
+ case NVS_OP_POW:
+ read0 = SMASK_X;
+ read1 = SMASK_X;
+ break;
+ case NVS_OP_DIV:
+ read0 = inst->mask;
+ read1 = SMASK_X;
+ break;
+ case NVS_OP_DP2:
+ read0 = SMASK_X|SMASK_Y;
+ read1 = SMASK_X|SMASK_Y;
+ break;
+ case NVS_OP_DP3:
+ case NVS_OP_RFL:
+ read0 = SMASK_X|SMASK_Y|SMASK_Z;
+ read1 = SMASK_X|SMASK_Y|SMASK_Z;
+ break;
+ case NVS_OP_DP4:
+ read0 = SMASK_ALL;
+ read1 = SMASK_ALL;
+ break;
+ case NVS_OP_DPH:
+ read0 = SMASK_X|SMASK_Y|SMASK_Z;
+ read1 = SMASK_ALL;
+ break;
+ case NVS_OP_DST:
+ if (inst->mask & SMASK_Y) read0 = read1 = SMASK_Y;
+ if (inst->mask & SMASK_Z) read0 |= SMASK_Z;
+ if (inst->mask & SMASK_W) read1 |= SMASK_W;
+ break;
+ case NVS_OP_NRM:
+ read0 = SMASK_X|SMASK_Y|SMASK_Z;
+ break;
+ case NVS_OP_PK2H:
+ case NVS_OP_PK2US:
+ read0 = SMASK_X|SMASK_Y;
+ break;
+ case NVS_OP_DDX:
+ case NVS_OP_DDY:
+ case NVS_OP_UP2H:
+ case NVS_OP_UP2US:
+ case NVS_OP_PK4B:
+ case NVS_OP_PK4UB:
+ case NVS_OP_UP4B:
+ case NVS_OP_UP4UB:
+ read0 = SMASK_ALL;
+ break;
+ case NVS_OP_X2D:
+ read1 = SMASK_X|SMASK_Y;
+ if (inst->mask & (SMASK_X|SMASK_Z)) {
+ read0 |= SMASK_X;
+ read2 |= SMASK_X|SMASK_Y;
+ }
+ if (inst->mask & (SMASK_Y|SMASK_W)) {
+ read0 |= SMASK_Y;
+ read2 |= SMASK_Z|SMASK_W;
+ }
+ break;
+ case NVS_OP_LIT:
+ read0 |= SMASK_X|SMASK_Y|SMASK_W;
+ break;
+ case NVS_OP_TEX:
+ case NVS_OP_TXP:
+ case NVS_OP_TXL:
+ case NVS_OP_TXB:
+ read0 = SMASK_ALL;
+ break;
+ case NVS_OP_TXD:
+ read0 = SMASK_ALL;
+ read1 = SMASK_ALL;
+ read2 = SMASK_ALL;
+ break;
+ case NVS_OP_KIL:
+ break;
+ default:
+ fprintf(stderr, "Unknown sop=%d", inst->op);
+ return PASS1_FAIL;
+ }
+
+ /* Any values that are written by this inst can't have been read further up */
+ if (inst->dest.file == NVS_FILE_TEMP)
+ rec->temp[inst->dest.index] &= ~inst->mask;
+
+ if (read0) pass1_track_source(nvs, inst, 0, read0);
+ if (read1) pass1_track_source(nvs, inst, 1, read1);
+ if (read2) pass1_track_source(nvs, inst, 2, read2);
+
+ return PASS1_OK;
+}
+
+/* Some basic dead code elimination
+ * - Remove unused instructions
+ * - Don't write unused register components
+ * - Modify swizzles to not reference unneeded components.
+ */
+GLboolean
+nouveau_shader_pass1(nvsPtr nvs)
+{
+ nvsFragmentList *list = nvs->list_tail;
+ int i;
+
+ for (i=0; i<NVS_MAX_TEMPS; i++)
+ nvs->temps[i].last_use = -1;
+
+ nvs->pass_rec = calloc(1, sizeof(struct pass1_rec));
+
+ while (list) {
+ assert(list->fragment->type == NVS_INSTRUCTION);
+
+ switch(pass1_check_instruction(nvs, (nvsInstruction *)list->fragment)) {
+ case PASS1_OK:
+ break;
+ case PASS1_KILL:
+ pass1_remove_fragment(nvs, list);
+ break;
+ case PASS1_FAIL:
+ default:
+ free(nvs->pass_rec);
+ nvs->pass_rec = NULL;
+ return GL_FALSE;
+ }
+
+ list = list->prev;
+ }
+
+ free(nvs->pass_rec);
+ nvs->pass_rec = NULL;
+
+ return GL_TRUE;
+}
+
+
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_shader_2.c b/src/mesa/drivers/dri/nouveau/nouveau_shader_2.c
new file mode 100644
index 0000000000..2177413b66
--- /dev/null
+++ b/src/mesa/drivers/dri/nouveau/nouveau_shader_2.c
@@ -0,0 +1,243 @@
+/*
+ * Copyright (C) 2006 Ben Skeggs.
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+/*
+ * Authors:
+ * Ben Skeggs <darktama@iinet.net.au>
+ */
+
+#include "glheader.h"
+#include "macros.h"
+#include "enums.h"
+
+#include "program.h"
+
+#include "nouveau_context.h"
+#include "nouveau_shader.h"
+
+struct pass2_rec {
+ /* Map nvsRegister temp ID onto hw temp ID */
+ unsigned int temps[NVS_MAX_TEMPS];
+ /* Track free hw registers */
+ unsigned int hw_temps[NVS_MAX_TEMPS];
+};
+
+static int
+pass2_alloc_hw_temp(nvsPtr nvs)
+{
+ struct pass2_rec *rec = nvs->pass_rec;
+ int i;
+
+ for (i=0; i<nvs->func->MaxTemp; i++) {
+ /* This is a *horrible* hack.. R0 is both temp0 and result.color
+ * in NV30/40 fragprogs, we can use R0 as a temp before result is
+ * written however..
+ */
+ if (nvs->mesa.vp.Base.Target == GL_FRAGMENT_PROGRAM_ARB && i==0)
+ continue;
+
+ if (rec->hw_temps[i] == 0) {
+ rec->hw_temps[i] = 1;
+ return i;
+ }
+ }
+ return -1;
+}
+
+static void
+pass2_free_hw_temp(nvsPtr nvs, int reg)
+{
+ struct pass2_rec *rec = nvs->pass_rec;
+ rec->hw_temps[reg] = 0;
+}
+
+static nvsRegister
+pass2_mangle_reg(nvsPtr nvs, nvsInstruction *inst, nvsRegister reg)
+{
+ struct pass2_rec *rec = nvs->pass_rec;
+
+ if (reg.file == NVS_FILE_TEMP) {
+ int hwidx;
+
+ if (rec->temps[reg.index] == -1)
+ rec->temps[reg.index] = pass2_alloc_hw_temp(nvs);
+ hwidx = rec->temps[reg.index];
+
+ if (nvs->temps[reg.index].last_use <= inst->header.position)
+ pass2_free_hw_temp(nvs, hwidx);
+
+ reg.index = hwidx;
+ }
+
+ return reg;
+}
+
+static void
+pass2_add_instruction(nvsPtr nvs, nvsInstruction *inst,
+ struct _op_xlat *op, int slot)
+{
+ nvsSwzComp default_swz[4] = { NVS_SWZ_X, NVS_SWZ_Y, NVS_SWZ_Z, NVS_SWZ_W };
+ nvsFunc *shader = nvs->func;
+ nvsRegister reg;
+ int i;
+
+ shader->SetOpcode(shader, op->NV, slot);
+ if (inst->saturate ) shader->SetSaturate(shader);
+ if (inst->cond_update) shader->SetCCUpdate(shader);
+ if (inst->cond_test ) shader->SetCondition(shader, 1, inst->cond,
+ inst->cond_reg,
+ inst->cond_swizzle);
+ else shader->SetCondition(shader, 0, NVS_COND_TR,
+ 0,
+ default_swz);
+ switch (inst->op) {
+ case NVS_OP_TEX:
+ case NVS_OP_TXB:
+ case NVS_OP_TXL:
+ case NVS_OP_TXP:
+ case NVS_OP_TXD:
+ shader->SetTexImageUnit(shader, inst->tex_unit);
+ break;
+ default:
+ break;
+ }
+
+ for (i = 0; i < 3; i++) {
+ if (op->srcpos[i] != -1) {
+ reg = pass2_mangle_reg(nvs, inst, inst->src[i]);
+ if (reg.file == NVS_FILE_ATTRIB)
+ nvs->inputs_read |= (1 << reg.index);
+ shader->SetSource(shader, &reg, op->srcpos[i]);
+ if (reg.file == NVS_FILE_CONST && shader->GetSourceConstVal) {
+ int idx_slot = nvs->params[reg.index].hw_index_cnt++;
+ nvs->params[reg.index].hw_index = realloc(
+ nvs->params[reg.index].hw_index, sizeof(int) * idx_slot+1);
+ nvs->params[reg.index].hw_index[idx_slot] = nvs->program_current + 4;
+ }
+ }
+ }
+
+ reg = pass2_mangle_reg(nvs, inst, inst->dest);
+ if (reg.file == NVS_FILE_RESULT)
+ nvs->outputs_written |= (1 << reg.index);
+ shader->SetResult(shader, &reg, inst->mask, slot);
+}
+
+static int
+pass2_assemble_instruction(nvsPtr nvs, nvsInstruction *inst, int last)
+{
+ nvsFunc *shader = nvs->func;
+ struct _op_xlat *op;
+ unsigned int hw_inst[8];
+ int slot;
+ int instsz;
+ int i;
+
+ shader->inst = hw_inst;
+
+ /* Assemble this instruction */
+ if (!(op = shader->GetOPTXFromSOP(inst->op, &slot)))
+ return 0;
+ shader->InitInstruction(shader);
+ pass2_add_instruction(nvs, inst, op, slot);
+ if (last)
+ shader->SetLastInst(shader);
+
+ instsz = shader->GetOffsetNext(nvs->func);
+ if (nvs->program_size + instsz >= nvs->program_alloc_size) {
+ nvs->program_alloc_size *= 2;
+ nvs->program = realloc(nvs->program,
+ nvs->program_alloc_size * sizeof(uint32_t));
+ }
+
+ for (i=0; i<instsz; i++)
+ nvs->program[nvs->program_current++] = hw_inst[i];
+ nvs->program_size = nvs->program_current;
+ return 1;
+}
+
+/* Translate program into hardware format */
+GLboolean
+nouveau_shader_pass2(nvsPtr nvs)
+{
+ nvsFragmentList *list = nvs->list_head;
+ struct pass2_rec *rec;
+ int i;
+
+ rec = calloc(1, sizeof(struct pass2_rec));
+ for (i=0; i<NVS_MAX_TEMPS; i++)
+ rec->temps[i] = -1;
+ nvs->pass_rec = rec;
+
+ /* Start off with allocating 4 uint32_t's for each inst, will be grown
+ * if necessary..
+ */
+ nvs->program_alloc_size = nvs->inst_count * 4;
+ nvs->program = calloc(nvs->program_alloc_size, sizeof(uint32_t));
+ nvs->program_size = 0;
+ nvs->program_current = 0;
+
+ while (list) {
+ assert(list->fragment->type == NVS_INSTRUCTION);
+
+ if (!pass2_assemble_instruction(nvs, (nvsInstruction *)list->fragment, list->next ? 0 : 1)) {
+ free(nvs->program);
+ nvs->program = NULL;
+ return GL_FALSE;
+ }
+
+ list = list->next;
+ }
+
+ /* Shrink allocated memory to only what we need */
+ nvs->program = realloc(nvs->program, nvs->program_size * sizeof(uint32_t));
+ nvs->program_alloc_size = nvs->program_size;
+
+ nvs->translated = 1;
+ nvs->on_hardware = 0;
+
+ if (NOUVEAU_DEBUG & DEBUG_SHADERS) {
+ fflush(stdout); fflush(stderr);
+ fprintf(stderr, "----------------MESA PROGRAM target=%s, id=0x%x\n",
+ _mesa_lookup_enum_by_nr(nvs->mesa.vp.Base.Target),
+ nvs->mesa.vp.Base.Id);
+ fflush(stdout); fflush(stderr);
+ _mesa_print_program(&nvs->mesa.vp.Base);
+ fflush(stdout); fflush(stderr);
+ fprintf(stderr, "^^^^^^^^^^^^^^^^MESA PROGRAM\n");
+ fflush(stdout); fflush(stderr);
+ fprintf(stderr, "----------------NV PROGRAM\n");
+ fflush(stdout); fflush(stderr);
+ nvsDisasmHWShader(nvs);
+ fflush(stdout); fflush(stderr);
+ fprintf(stderr, "^^^^^^^^^^^^^^^^NV PROGRAM\n");
+ fflush(stdout); fflush(stderr);
+ }
+
+ return GL_TRUE;
+}
+
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_span.c b/src/mesa/drivers/dri/nouveau/nouveau_span.c
new file mode 100644
index 0000000000..74dec66afc
--- /dev/null
+++ b/src/mesa/drivers/dri/nouveau/nouveau_span.c
@@ -0,0 +1,125 @@
+/**************************************************************************
+
+Copyright 2006 Stephane Marchesin
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+
+#include "nouveau_context.h"
+#include "nouveau_span.h"
+#include "nouveau_fifo.h"
+#include "nouveau_lock.h"
+
+#include "swrast/swrast.h"
+
+#define HAVE_HW_DEPTH_SPANS 0
+#define HAVE_HW_DEPTH_PIXELS 0
+#define HAVE_HW_STENCIL_SPANS 0
+#define HAVE_HW_STENCIL_PIXELS 0
+
+#define HW_CLIPLOOP() \
+ do { \
+ int _nc = nmesa->numClipRects; \
+ while ( _nc-- ) { \
+ int minx = nmesa->pClipRects[_nc].x1 - nmesa->drawX; \
+ int miny = nmesa->pClipRects[_nc].y1 - nmesa->drawY; \
+ int maxx = nmesa->pClipRects[_nc].x2 - nmesa->drawX; \
+ int maxy = nmesa->pClipRects[_nc].y2 - nmesa->drawY;
+
+#define LOCAL_VARS \
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); \
+ nouveau_renderbuffer *nrb = (nouveau_renderbuffer *)rb; \
+ GLuint height = nrb->mesa.Height; \
+ GLubyte *map = (GLubyte *)(nrb->map ? nrb->map : nrb->mem->map) + \
+ (nmesa->drawY * nrb->pitch) + (nmesa->drawX * nrb->cpp); \
+ GLuint p; \
+ (void) p;
+
+#define Y_FLIP( _y ) (height - _y - 1)
+
+#define HW_LOCK()
+
+#define HW_UNLOCK()
+
+
+
+/* ================================================================
+ * Color buffers
+ */
+
+/* RGB565 */
+#define SPANTMP_PIXEL_FMT GL_RGB
+#define SPANTMP_PIXEL_TYPE GL_UNSIGNED_SHORT_5_6_5
+
+#define TAG(x) nouveau##x##_RGB565
+#define TAG2(x,y) nouveau##x##_RGB565##y
+#define GET_PTR(X,Y) (map + (Y)*nrb->pitch + (X)*nrb->cpp)
+#include "spantmp2.h"
+
+
+/* ARGB8888 */
+#define SPANTMP_PIXEL_FMT GL_BGRA
+#define SPANTMP_PIXEL_TYPE GL_UNSIGNED_INT_8_8_8_8_REV
+
+#define TAG(x) nouveau##x##_ARGB8888
+#define TAG2(x,y) nouveau##x##_ARGB8888##y
+#define GET_PTR(X,Y) (map + (Y)*nrb->pitch + (X)*nrb->cpp)
+#include "spantmp2.h"
+
+static void
+nouveauSpanRenderStart( GLcontext *ctx )
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ FIRE_RING();
+ LOCK_HARDWARE(nmesa);
+ nouveauWaitForIdleLocked( nmesa );
+}
+
+static void
+nouveauSpanRenderFinish( GLcontext *ctx )
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ _swrast_flush( ctx );
+ nouveauWaitForIdleLocked( nmesa );
+ UNLOCK_HARDWARE( nmesa );
+}
+
+void nouveauSpanInitFunctions( GLcontext *ctx )
+{
+ struct swrast_device_driver *swdd = _swrast_GetDeviceDriverReference(ctx);
+ swdd->SpanRenderStart = nouveauSpanRenderStart;
+ swdd->SpanRenderFinish = nouveauSpanRenderFinish;
+}
+
+
+/**
+ * Plug in the Get/Put routines for the given driRenderbuffer.
+ */
+void
+nouveauSpanSetFunctions(nouveau_renderbuffer *nrb, const GLvisual *vis)
+{
+ if (nrb->mesa._ActualFormat == GL_RGBA8)
+ nouveauInitPointers_ARGB8888(&nrb->mesa);
+ else if (nrb->mesa._ActualFormat == GL_RGB5)
+ nouveauInitPointers_RGB565(&nrb->mesa);
+}
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_span.h b/src/mesa/drivers/dri/nouveau/nouveau_span.h
new file mode 100644
index 0000000000..bc39ecd17b
--- /dev/null
+++ b/src/mesa/drivers/dri/nouveau/nouveau_span.h
@@ -0,0 +1,39 @@
+/**************************************************************************
+
+Copyright 2006 Stephane Marchesin
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+
+
+#ifndef __NOUVEAU_SPAN_H__
+#define __NOUVEAU_SPAN_H__
+
+#include "drirenderbuffer.h"
+#include "nouveau_buffers.h"
+
+extern void nouveauSpanInitFunctions( GLcontext *ctx );
+extern void nouveauSpanSetFunctions(nouveau_renderbuffer *nrb, const GLvisual *vis);
+
+#endif /* __NOUVEAU_SPAN_H__ */
+
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_state.c b/src/mesa/drivers/dri/nouveau/nouveau_state.c
new file mode 100644
index 0000000000..8d3c018dff
--- /dev/null
+++ b/src/mesa/drivers/dri/nouveau/nouveau_state.c
@@ -0,0 +1,341 @@
+/**************************************************************************
+
+Copyright 2006 Jeremy Kolb
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+#include "nouveau_context.h"
+#include "nouveau_state.h"
+#include "nouveau_swtcl.h"
+#include "nouveau_fifo.h"
+
+#include "swrast/swrast.h"
+#include "tnl/tnl.h"
+#include "swrast_setup/swrast_setup.h"
+
+#include "tnl/t_pipeline.h"
+
+#include "mtypes.h"
+#include "colormac.h"
+
+static __inline__ GLuint nouveauPackColor(GLuint format,
+ GLubyte r, GLubyte g,
+ GLubyte b, GLubyte a)
+{
+ switch (format) {
+ case 2:
+ return PACK_COLOR_565( r, g, b );
+ case 4:
+ return PACK_COLOR_8888( r, g, b, a);
+ default:
+ fprintf(stderr, "unknown format %d\n", (int)format);
+ return 0;
+ }
+}
+
+static void nouveauCalcViewport(GLcontext *ctx)
+{
+ /* Calculate the Viewport Matrix */
+
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ const GLfloat *v = ctx->Viewport._WindowMap.m;
+ GLfloat *m = nmesa->viewport.m;
+ GLfloat xoffset = nmesa->drawX, yoffset = nmesa->drawY;
+
+ nmesa->depth_scale = 1.0 / ctx->DrawBuffer->_DepthMaxF;
+
+ m[MAT_SX] = v[MAT_SX];
+ m[MAT_TX] = v[MAT_TX] + xoffset + SUBPIXEL_X;
+ m[MAT_SY] = - v[MAT_SY];
+ m[MAT_TY] = v[MAT_TY] + yoffset + SUBPIXEL_Y;
+ m[MAT_SZ] = v[MAT_SZ] * nmesa->depth_scale;
+ m[MAT_TZ] = v[MAT_TZ] * nmesa->depth_scale;
+
+ nmesa->hw_func.WindowMoved(nmesa);
+}
+
+static void nouveauViewport(GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h)
+{
+ /*
+ * Need to send (at least on an nv35 the following:
+ * cons = 4 (this may be bytes per pixel)
+ *
+ * The viewport:
+ * 445 0x0000bee0 {size: 0x0 channel: 0x1 cmd: 0x00009ee0} <-- VIEWPORT_SETUP/HEADER ?
+ * 446 0x00000000 {size: 0x0 channel: 0x0 cmd: 0x00000000} <-- x * cons
+ * 447 0x00000c80 {size: 0x0 channel: 0x0 cmd: 0x00000c80} <-- (height + x) * cons
+ * 448 0x00000000 {size: 0x0 channel: 0x0 cmd: 0x00000000} <-- y * cons
+ * 449 0x00000960 {size: 0x0 channel: 0x0 cmd: 0x00000960} <-- (width + y) * cons
+ * 44a 0x00082a00 {size: 0x2 channel: 0x1 cmd: 0x00000a00} <-- VIEWPORT_DIMS
+ * 44b 0x04000000 <-- (Width_from_glViewport << 16) | x
+ * 44c 0x03000000 <-- (Height_from_glViewport << 16) | (win_height - height - y)
+ *
+ */
+
+ nouveauCalcViewport(ctx);
+}
+
+static void nouveauDepthRange(GLcontext *ctx, GLclampd near, GLclampd far)
+{
+ nouveauCalcViewport(ctx);
+}
+
+static void nouveauDDUpdateHWState(GLcontext *ctx)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ int new_state = nmesa->new_state;
+
+ if ( new_state || nmesa->new_render_state & _NEW_TEXTURE )
+ {
+ nmesa->new_state = 0;
+
+ /* Update the various parts of the context's state.
+ */
+ /*
+ if ( new_state & NOUVEAU_NEW_ALPHA )
+ nouveauUpdateAlphaMode( ctx );
+
+ if ( new_state & NOUVEAU_NEW_DEPTH )
+ nouveauUpdateZMode( ctx );
+
+ if ( new_state & NOUVEAU_NEW_FOG )
+ nouveauUpdateFogAttrib( ctx );
+
+ if ( new_state & NOUVEAU_NEW_CLIP )
+ nouveauUpdateClipping( ctx );
+
+ if ( new_state & NOUVEAU_NEW_CULL )
+ nouveauUpdateCull( ctx );
+
+ if ( new_state & NOUVEAU_NEW_MASKS )
+ nouveauUpdateMasks( ctx );
+
+ if ( new_state & NOUVEAU_NEW_WINDOW )
+ nouveauUpdateWindow( ctx );
+
+ if ( nmesa->new_render_state & _NEW_TEXTURE ) {
+ nouveauUpdateTextureState( ctx );
+ }*/
+ }
+}
+
+static void nouveauDDInvalidateState(GLcontext *ctx, GLuint new_state)
+{
+ _swrast_InvalidateState( ctx, new_state );
+ _swsetup_InvalidateState( ctx, new_state );
+ _vbo_InvalidateState( ctx, new_state );
+ _tnl_InvalidateState( ctx, new_state );
+ NOUVEAU_CONTEXT(ctx)->new_render_state |= new_state;
+}
+
+/* Initialize the context's hardware state. */
+void nouveauDDInitState(nouveauContextPtr nmesa)
+{
+ uint32_t type = nmesa->screen->card->type;
+ switch(type)
+ {
+ case NV_03:
+ case NV_04:
+ case NV_05:
+ /* No TCL engines for these ones */
+ break;
+ case NV_10:
+ nv10InitStateFuncs(nmesa->glCtx, &nmesa->glCtx->Driver);
+ break;
+ case NV_20:
+ nv20InitStateFuncs(nmesa->glCtx, &nmesa->glCtx->Driver);
+ break;
+ case NV_30:
+ case NV_40:
+ case NV_44:
+ case NV_50:
+ nv30InitStateFuncs(nmesa->glCtx, &nmesa->glCtx->Driver);
+ break;
+ default:
+ break;
+ }
+ nouveau_state_cache_init(nmesa);
+}
+
+/* Initialize the driver's state functions */
+void nouveauDDInitStateFuncs(GLcontext *ctx)
+{
+ ctx->Driver.UpdateState = nouveauDDInvalidateState;
+
+ ctx->Driver.ClearIndex = NULL;
+ ctx->Driver.ClearColor = NULL; //nouveauDDClearColor;
+ ctx->Driver.ClearStencil = NULL; //nouveauDDClearStencil;
+ ctx->Driver.DrawBuffer = NULL; //nouveauDDDrawBuffer;
+ ctx->Driver.ReadBuffer = NULL; //nouveauDDReadBuffer;
+
+ ctx->Driver.IndexMask = NULL;
+ ctx->Driver.ColorMask = NULL; //nouveauDDColorMask;
+ ctx->Driver.AlphaFunc = NULL; //nouveauDDAlphaFunc;
+ ctx->Driver.BlendEquationSeparate = NULL; //nouveauDDBlendEquationSeparate;
+ ctx->Driver.BlendFuncSeparate = NULL; //nouveauDDBlendFuncSeparate;
+ ctx->Driver.ClearDepth = NULL; //nouveauDDClearDepth;
+ ctx->Driver.CullFace = NULL; //nouveauDDCullFace;
+ ctx->Driver.FrontFace = NULL; //nouveauDDFrontFace;
+ ctx->Driver.DepthFunc = NULL; //nouveauDDDepthFunc;
+ ctx->Driver.DepthMask = NULL; //nouveauDDDepthMask;
+ ctx->Driver.Enable = NULL; //nouveauDDEnable;
+ ctx->Driver.Fogfv = NULL; //nouveauDDFogfv;
+ ctx->Driver.Hint = NULL;
+ ctx->Driver.Lightfv = NULL;
+ ctx->Driver.LightModelfv = NULL; //nouveauDDLightModelfv;
+ ctx->Driver.LogicOpcode = NULL; //nouveauDDLogicOpCode;
+ ctx->Driver.PolygonMode = NULL;
+ ctx->Driver.PolygonStipple = NULL; //nouveauDDPolygonStipple;
+ ctx->Driver.RenderMode = NULL; //nouveauDDRenderMode;
+ ctx->Driver.Scissor = NULL; //nouveauDDScissor;
+ ctx->Driver.ShadeModel = NULL; //nouveauDDShadeModel;
+ ctx->Driver.StencilFuncSeparate = NULL; //nouveauDDStencilFuncSeparate;
+ ctx->Driver.StencilMaskSeparate = NULL; //nouveauDDStencilMaskSeparate;
+ ctx->Driver.StencilOpSeparate = NULL; //nouveauDDStencilOpSeparate;
+
+ ctx->Driver.DepthRange = nouveauDepthRange;
+ ctx->Driver.Viewport = nouveauViewport;
+
+ /* Pixel path fallbacks.
+ */
+ ctx->Driver.Accum = _swrast_Accum;
+ ctx->Driver.Bitmap = _swrast_Bitmap;
+ ctx->Driver.CopyPixels = _swrast_CopyPixels;
+ ctx->Driver.DrawPixels = _swrast_DrawPixels;
+ ctx->Driver.ReadPixels = _swrast_ReadPixels;
+
+ /* Swrast hooks for imaging extensions:
+ */
+ ctx->Driver.CopyColorTable = _swrast_CopyColorTable;
+ ctx->Driver.CopyColorSubTable = _swrast_CopyColorSubTable;
+ ctx->Driver.CopyConvolutionFilter1D = _swrast_CopyConvolutionFilter1D;
+ ctx->Driver.CopyConvolutionFilter2D = _swrast_CopyConvolutionFilter2D;
+}
+
+#define STATE_INIT(a) if (ctx->Driver.a) ctx->Driver.a
+
+void nouveauInitState(GLcontext *ctx)
+{
+ /*
+ * Mesa should do this for us:
+ */
+
+ STATE_INIT(AlphaFunc)( ctx,
+ ctx->Color.AlphaFunc,
+ ctx->Color.AlphaRef);
+
+ STATE_INIT(BlendColor)( ctx,
+ ctx->Color.BlendColor );
+
+ STATE_INIT(BlendEquationSeparate)( ctx,
+ ctx->Color.BlendEquationRGB,
+ ctx->Color.BlendEquationA);
+
+ STATE_INIT(BlendFuncSeparate)( ctx,
+ ctx->Color.BlendSrcRGB,
+ ctx->Color.BlendDstRGB,
+ ctx->Color.BlendSrcA,
+ ctx->Color.BlendDstA);
+
+ STATE_INIT(ClearColor)( ctx, ctx->Color.ClearColor);
+ STATE_INIT(ClearDepth)( ctx, ctx->Depth.Clear);
+ STATE_INIT(ClearStencil)( ctx, ctx->Stencil.Clear);
+
+ STATE_INIT(ColorMask)( ctx,
+ ctx->Color.ColorMask[RCOMP],
+ ctx->Color.ColorMask[GCOMP],
+ ctx->Color.ColorMask[BCOMP],
+ ctx->Color.ColorMask[ACOMP]);
+
+ STATE_INIT(CullFace)( ctx, ctx->Polygon.CullFaceMode );
+ STATE_INIT(DepthFunc)( ctx, ctx->Depth.Func );
+ STATE_INIT(DepthMask)( ctx, ctx->Depth.Mask );
+
+ STATE_INIT(Enable)( ctx, GL_ALPHA_TEST, ctx->Color.AlphaEnabled );
+ STATE_INIT(Enable)( ctx, GL_BLEND, ctx->Color.BlendEnabled );
+ STATE_INIT(Enable)( ctx, GL_COLOR_LOGIC_OP, ctx->Color.ColorLogicOpEnabled );
+ STATE_INIT(Enable)( ctx, GL_COLOR_SUM, ctx->Fog.ColorSumEnabled );
+ STATE_INIT(Enable)( ctx, GL_CULL_FACE, ctx->Polygon.CullFlag );
+ STATE_INIT(Enable)( ctx, GL_DEPTH_TEST, ctx->Depth.Test );
+ STATE_INIT(Enable)( ctx, GL_DITHER, ctx->Color.DitherFlag );
+ STATE_INIT(Enable)( ctx, GL_FOG, ctx->Fog.Enabled );
+ STATE_INIT(Enable)( ctx, GL_LIGHTING, ctx->Light.Enabled );
+ STATE_INIT(Enable)( ctx, GL_LINE_SMOOTH, ctx->Line.SmoothFlag );
+ STATE_INIT(Enable)( ctx, GL_LINE_STIPPLE, ctx->Line.StippleFlag );
+ STATE_INIT(Enable)( ctx, GL_POINT_SMOOTH, ctx->Point.SmoothFlag );
+ STATE_INIT(Enable)( ctx, GL_POLYGON_OFFSET_FILL, ctx->Polygon.OffsetFill);
+ STATE_INIT(Enable)( ctx, GL_POLYGON_OFFSET_LINE, ctx->Polygon.OffsetLine);
+ STATE_INIT(Enable)( ctx, GL_POLYGON_OFFSET_POINT, ctx->Polygon.OffsetPoint);
+ STATE_INIT(Enable)( ctx, GL_POLYGON_SMOOTH, ctx->Polygon.SmoothFlag );
+ STATE_INIT(Enable)( ctx, GL_POLYGON_STIPPLE, ctx->Polygon.StippleFlag );
+ STATE_INIT(Enable)( ctx, GL_SCISSOR_TEST, ctx->Scissor.Enabled );
+ STATE_INIT(Enable)( ctx, GL_STENCIL_TEST, ctx->Stencil.Enabled );
+ STATE_INIT(Enable)( ctx, GL_TEXTURE_1D, GL_FALSE );
+ STATE_INIT(Enable)( ctx, GL_TEXTURE_2D, GL_FALSE );
+ STATE_INIT(Enable)( ctx, GL_TEXTURE_RECTANGLE_NV, GL_FALSE );
+ STATE_INIT(Enable)( ctx, GL_TEXTURE_3D, GL_FALSE );
+ STATE_INIT(Enable)( ctx, GL_TEXTURE_CUBE_MAP, GL_FALSE );
+
+ STATE_INIT(Fogfv)( ctx, GL_FOG_COLOR, ctx->Fog.Color );
+ STATE_INIT(Fogfv)( ctx, GL_FOG_MODE, 0 );
+ STATE_INIT(Fogfv)( ctx, GL_FOG_DENSITY, &ctx->Fog.Density );
+ STATE_INIT(Fogfv)( ctx, GL_FOG_START, &ctx->Fog.Start );
+ STATE_INIT(Fogfv)( ctx, GL_FOG_END, &ctx->Fog.End );
+
+ STATE_INIT(FrontFace)( ctx, ctx->Polygon.FrontFace );
+
+ {
+ GLfloat f = (GLfloat)ctx->Light.Model.ColorControl;
+ STATE_INIT(LightModelfv)( ctx, GL_LIGHT_MODEL_COLOR_CONTROL, &f );
+ }
+
+ STATE_INIT(LineStipple)( ctx, ctx->Line.StippleFactor, ctx->Line.StipplePattern );
+ STATE_INIT(LineWidth)( ctx, ctx->Line.Width );
+ STATE_INIT(LogicOpcode)( ctx, ctx->Color.LogicOp );
+ STATE_INIT(PointSize)( ctx, ctx->Point.Size );
+ STATE_INIT(PolygonMode)( ctx, GL_FRONT, ctx->Polygon.FrontMode );
+ STATE_INIT(PolygonMode)( ctx, GL_BACK, ctx->Polygon.BackMode );
+ STATE_INIT(PolygonOffset)( ctx,
+ ctx->Polygon.OffsetFactor,
+ ctx->Polygon.OffsetUnits );
+ STATE_INIT(PolygonStipple)( ctx, (const GLubyte *)ctx->PolygonStipple );
+ STATE_INIT(ShadeModel)( ctx, ctx->Light.ShadeModel );
+ STATE_INIT(StencilFuncSeparate)( ctx, GL_FRONT,
+ ctx->Stencil.Function[0],
+ ctx->Stencil.Ref[0],
+ ctx->Stencil.ValueMask[0] );
+ STATE_INIT(StencilFuncSeparate)( ctx, GL_BACK,
+ ctx->Stencil.Function[1],
+ ctx->Stencil.Ref[1],
+ ctx->Stencil.ValueMask[1] );
+ STATE_INIT(StencilMaskSeparate)( ctx, GL_FRONT, ctx->Stencil.WriteMask[0] );
+ STATE_INIT(StencilMaskSeparate)( ctx, GL_BACK, ctx->Stencil.WriteMask[1] );
+ STATE_INIT(StencilOpSeparate)( ctx, GL_FRONT,
+ ctx->Stencil.FailFunc[0],
+ ctx->Stencil.ZFailFunc[0],
+ ctx->Stencil.ZPassFunc[0]);
+ STATE_INIT(StencilOpSeparate)( ctx, GL_BACK,
+ ctx->Stencil.FailFunc[1],
+ ctx->Stencil.ZFailFunc[1],
+ ctx->Stencil.ZPassFunc[1]);
+}
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_state.h b/src/mesa/drivers/dri/nouveau/nouveau_state.h
new file mode 100644
index 0000000000..16d63a6ac2
--- /dev/null
+++ b/src/mesa/drivers/dri/nouveau/nouveau_state.h
@@ -0,0 +1,48 @@
+/**************************************************************************
+
+Copyright 2006 Jeremy Kolb
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+#ifndef __NOUVEAU_STATE_H__
+#define __NOUVEAU_STATE_H__
+
+#include "nouveau_context.h"
+
+extern void nouveauDDInitState(nouveauContextPtr nmesa);
+extern void nouveauDDInitStateFuncs(GLcontext *ctx);
+
+extern void nv10InitStateFuncs(GLcontext *ctx, struct dd_function_table *func);
+extern void nv20InitStateFuncs(GLcontext *ctx, struct dd_function_table *func);
+extern void nv30InitStateFuncs(GLcontext *ctx, struct dd_function_table *func);
+
+extern void nouveauInitState(GLcontext *ctx);
+
+/*
+extern void nouveauDDUpdateState(GLcontext *ctx);
+extern void nouveauDDUpdateHWState(GLcontext *ctx);
+
+extern void nouveauEmitHwStateLocked(nouveauContextPtr nmesa);
+*/
+#endif
+
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_state_cache.c b/src/mesa/drivers/dri/nouveau/nouveau_state_cache.c
new file mode 100644
index 0000000000..cb4b9d3027
--- /dev/null
+++ b/src/mesa/drivers/dri/nouveau/nouveau_state_cache.c
@@ -0,0 +1,69 @@
+
+#include "nouveau_state_cache.h"
+#include "nouveau_context.h"
+#include "nouveau_object.h"
+#include "nouveau_fifo.h"
+
+#define BEGIN_RING_NOFLUSH(subchannel,tag,size) do { \
+ if (nmesa->fifo.free <= (size)) \
+ WAIT_RING(nmesa,(size)); \
+ OUT_RING( ((size)<<18) | ((subchannel) << 13) | (tag)); \
+ nmesa->fifo.free -= ((size) + 1); \
+}while(0)
+
+// flush all the dirty state
+void nouveau_state_cache_flush(nouveauContextPtr nmesa)
+{
+ int i=0;
+ int run=0;
+
+ // fast-path no state changes
+ if (!nmesa->state_cache.dirty)
+ return;
+ nmesa->state_cache.dirty=0;
+
+ do
+ {
+ // jump to a dirty state
+ while((nmesa->state_cache.hdirty[i/NOUVEAU_STATE_CACHE_HIER_SIZE]==0)&&(i<NOUVEAU_STATE_CACHE_ENTRIES))
+ i=(i&~(NOUVEAU_STATE_CACHE_HIER_SIZE-1))+NOUVEAU_STATE_CACHE_HIER_SIZE;
+ while((nmesa->state_cache.atoms[i].dirty==0)&&(i<NOUVEAU_STATE_CACHE_ENTRIES))
+ i++;
+
+ // figure out a run of dirty values
+ run=0;
+ while((nmesa->state_cache.atoms[i+run].dirty)&&(i+run<NOUVEAU_STATE_CACHE_ENTRIES))
+ run++;
+
+ // output everything as a single run
+ if (run>0) {
+ int j;
+
+ BEGIN_RING_NOFLUSH(NvSub3D, i*4, run);
+ for(j=0;j<run;j++)
+ {
+ OUT_RING(nmesa->state_cache.atoms[i+j].value);
+ nmesa->state_cache.atoms[i+j].dirty=0;
+ if ((i+j)%NOUVEAU_STATE_CACHE_HIER_SIZE==0)
+ nmesa->state_cache.hdirty[(i+j)/NOUVEAU_STATE_CACHE_HIER_SIZE-1]=0;
+ }
+ i+=run;
+ }
+ }
+ while(i<NOUVEAU_STATE_CACHE_ENTRIES);
+ nmesa->state_cache.hdirty[NOUVEAU_STATE_CACHE_HIER_SIZE/NOUVEAU_STATE_CACHE_HIER_SIZE-1]=0;
+}
+
+
+// inits the state cache
+void nouveau_state_cache_init(nouveauContextPtr nmesa)
+{
+ int i;
+ for(i=0;i<NOUVEAU_STATE_CACHE_ENTRIES;i++)
+ {
+ nmesa->state_cache.atoms[i].dirty=0;
+ nmesa->state_cache.atoms[i].value=0xDEADBEEF; // nvidia cards like beef
+ }
+ nmesa->state_cache.dirty=0;
+}
+
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_state_cache.h b/src/mesa/drivers/dri/nouveau/nouveau_state_cache.h
new file mode 100644
index 0000000000..5f9d426450
--- /dev/null
+++ b/src/mesa/drivers/dri/nouveau/nouveau_state_cache.h
@@ -0,0 +1,29 @@
+
+#ifndef __NOUVEAU_STATE_CACHE_H__
+#define __NOUVEAU_STATE_CACHE_H__
+
+#include "mtypes.h"
+
+#define NOUVEAU_STATE_CACHE_ENTRIES 2048
+// size of a dirty requests block
+// you can play with that and tune the value to increase/decrease performance
+// but keep it a power of 2 !
+#define NOUVEAU_STATE_CACHE_HIER_SIZE 32
+
+typedef struct nouveau_state_atom_t{
+ uint32_t value;
+ uint32_t dirty;
+}nouveau_state_atom;
+
+typedef struct nouveau_state_cache_t{
+ nouveau_state_atom atoms[NOUVEAU_STATE_CACHE_ENTRIES];
+ uint32_t current_pos;
+ // hierarchical dirty flags
+ uint8_t hdirty[NOUVEAU_STATE_CACHE_ENTRIES/NOUVEAU_STATE_CACHE_HIER_SIZE];
+ // master dirty flag
+ uint8_t dirty;
+}nouveau_state_cache;
+
+
+#endif
+
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_swtcl.c b/src/mesa/drivers/dri/nouveau/nouveau_swtcl.c
new file mode 100644
index 0000000000..f5c92a1b4e
--- /dev/null
+++ b/src/mesa/drivers/dri/nouveau/nouveau_swtcl.c
@@ -0,0 +1,127 @@
+/**************************************************************************
+
+Copyright 2006 Stephane Marchesin
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/* Common software TCL code */
+
+#include "nouveau_context.h"
+#include "nouveau_swtcl.h"
+#include "nv10_swtcl.h"
+#include "nouveau_span.h"
+#include "swrast/swrast.h"
+#include "swrast_setup/swrast_setup.h"
+#include "tnl/tnl.h"
+#include "tnl/t_pipeline.h"
+
+/* Common tri functions */
+
+/* The fallbacks */
+void nouveau_fallback_tri(struct nouveau_context *nmesa,
+ nouveauVertex *v0,
+ nouveauVertex *v1,
+ nouveauVertex *v2)
+{
+ GLcontext *ctx = nmesa->glCtx;
+ SWvertex v[3];
+ _swsetup_Translate(ctx, v0, &v[0]);
+ _swsetup_Translate(ctx, v1, &v[1]);
+ _swsetup_Translate(ctx, v2, &v[2]);
+ _swrast_Triangle(ctx, &v[0], &v[1], &v[2]);
+}
+
+
+void nouveau_fallback_line(struct nouveau_context *nmesa,
+ nouveauVertex *v0,
+ nouveauVertex *v1)
+{
+ GLcontext *ctx = nmesa->glCtx;
+ SWvertex v[2];
+ _swsetup_Translate(ctx, v0, &v[0]);
+ _swsetup_Translate(ctx, v1, &v[1]);
+ _swrast_Line(ctx, &v[0], &v[1]);
+}
+
+
+void nouveau_fallback_point(struct nouveau_context *nmesa,
+ nouveauVertex *v0)
+{
+ GLcontext *ctx = nmesa->glCtx;
+ SWvertex v[1];
+ _swsetup_Translate(ctx, v0, &v[0]);
+ _swrast_Point(ctx, &v[0]);
+}
+
+void nouveauFallback(struct nouveau_context *nmesa, GLuint bit, GLboolean mode)
+{
+ GLcontext *ctx = nmesa->glCtx;
+ GLuint oldfallback = nmesa->Fallback;
+
+ if (mode) {
+ nmesa->Fallback |= bit;
+ if (oldfallback == 0) {
+ if (nmesa->screen->card->type<NV_10) {
+ //nv04FinishPrimitive(nmesa);
+ } else {
+ nv10FinishPrimitive(nmesa);
+ }
+
+ _swsetup_Wakeup(ctx);
+ nmesa->render_index = ~0;
+ }
+ }
+ else {
+ nmesa->Fallback &= ~bit;
+ if (oldfallback == bit) {
+ _swrast_flush( ctx );
+
+ if (nmesa->screen->card->type<NV_10) {
+ //nv04TriInitFunctions(ctx);
+ } else {
+ nv10TriInitFunctions(ctx);
+ }
+
+ _tnl_invalidate_vertex_state( ctx, ~0 );
+ _tnl_invalidate_vertices( ctx, ~0 );
+ _tnl_install_attrs( ctx,
+ nmesa->vertex_attrs,
+ nmesa->vertex_attr_count,
+ nmesa->viewport.m, 0 );
+ }
+ }
+}
+
+
+void nouveauRunPipeline( GLcontext *ctx )
+{
+ struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx);
+
+ if (nmesa->new_state) {
+ nmesa->new_render_state |= nmesa->new_state;
+ }
+
+ _tnl_run_pipeline( ctx );
+}
+
+
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_swtcl.h b/src/mesa/drivers/dri/nouveau/nouveau_swtcl.h
new file mode 100644
index 0000000000..ba4d8725a6
--- /dev/null
+++ b/src/mesa/drivers/dri/nouveau/nouveau_swtcl.h
@@ -0,0 +1,55 @@
+/**************************************************************************
+
+Copyright 2006 Stephane Marchesin
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+
+
+#ifndef __NOUVEAU_SWTCL_H__
+#define __NOUVEAU_SWTCL_H__
+
+#include "nouveau_context.h"
+
+extern void nouveau_fallback_tri(struct nouveau_context *nmesa,
+ nouveauVertex *v0,
+ nouveauVertex *v1,
+ nouveauVertex *v2);
+
+extern void nouveau_fallback_line(struct nouveau_context *nmesa,
+ nouveauVertex *v0,
+ nouveauVertex *v1);
+
+extern void nouveau_fallback_point(struct nouveau_context *nmesa,
+ nouveauVertex *v0);
+
+extern void nouveauFallback(struct nouveau_context *nmesa, GLuint bit, GLboolean mode);
+
+extern void nouveauRunPipeline( GLcontext *ctx );
+
+extern void nouveauTriInitFunctions( GLcontext *ctx );
+
+
+#endif /* __NOUVEAU_SWTCL_H__ */
+
+
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_sync.c b/src/mesa/drivers/dri/nouveau/nouveau_sync.c
new file mode 100644
index 0000000000..0bf20e723b
--- /dev/null
+++ b/src/mesa/drivers/dri/nouveau/nouveau_sync.c
@@ -0,0 +1,136 @@
+#include "vblank.h" /* for DO_USLEEP */
+
+#include "nouveau_context.h"
+#include "nouveau_buffers.h"
+#include "nouveau_object.h"
+#include "nouveau_fifo.h"
+#include "nouveau_reg.h"
+#include "nouveau_msg.h"
+#include "nouveau_sync.h"
+
+nouveau_notifier *
+nouveau_notifier_new(GLcontext *ctx, GLuint handle)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ nouveau_notifier *notifier;
+
+ notifier = CALLOC_STRUCT(nouveau_notifier_t);
+ if (!notifier)
+ return NULL;
+
+ notifier->mem = nouveau_mem_alloc(ctx,
+ NOUVEAU_MEM_FB | NOUVEAU_MEM_MAPPED,
+ 32,
+ 0);
+ if (!notifier->mem) {
+ FREE(notifier);
+ return NULL;
+ }
+
+ if (!nouveauCreateDmaObject(nmesa, handle, notifier->mem->offset,
+ notifier->mem->size,
+ 0 /* NV_DMA_TARGET_FB */,
+ 0 /* NV_DMA_ACCESS_RW */)) {
+ nouveau_mem_free(ctx, notifier->mem);
+ FREE(notifier);
+ return NULL;
+ }
+
+ notifier->handle = handle;
+ return notifier;
+}
+
+void
+nouveau_notifier_destroy(GLcontext *ctx, nouveau_notifier *notifier)
+{
+ /*XXX: free DMA object.. */
+ nouveau_mem_free(ctx, notifier->mem);
+ FREE(notifier);
+}
+
+void
+nouveau_notifier_reset(nouveau_notifier *notifier)
+{
+ volatile GLuint *n = notifier->mem->map;
+
+ n[NV_NOTIFY_TIME_0 /4] = 0x00000000;
+ n[NV_NOTIFY_TIME_1 /4] = 0x00000000;
+ n[NV_NOTIFY_RETURN_VALUE/4] = 0x00000000;
+ n[NV_NOTIFY_STATE /4] = (NV_NOTIFY_STATE_STATUS_IN_PROCESS <<
+ NV_NOTIFY_STATE_STATUS_SHIFT);
+}
+
+GLboolean
+nouveau_notifier_wait_status(nouveau_notifier *notifier, GLuint status,
+ GLuint timeout)
+{
+ volatile GLuint *n = notifier->mem->map;
+ unsigned int time = 0;
+
+ while (time <= timeout) {
+ if (n[NV_NOTIFY_STATE/4] & NV_NOTIFY_STATE_ERROR_CODE_MASK) {
+ MESSAGE("Notifier returned error: 0x%04x\n",
+ n[NV_NOTIFY_STATE] &
+ NV_NOTIFY_STATE_ERROR_CODE_MASK);
+ return GL_FALSE;
+ }
+
+ if (((n[NV_NOTIFY_STATE/4] & NV_NOTIFY_STATE_STATUS_MASK) >>
+ NV_NOTIFY_STATE_STATUS_SHIFT) == status)
+ return GL_TRUE;
+
+ if (timeout) {
+ DO_USLEEP(1);
+ time++;
+ }
+ }
+
+ MESSAGE("Notifier timed out\n");
+ return GL_FALSE;
+}
+
+void
+nouveau_notifier_wait_nop(GLcontext *ctx, nouveau_notifier *notifier,
+ GLuint subc)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ GLboolean ret;
+
+ nouveau_notifier_reset(notifier);
+
+ BEGIN_RING_SIZE(subc, NV_NOTIFY, 1);
+ OUT_RING (NV_NOTIFY_STYLE_WRITE_ONLY);
+ BEGIN_RING_SIZE(subc, NV_NOP, 1);
+ OUT_RING (0);
+ FIRE_RING();
+
+ ret = nouveau_notifier_wait_status(notifier,
+ NV_NOTIFY_STATE_STATUS_COMPLETED,
+ 0 /* no timeout */);
+ if (ret == GL_FALSE) MESSAGE("wait on notifier failed\n");
+}
+
+GLboolean nouveauSyncInitFuncs(GLcontext *ctx)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+
+ nmesa->syncNotifier = nouveau_notifier_new(ctx, NvSyncNotify);
+ if (!nmesa->syncNotifier) {
+ MESSAGE("Failed to create channel sync notifier\n");
+ return GL_FALSE;
+ }
+
+ /* 0x180 is SET_DMA_NOTIFY, should be correct for all supported 3D
+ * object classes
+ */
+ BEGIN_RING_CACHE(NvSub3D, 0x180, 1);
+ OUT_RING_CACHE (NvSyncNotify);
+#ifdef ALLOW_MULTI_SUBCHANNEL
+ BEGIN_RING_SIZE(NvSubMemFormat,
+ NV_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 1);
+ OUT_RING (NvSyncNotify);
+#endif
+
+ return GL_TRUE;
+}
+
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_sync.h b/src/mesa/drivers/dri/nouveau/nouveau_sync.h
new file mode 100644
index 0000000000..d9e3d4b80c
--- /dev/null
+++ b/src/mesa/drivers/dri/nouveau/nouveau_sync.h
@@ -0,0 +1,36 @@
+#ifndef __NOUVEAU_SYNC_H__
+#define __NOUVEAU_SYNC_H__
+
+#include "nouveau_buffers.h"
+
+#define NV_NOTIFY_TIME_0 0x00000000
+#define NV_NOTIFY_TIME_1 0x00000004
+#define NV_NOTIFY_RETURN_VALUE 0x00000008
+#define NV_NOTIFY_STATE 0x0000000C
+#define NV_NOTIFY_STATE_STATUS_MASK 0xFF000000
+#define NV_NOTIFY_STATE_STATUS_SHIFT 24
+#define NV_NOTIFY_STATE_STATUS_COMPLETED 0x00
+#define NV_NOTIFY_STATE_STATUS_IN_PROCESS 0x01
+#define NV_NOTIFY_STATE_ERROR_CODE_MASK 0x0000FFFF
+#define NV_NOTIFY_STATE_ERROR_CODE_SHIFT 0
+
+/* Methods that (hopefully) all objects have */
+#define NV_NOP 0x00000100
+#define NV_NOTIFY 0x00000104
+#define NV_NOTIFY_STYLE_WRITE_ONLY 0
+
+typedef struct nouveau_notifier_t {
+ GLuint handle;
+ nouveau_mem *mem;
+} nouveau_notifier;
+
+extern nouveau_notifier *nouveau_notifier_new(GLcontext *, GLuint handle);
+extern void nouveau_notifier_destroy(GLcontext *, nouveau_notifier *);
+extern void nouveau_notifier_reset(nouveau_notifier *);
+extern GLboolean nouveau_notifier_wait_status(nouveau_notifier *r,
+ GLuint status, GLuint timeout);
+extern void nouveau_notifier_wait_nop(GLcontext *ctx,
+ nouveau_notifier *, GLuint subc);
+
+extern GLboolean nouveauSyncInitFuncs(GLcontext *ctx);
+#endif
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_tex.c b/src/mesa/drivers/dri/nouveau/nouveau_tex.c
new file mode 100644
index 0000000000..0a8d279669
--- /dev/null
+++ b/src/mesa/drivers/dri/nouveau/nouveau_tex.c
@@ -0,0 +1,49 @@
+/**************************************************************************
+
+Copyright 2006 Stephane Marchesin
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+
+#include "nouveau_tex.h"
+
+// XXX needs some love
+void nouveauTexInitFunctions( struct dd_function_table *functions )
+{
+/*
+ functions->TexEnv = nouveauTexEnv;
+ functions->ChooseTextureFormat = nouveauChooseTextureFormat;
+ functions->TexImage1D = nouveauTexImage1D;
+ functions->TexSubImage1D = nouveauTexSubImage1D;
+ functions->TexImage2D = nouveauTexImage2D;
+ functions->TexSubImage2D = nouveauTexSubImage2D;
+ functions->TexParameter = nouveauTexParameter;
+ functions->BindTexture = nouveauBindTexture;
+ functions->NewTextureObject = nouveauNewTextureObject;
+ functions->DeleteTexture = nouveauDeleteTexture;
+ functions->IsTextureResident = driIsTextureResident;
+
+ driInitTextureFormats();
+*/
+}
+
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_tex.h b/src/mesa/drivers/dri/nouveau/nouveau_tex.h
new file mode 100644
index 0000000000..7ac71f8300
--- /dev/null
+++ b/src/mesa/drivers/dri/nouveau/nouveau_tex.h
@@ -0,0 +1,38 @@
+/**************************************************************************
+
+Copyright 2006 Stephane Marchesin
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+
+#ifndef __NOUVEAU_TEX_H__
+#define __NOUVEAU_TEX_H__
+
+#include <errno.h>
+#include "mtypes.h"
+#include "macros.h"
+#include "dd.h"
+
+extern void nouveauTexInitFunctions( struct dd_function_table *functions );
+
+#endif /* __NOUVEAU_TEX_H__ */
diff --git a/src/mesa/drivers/dri/nouveau/nv04_swtcl.c b/src/mesa/drivers/dri/nouveau/nv04_swtcl.c
new file mode 100644
index 0000000000..f31c0d692d
--- /dev/null
+++ b/src/mesa/drivers/dri/nouveau/nv04_swtcl.c
@@ -0,0 +1,570 @@
+/*
+ * Copyright 2007 Stephane Marchesin. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sub license,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/* Software TCL for NV04, NV05, NV06 */
+
+#include <stdio.h>
+#include <math.h>
+
+#include "glheader.h"
+#include "context.h"
+#include "mtypes.h"
+#include "macros.h"
+#include "colormac.h"
+#include "enums.h"
+
+#include "swrast/swrast.h"
+#include "swrast_setup/swrast_setup.h"
+#include "tnl/t_context.h"
+#include "tnl/t_pipeline.h"
+
+#include "nouveau_swtcl.h"
+#include "nv04_swtcl.h"
+#include "nouveau_context.h"
+#include "nouveau_span.h"
+#include "nouveau_reg.h"
+#include "nouveau_tex.h"
+#include "nouveau_fifo.h"
+#include "nouveau_msg.h"
+#include "nouveau_object.h"
+
+static void nv04RasterPrimitive( GLcontext *ctx, GLenum rprim, GLuint hwprim );
+static void nv04RenderPrimitive( GLcontext *ctx, GLenum prim );
+static void nv04ResetLineStipple( GLcontext *ctx );
+
+
+static inline void nv04_2triangles(struct nouveau_context *nmesa,nouveauVertex* v0,nouveauVertex* v1,nouveauVertex* v2,nouveauVertex* v3,nouveauVertex* v4,nouveauVertex* v5)
+{
+ BEGIN_RING_SIZE(NvSub3D,NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX(0xA),49);
+ OUT_RINGp(v0,8);
+ OUT_RINGp(v1,8);
+ OUT_RINGp(v2,8);
+ OUT_RINGp(v3,8);
+ OUT_RINGp(v4,8);
+ OUT_RINGp(v5,8);
+ OUT_RING(0xFEDCBA);
+}
+
+static inline void nv04_1triangle(struct nouveau_context *nmesa,nouveauVertex* v0,nouveauVertex* v1,nouveauVertex* v2)
+{
+ BEGIN_RING_SIZE(NvSub3D,NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX(0xD),25);
+ OUT_RINGp(v0,8);
+ OUT_RINGp(v1,8);
+ OUT_RINGp(v2,8);
+ OUT_RING(0xFED);
+}
+
+static inline void nv04_1quad(struct nouveau_context *nmesa,nouveauVertex* v0,nouveauVertex* v1,nouveauVertex* v2,nouveauVertex* v3)
+{
+ BEGIN_RING_SIZE(NvSub3D,NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX(0xC),33);
+ OUT_RINGp(v0,8);
+ OUT_RINGp(v1,8);
+ OUT_RINGp(v2,8);
+ OUT_RINGp(v3,8);
+ OUT_RING(0xFECEDC);
+}
+
+/**********************************************************************/
+/* Render unclipped begin/end objects */
+/**********************************************************************/
+
+static void nv04_render_points_verts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
+{
+ // erm
+}
+
+static void nv04_render_lines_verts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
+{
+ // umm
+}
+
+static void nv04_render_line_strip_verts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
+{
+ // yeah
+}
+
+static void nv04_render_line_loop_verts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
+{
+ // right
+}
+
+static void nv04_render_triangles_verts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
+{
+ struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx);
+ GLubyte *vertptr = (GLubyte *)nmesa->verts;
+ GLuint vertsize = nmesa->vertex_size;
+ int i;
+
+ for(i=start;i<count-5;i+=6)
+ nv04_2triangles(nmesa,
+ (nouveauVertex*)(vertptr+(i+0)*vertsize),
+ (nouveauVertex*)(vertptr+(i+1)*vertsize),
+ (nouveauVertex*)(vertptr+(i+2)*vertsize),
+ (nouveauVertex*)(vertptr+(i+3)*vertsize),
+ (nouveauVertex*)(vertptr+(i+4)*vertsize),
+ (nouveauVertex*)(vertptr+(i+5)*vertsize)
+ );
+ if (i!=count)
+ {
+ nv04_1triangle(nmesa,
+ (nouveauVertex*)(vertptr+(i+0)*vertsize),
+ (nouveauVertex*)(vertptr+(i+1)*vertsize),
+ (nouveauVertex*)(vertptr+(i+2)*vertsize)
+ );
+ i+=3;
+ }
+ if (i!=count)
+ printf("oops\n");
+}
+
+static void nv04_render_tri_strip_verts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
+{
+ struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx);
+ GLubyte *vertptr = (GLubyte *)nmesa->verts;
+ GLuint vertsize = nmesa->vertex_size;
+ uint32_t striptbl[]={0x321210,0x543432,0x765654,0x987876,0xBA9A98,0xDCBCBA,0xFEDEDC};
+ int i,j;
+
+ for(i=start;i<count;i+=14)
+ {
+ int numvert=MIN2(16,count-i);
+ int numtri=numvert-2;
+ if (numvert<3)
+ break;
+
+ BEGIN_RING_SIZE(NvSub3D,NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX(0x0),numvert*8);
+ for(j=0;j<numvert;j++)
+ OUT_RINGp((nouveauVertex*)(vertptr+(i+j)*vertsize),8);
+
+ BEGIN_RING_SIZE(NvSub3D,NV04_DX5_TEXTURED_TRIANGLE_DRAW|NONINC_METHOD,(numtri+1)/2);
+ for(j=0;j<numtri/2;j++)
+ OUT_RING(striptbl[j]);
+ if (numtri%2)
+ OUT_RING(striptbl[numtri/2]&0xFFF);
+ }
+}
+
+static void nv04_render_tri_fan_verts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
+{
+ struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx);
+ GLubyte *vertptr = (GLubyte *)nmesa->verts;
+ GLuint vertsize = nmesa->vertex_size;
+ uint32_t fantbl[]={0x320210,0x540430,0x760650,0x980870,0xBA0A90,0xDC0CB0,0xFE0ED0};
+ int i,j;
+
+ BEGIN_RING_SIZE(NvSub3D,NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX(0x0),8);
+ OUT_RINGp((nouveauVertex*)(vertptr+start*vertsize),8);
+
+ for(i=start+1;i<count;i+=14)
+ {
+ int numvert=MIN2(15,count-i);
+ int numtri=numvert-1;
+ if (numvert<3)
+ break;
+
+ BEGIN_RING_SIZE(NvSub3D,NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX(0x1),numvert*8);
+
+ for(j=0;j<numvert;j++)
+ OUT_RINGp((nouveauVertex*)(vertptr+(i+j)*vertsize),8);
+
+ BEGIN_RING_SIZE(NvSub3D,NV04_DX5_TEXTURED_TRIANGLE_DRAW|NONINC_METHOD,(numtri+1)/2);
+ for(j=0;j<numtri/2;j++)
+ OUT_RING(fantbl[j]);
+ if (numtri%2)
+ OUT_RING(fantbl[numtri/2]&0xFFF);
+ }
+}
+
+static void nv04_render_quads_verts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
+{
+ struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx);
+ GLubyte *vertptr = (GLubyte *)nmesa->verts;
+ GLuint vertsize = nmesa->vertex_size;
+ int i;
+
+ for(i=start;i<count;i+=4)
+ nv04_1quad(nmesa,
+ (nouveauVertex*)(vertptr+(i+0)*vertsize),
+ (nouveauVertex*)(vertptr+(i+1)*vertsize),
+ (nouveauVertex*)(vertptr+(i+2)*vertsize),
+ (nouveauVertex*)(vertptr+(i+3)*vertsize)
+ );
+}
+
+static void nv04_render_noop_verts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
+{
+}
+
+static void (*nv04_render_tab_verts[GL_POLYGON+2])(GLcontext *,
+ GLuint,
+ GLuint,
+ GLuint) =
+{
+ nv04_render_points_verts,
+ nv04_render_lines_verts,
+ nv04_render_line_loop_verts,
+ nv04_render_line_strip_verts,
+ nv04_render_triangles_verts,
+ nv04_render_tri_strip_verts,
+ nv04_render_tri_fan_verts,
+ nv04_render_quads_verts,
+ nv04_render_tri_strip_verts, //nv04_render_quad_strip_verts
+ nv04_render_tri_fan_verts, //nv04_render_poly_verts
+ nv04_render_noop_verts,
+};
+
+
+static void nv04_render_points_elts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
+{
+ // erm
+}
+
+static void nv04_render_lines_elts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
+{
+ // umm
+}
+
+static void nv04_render_line_strip_elts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
+{
+ // yeah
+}
+
+static void nv04_render_line_loop_elts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
+{
+ // right
+}
+
+static void nv04_render_triangles_elts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
+{
+ struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx);
+ GLubyte *vertptr = (GLubyte *)nmesa->verts;
+ GLuint vertsize = nmesa->vertex_size;
+ const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts;
+ int i;
+
+ for(i=start;i<count-5;i+=6)
+ nv04_2triangles(nmesa,
+ (nouveauVertex*)(vertptr+elt[i+0]*vertsize),
+ (nouveauVertex*)(vertptr+elt[i+1]*vertsize),
+ (nouveauVertex*)(vertptr+elt[i+2]*vertsize),
+ (nouveauVertex*)(vertptr+elt[i+3]*vertsize),
+ (nouveauVertex*)(vertptr+elt[i+4]*vertsize),
+ (nouveauVertex*)(vertptr+elt[i+5]*vertsize)
+ );
+ if (i!=count)
+ {
+ nv04_1triangle(nmesa,
+ (nouveauVertex*)(vertptr+elt[i+0]*vertsize),
+ (nouveauVertex*)(vertptr+elt[i+1]*vertsize),
+ (nouveauVertex*)(vertptr+elt[i+2]*vertsize)
+ );
+ i+=3;
+ }
+ if (i!=count)
+ printf("oops\n");
+}
+
+static void nv04_render_tri_strip_elts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
+{
+ struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx);
+ GLubyte *vertptr = (GLubyte *)nmesa->verts;
+ GLuint vertsize = nmesa->vertex_size;
+ uint32_t striptbl[]={0x321210,0x543432,0x765654,0x987876,0xBA9A98,0xDCBCBA,0xFEDEDC};
+ const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts;
+ int i,j;
+
+ for(i=start;i<count;i+=14)
+ {
+ int numvert=MIN2(16,count-i);
+ int numtri=numvert-2;
+ if (numvert<3)
+ break;
+
+ BEGIN_RING_SIZE(NvSub3D,NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX(0x0),numvert*8);
+ for(j=0;j<numvert;j++)
+ OUT_RINGp((nouveauVertex*)(vertptr+elt[i+j]*vertsize),8);
+
+ BEGIN_RING_SIZE(NvSub3D,NV04_DX5_TEXTURED_TRIANGLE_DRAW|NONINC_METHOD,(numtri+1)/2);
+ for(j=0;j<numtri/2;j++)
+ OUT_RING(striptbl[j]);
+ if (numtri%2)
+ OUT_RING(striptbl[numtri/2]&0xFFF);
+ }
+}
+
+static void nv04_render_tri_fan_elts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
+{
+ struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx);
+ GLubyte *vertptr = (GLubyte *)nmesa->verts;
+ GLuint vertsize = nmesa->vertex_size;
+ uint32_t fantbl[]={0x320210,0x540430,0x760650,0x980870,0xBA0A90,0xDC0CB0,0xFE0ED0};
+ const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts;
+ int i,j;
+
+ BEGIN_RING_SIZE(NvSub3D,NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX(0x0),8);
+ OUT_RINGp((nouveauVertex*)(vertptr+elt[start]*vertsize),8);
+
+ for(i=start+1;i<count;i+=14)
+ {
+ int numvert=MIN2(15,count-i);
+ int numtri=numvert-2;
+ if (numvert<3)
+ break;
+
+ BEGIN_RING_SIZE(NvSub3D,NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX(0x1),numvert*8);
+
+ for(j=0;j<numvert;j++)
+ OUT_RINGp((nouveauVertex*)(vertptr+elt[i+j]*vertsize),8);
+
+ BEGIN_RING_SIZE(NvSub3D,NV04_DX5_TEXTURED_TRIANGLE_DRAW|NONINC_METHOD,(numtri+1)/2);
+ for(j=0;j<numtri/2;j++)
+ OUT_RING(fantbl[j]);
+ if (numtri%2)
+ OUT_RING(fantbl[numtri/2]&0xFFF);
+ }
+}
+
+static void nv04_render_quads_elts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
+{
+ struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx);
+ GLubyte *vertptr = (GLubyte *)nmesa->verts;
+ GLuint vertsize = nmesa->vertex_size;
+ const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts;
+ int i;
+
+ for(i=start;i<count;i+=4)
+ nv04_1quad(nmesa,
+ (nouveauVertex*)(vertptr+elt[i+0]*vertsize),
+ (nouveauVertex*)(vertptr+elt[i+1]*vertsize),
+ (nouveauVertex*)(vertptr+elt[i+2]*vertsize),
+ (nouveauVertex*)(vertptr+elt[i+3]*vertsize)
+ );
+}
+
+static void nv04_render_noop_elts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
+{
+}
+
+static void (*nv04_render_tab_elts[GL_POLYGON+2])(GLcontext *,
+ GLuint,
+ GLuint,
+ GLuint) =
+{
+ nv04_render_points_elts,
+ nv04_render_lines_elts,
+ nv04_render_line_loop_elts,
+ nv04_render_line_strip_elts,
+ nv04_render_triangles_elts,
+ nv04_render_tri_strip_elts,
+ nv04_render_tri_fan_elts,
+ nv04_render_quads_elts,
+ nv04_render_tri_strip_elts, // nv04_render_quad_strip_elts,
+ nv04_render_tri_fan_elts, // nv04_render_poly_elts,
+ nv04_render_noop_elts,
+};
+
+
+/**********************************************************************/
+/* Choose render functions */
+/**********************************************************************/
+
+
+#define EMIT_ATTR( ATTR, STYLE ) \
+do { \
+ nmesa->vertex_attrs[nmesa->vertex_attr_count].attrib = (ATTR); \
+ nmesa->vertex_attrs[nmesa->vertex_attr_count].format = (STYLE); \
+ nmesa->vertex_attr_count++; \
+} while (0)
+
+#define EMIT_PAD( N ) \
+do { \
+ nmesa->vertex_attrs[nmesa->vertex_attr_count].attrib = 0; \
+ nmesa->vertex_attrs[nmesa->vertex_attr_count].format = EMIT_PAD; \
+ nmesa->vertex_attrs[nmesa->vertex_attr_count].offset = (N); \
+ nmesa->vertex_attr_count++; \
+} while (0)
+
+
+static void nv04ChooseRenderState(GLcontext *ctx)
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+
+ tnl->Driver.Render.PrimTabVerts = nv04_render_tab_verts;
+ tnl->Driver.Render.PrimTabElts = nv04_render_tab_elts;
+ tnl->Driver.Render.ClippedLine = NULL;
+ tnl->Driver.Render.ClippedPolygon = NULL;
+}
+
+
+
+static inline void nv04OutputVertexFormat(struct nouveau_context* nmesa)
+{
+ GLcontext* ctx=nmesa->glCtx;
+ DECLARE_RENDERINPUTS(index);
+
+ /*
+ * Tell t_vertex about the vertex format
+ */
+ RENDERINPUTS_COPY(index, nmesa->render_inputs_bitset);
+
+ // SX SY SZ INVW
+ // FIXME : we use W instead of INVW, but since W=1 it doesn't matter
+ if (RENDERINPUTS_TEST(index, _TNL_ATTRIB_POS))
+ EMIT_ATTR(_TNL_ATTRIB_POS,EMIT_4F_VIEWPORT);
+ else
+ EMIT_PAD(4*sizeof(float));
+
+ // COLOR
+ if (RENDERINPUTS_TEST(index, _TNL_ATTRIB_COLOR0))
+ EMIT_ATTR(_TNL_ATTRIB_COLOR0,EMIT_4UB_4F_ABGR);
+ else
+ EMIT_PAD(4);
+
+ // SPECULAR
+ if (RENDERINPUTS_TEST(index, _TNL_ATTRIB_COLOR1))
+ EMIT_ATTR(_TNL_ATTRIB_COLOR1,EMIT_4UB_4F_ABGR);
+ else
+ EMIT_PAD(4);
+
+ // TEXTURE
+ if (RENDERINPUTS_TEST(index, _TNL_ATTRIB_TEX0))
+ EMIT_ATTR(_TNL_ATTRIB_TEX0,EMIT_2F);
+ else
+ EMIT_PAD(2*sizeof(float));
+
+ nmesa->vertex_size=_tnl_install_attrs( ctx,
+ nmesa->vertex_attrs,
+ nmesa->vertex_attr_count,
+ ctx->Viewport._WindowMap.m, 0 );
+}
+
+
+static void nv04ChooseVertexState( GLcontext *ctx )
+{
+ struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx);
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ DECLARE_RENDERINPUTS(index);
+
+ RENDERINPUTS_COPY(index, tnl->render_inputs_bitset);
+ if (!RENDERINPUTS_EQUAL(index, nmesa->render_inputs_bitset))
+ {
+ RENDERINPUTS_COPY(nmesa->render_inputs_bitset, index);
+ nv04OutputVertexFormat(nmesa);
+ }
+}
+
+
+/**********************************************************************/
+/* High level hooks for t_vb_render.c */
+/**********************************************************************/
+
+
+static void nv04RenderStart(GLcontext *ctx)
+{
+ struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx);
+
+ if (nmesa->new_state) {
+ nmesa->new_render_state |= nmesa->new_state;
+ }
+
+ if (nmesa->new_render_state) {
+ nv04ChooseVertexState(ctx);
+ nv04ChooseRenderState(ctx);
+ nmesa->new_render_state = 0;
+ }
+}
+
+static void nv04RenderFinish(GLcontext *ctx)
+{
+}
+
+
+/* System to flush dma and emit state changes based on the rasterized
+ * primitive.
+ */
+void nv04RasterPrimitive(GLcontext *ctx,
+ GLenum glprim,
+ GLuint hwprim)
+{
+ struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx);
+
+ assert (!nmesa->new_state);
+
+ if (hwprim != nmesa->current_primitive)
+ {
+ nmesa->current_primitive=hwprim;
+
+ }
+}
+
+static const GLuint hw_prim[GL_POLYGON+1] = {
+ GL_POINTS+1,
+ GL_LINES+1,
+ GL_LINE_STRIP+1,
+ GL_LINE_LOOP+1,
+ GL_TRIANGLES+1,
+ GL_TRIANGLE_STRIP+1,
+ GL_TRIANGLE_FAN+1,
+ GL_QUADS+1,
+ GL_QUAD_STRIP+1,
+ GL_POLYGON+1
+};
+
+/* Callback for mesa:
+ */
+static void nv04RenderPrimitive( GLcontext *ctx, GLuint prim )
+{
+ nv04RasterPrimitive( ctx, prim, hw_prim[prim] );
+}
+
+static void nv04ResetLineStipple( GLcontext *ctx )
+{
+ /* FIXME do something here */
+ WARN_ONCE("Unimplemented nv04ResetLineStipple\n");
+}
+
+
+/**********************************************************************/
+/* Initialization. */
+/**********************************************************************/
+
+void nv04TriInitFunctions(GLcontext *ctx)
+{
+ struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx);
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+
+ tnl->Driver.RunPipeline = nouveauRunPipeline;
+ tnl->Driver.Render.Start = nv04RenderStart;
+ tnl->Driver.Render.Finish = nv04RenderFinish;
+ tnl->Driver.Render.PrimitiveNotify = nv04RenderPrimitive;
+ tnl->Driver.Render.ResetLineStipple = nv04ResetLineStipple;
+ tnl->Driver.Render.BuildVertices = _tnl_build_vertices;
+ tnl->Driver.Render.CopyPV = _tnl_copy_pv;
+ tnl->Driver.Render.Interp = _tnl_interp;
+
+ _tnl_init_vertices( ctx, ctx->Const.MaxArrayLockSize + 12, 32 );
+
+ nmesa->verts = (GLubyte *)tnl->clipspace.vertex_buf;
+}
+
+
diff --git a/src/mesa/drivers/dri/nouveau/nv04_swtcl.h b/src/mesa/drivers/dri/nouveau/nv04_swtcl.h
new file mode 100644
index 0000000000..42dde5383e
--- /dev/null
+++ b/src/mesa/drivers/dri/nouveau/nv04_swtcl.h
@@ -0,0 +1,12 @@
+#ifndef __NV04_SWTCL_H__
+#define __NV04_SWTCL_H__
+
+#include "mtypes.h"
+
+extern void nv04Fallback( GLcontext *ctx, GLuint bit, GLboolean mode );
+extern void nv04FinishPrimitive(struct nouveau_context *nmesa);
+extern void nv04TriInitFunctions(GLcontext *ctx);
+#define FALLBACK( nmesa, bit, mode ) nouveauFallback( nmesa->glCtx, bit, mode )
+
+#endif /* __NV04_SWTCL_H__ */
+
diff --git a/src/mesa/drivers/dri/nouveau/nv10_state.c b/src/mesa/drivers/dri/nouveau/nv10_state.c
new file mode 100644
index 0000000000..0e912e73ff
--- /dev/null
+++ b/src/mesa/drivers/dri/nouveau/nv10_state.c
@@ -0,0 +1,746 @@
+/**************************************************************************
+
+Copyright 2006 Nouveau
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+#include "nouveau_context.h"
+#include "nouveau_object.h"
+#include "nouveau_fifo.h"
+#include "nouveau_reg.h"
+
+#include "tnl/t_pipeline.h"
+
+#include "mtypes.h"
+#include "colormac.h"
+
+static void nv10AlphaFunc(GLcontext *ctx, GLenum func, GLfloat ref)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ GLubyte ubRef;
+ CLAMPED_FLOAT_TO_UBYTE(ubRef, ref);
+
+ BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_ALPHA_FUNC_FUNC, 2);
+ OUT_RING_CACHE(func);
+ OUT_RING_CACHE(ubRef);
+}
+
+static void nv10BlendColor(GLcontext *ctx, const GLfloat color[4])
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ GLubyte cf[4];
+
+ CLAMPED_FLOAT_TO_UBYTE(cf[0], color[0]);
+ CLAMPED_FLOAT_TO_UBYTE(cf[1], color[1]);
+ CLAMPED_FLOAT_TO_UBYTE(cf[2], color[2]);
+ CLAMPED_FLOAT_TO_UBYTE(cf[3], color[3]);
+
+ BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_BLEND_COLOR, 1);
+ OUT_RING_CACHE(PACK_COLOR_8888(cf[3], cf[1], cf[2], cf[0]));
+}
+
+static void nv10BlendEquationSeparate(GLcontext *ctx, GLenum modeRGB, GLenum modeA)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+
+ assert( modeRGB == modeA );
+
+ BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_BLEND_EQUATION, 1);
+ OUT_RING_CACHE(modeRGB);
+}
+
+
+static void nv10BlendFuncSeparate(GLcontext *ctx, GLenum sfactorRGB, GLenum dfactorRGB,
+ GLenum sfactorA, GLenum dfactorA)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+
+ assert( sfactorRGB == sfactorA );
+ assert( dfactorRGB == dfactorA );
+
+ BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_BLEND_FUNC_SRC, 2);
+ OUT_RING_CACHE(sfactorRGB);
+ OUT_RING_CACHE(dfactorRGB);
+}
+
+static void nv10Clear(GLcontext *ctx, GLbitfield mask)
+{
+ /* TODO */
+}
+
+static void nv10ClearColor(GLcontext *ctx, const GLfloat color[4])
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ GLubyte c[4];
+ UNCLAMPED_FLOAT_TO_RGBA_CHAN(c,color);
+ nmesa->clear_color_value = PACK_COLOR_8888(c[3],c[0],c[1],c[2]);
+}
+
+static void nv10ClearDepth(GLcontext *ctx, GLclampd d)
+{
+ /* FIXME: check if 16 or 24/32 bits depth buffer */
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ nmesa->clear_value=((nmesa->clear_value&0x000000FF)|(((uint32_t)(d*0xFFFFFF))<<8));
+}
+
+static void nv10ClearStencil(GLcontext *ctx, GLint s)
+{
+ /* FIXME: not valid for 16 bits depth buffer (0 stencil bits) */
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ nmesa->clear_value=((nmesa->clear_value&0xFFFFFF00)|(s&0x000000FF));
+}
+
+static void nv10ClipPlane(GLcontext *ctx, GLenum plane, const GLfloat *equation)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_CLIP_PLANE_A(plane), 4);
+ OUT_RING_CACHEf(equation[0]);
+ OUT_RING_CACHEf(equation[1]);
+ OUT_RING_CACHEf(equation[2]);
+ OUT_RING_CACHEf(equation[3]);
+}
+
+static void nv10ColorMask(GLcontext *ctx, GLboolean rmask, GLboolean gmask,
+ GLboolean bmask, GLboolean amask )
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_COLOR_MASK, 1);
+ OUT_RING_CACHE(((amask && 0x01) << 24) | ((rmask && 0x01) << 16) | ((gmask && 0x01)<< 8) | ((bmask && 0x01) << 0));
+}
+
+static void nv10ColorMaterial(GLcontext *ctx, GLenum face, GLenum mode)
+{
+ /* TODO I need love */
+}
+
+static void nv10CullFace(GLcontext *ctx, GLenum mode)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_CULL_FACE, 1);
+ OUT_RING_CACHE(mode);
+}
+
+static void nv10FrontFace(GLcontext *ctx, GLenum mode)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_FRONT_FACE, 1);
+ OUT_RING_CACHE(mode);
+}
+
+static void nv10DepthFunc(GLcontext *ctx, GLenum func)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_DEPTH_FUNC, 1);
+ OUT_RING_CACHE(func);
+}
+
+static void nv10DepthMask(GLcontext *ctx, GLboolean flag)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_DEPTH_WRITE_ENABLE, 1);
+ OUT_RING_CACHE(flag);
+}
+
+static void nv10DepthRange(GLcontext *ctx, GLclampd nearval, GLclampd farval)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_DEPTH_RANGE_NEAR, 2);
+ OUT_RING_CACHEf(nearval);
+ OUT_RING_CACHEf(farval);
+}
+
+/** Specify the current buffer for writing */
+//void (*DrawBuffer)( GLcontext *ctx, GLenum buffer );
+/** Specify the buffers for writing for fragment programs*/
+//void (*DrawBuffers)( GLcontext *ctx, GLsizei n, const GLenum *buffers );
+
+static void nv10Enable(GLcontext *ctx, GLenum cap, GLboolean state)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ switch(cap)
+ {
+ case GL_ALPHA_TEST:
+ BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_ALPHA_FUNC_ENABLE, 1);
+ OUT_RING_CACHE(state);
+ break;
+// case GL_AUTO_NORMAL:
+ case GL_BLEND:
+ BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_BLEND_FUNC_ENABLE, 1);
+ OUT_RING_CACHE(state);
+ break;
+ case GL_CLIP_PLANE0:
+ case GL_CLIP_PLANE1:
+ case GL_CLIP_PLANE2:
+ case GL_CLIP_PLANE3:
+ case GL_CLIP_PLANE4:
+ case GL_CLIP_PLANE5:
+ BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_CLIP_PLANE_ENABLE(cap-GL_CLIP_PLANE0), 1);
+ OUT_RING_CACHE(state);
+ break;
+ case GL_COLOR_LOGIC_OP:
+ BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_COLOR_LOGIC_OP_ENABLE, 1);
+ OUT_RING_CACHE(state);
+ break;
+// case GL_COLOR_MATERIAL:
+// case GL_COLOR_SUM_EXT:
+// case GL_COLOR_TABLE:
+// case GL_CONVOLUTION_1D:
+// case GL_CONVOLUTION_2D:
+ case GL_CULL_FACE:
+ BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_CULL_FACE_ENABLE, 1);
+ OUT_RING_CACHE(state);
+ break;
+ case GL_DEPTH_TEST:
+ BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_DEPTH_TEST_ENABLE, 1);
+ OUT_RING_CACHE(state);
+ break;
+ case GL_DITHER:
+ BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_DITHER_ENABLE, 1);
+ OUT_RING_CACHE(state);
+ break;
+ case GL_FOG:
+ BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_FOG_ENABLE, 1);
+ OUT_RING_CACHE(state);
+ break;
+// case GL_HISTOGRAM:
+// case GL_INDEX_LOGIC_OP:
+ case GL_LIGHT0:
+ case GL_LIGHT1:
+ case GL_LIGHT2:
+ case GL_LIGHT3:
+ case GL_LIGHT4:
+ case GL_LIGHT5:
+ case GL_LIGHT6:
+ case GL_LIGHT7:
+ {
+ uint32_t mask=1<<(2*(cap-GL_LIGHT0));
+ nmesa->enabled_lights=((nmesa->enabled_lights&mask)|(mask*state));
+ if (nmesa->lighting_enabled)
+ {
+ BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_ENABLED_LIGHTS, 1);
+ OUT_RING_CACHE(nmesa->enabled_lights);
+ }
+ break;
+ }
+ case GL_LIGHTING:
+ nmesa->lighting_enabled=state;
+ BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_ENABLED_LIGHTS, 1);
+ if (nmesa->lighting_enabled)
+ OUT_RING_CACHE(nmesa->enabled_lights);
+ else
+ OUT_RING_CACHE(0x0);
+ break;
+ case GL_LINE_SMOOTH:
+ BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_LINE_SMOOTH_ENABLE, 1);
+ OUT_RING_CACHE(state);
+ break;
+// case GL_LINE_STIPPLE:
+// case GL_MAP1_COLOR_4:
+// case GL_MAP1_INDEX:
+// case GL_MAP1_NORMAL:
+// case GL_MAP1_TEXTURE_COORD_1:
+// case GL_MAP1_TEXTURE_COORD_2:
+// case GL_MAP1_TEXTURE_COORD_3:
+// case GL_MAP1_TEXTURE_COORD_4:
+// case GL_MAP1_VERTEX_3:
+// case GL_MAP1_VERTEX_4:
+// case GL_MAP2_COLOR_4:
+// case GL_MAP2_INDEX:
+// case GL_MAP2_NORMAL:
+// case GL_MAP2_TEXTURE_COORD_1:
+// case GL_MAP2_TEXTURE_COORD_2:
+// case GL_MAP2_TEXTURE_COORD_3:
+// case GL_MAP2_TEXTURE_COORD_4:
+// case GL_MAP2_VERTEX_3:
+// case GL_MAP2_VERTEX_4:
+// case GL_MINMAX:
+ case GL_NORMALIZE:
+ BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_NORMALIZE_ENABLE, 1);
+ OUT_RING_CACHE(state);
+ break;
+// case GL_POINT_SMOOTH:
+ case GL_POLYGON_OFFSET_POINT:
+ BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_POLYGON_OFFSET_POINT_ENABLE, 1);
+ OUT_RING_CACHE(state);
+ break;
+ case GL_POLYGON_OFFSET_LINE:
+ BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_POLYGON_OFFSET_LINE_ENABLE, 1);
+ OUT_RING_CACHE(state);
+ break;
+ case GL_POLYGON_OFFSET_FILL:
+ BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_POLYGON_OFFSET_FILL_ENABLE, 1);
+ OUT_RING_CACHE(state);
+ break;
+ case GL_POLYGON_SMOOTH:
+ BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_POLYGON_SMOOTH_ENABLE, 1);
+ OUT_RING_CACHE(state);
+ break;
+// case GL_POLYGON_STIPPLE:
+// case GL_POST_COLOR_MATRIX_COLOR_TABLE:
+// case GL_POST_CONVOLUTION_COLOR_TABLE:
+// case GL_RESCALE_NORMAL:
+// case GL_SCISSOR_TEST:
+// case GL_SEPARABLE_2D:
+ case GL_STENCIL_TEST:
+ // TODO BACK and FRONT ?
+ BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_STENCIL_ENABLE, 1);
+ OUT_RING_CACHE(state);
+ break;
+// case GL_TEXTURE_GEN_Q:
+// case GL_TEXTURE_GEN_R:
+// case GL_TEXTURE_GEN_S:
+// case GL_TEXTURE_GEN_T:
+// case GL_TEXTURE_1D:
+// case GL_TEXTURE_2D:
+// case GL_TEXTURE_3D:
+ }
+}
+
+static void nv10Fogfv(GLcontext *ctx, GLenum pname, const GLfloat *params)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ switch(pname)
+ {
+ case GL_FOG_MODE:
+ BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_FOG_MODE, 1);
+ //OUT_RING_CACHE (params);
+ break;
+ /* TODO: unsure about the rest.*/
+ default:
+ break;
+ }
+
+}
+
+static void nv10Hint(GLcontext *ctx, GLenum target, GLenum mode)
+{
+ /* TODO I need love (fog and line_smooth hints) */
+}
+
+// void (*IndexMask)(GLcontext *ctx, GLuint mask);
+
+enum {
+ SPOTLIGHT_NO_UPDATE,
+ SPOTLIGHT_UPDATE_EXPONENT,
+ SPOTLIGHT_UPDATE_DIRECTION,
+ SPOTLIGHT_UPDATE_ALL
+};
+
+static void nv10Lightfv(GLcontext *ctx, GLenum light, GLenum pname, const GLfloat *params )
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ GLint p = light - GL_LIGHT0;
+ struct gl_light *l = &ctx->Light.Light[p];
+ int spotlight_update = SPOTLIGHT_NO_UPDATE;
+
+ switch(pname)
+ {
+ case GL_AMBIENT:
+ BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_AMBIENT_R(p), 3);
+ OUT_RING_CACHEf(params[0]);
+ OUT_RING_CACHEf(params[1]);
+ OUT_RING_CACHEf(params[2]);
+ break;
+ case GL_DIFFUSE:
+ BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_DIFFUSE_R(p), 3);
+ OUT_RING_CACHEf(params[0]);
+ OUT_RING_CACHEf(params[1]);
+ OUT_RING_CACHEf(params[2]);
+ break;
+ case GL_SPECULAR:
+ BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_SPECULAR_R(p), 3);
+ OUT_RING_CACHEf(params[0]);
+ OUT_RING_CACHEf(params[1]);
+ OUT_RING_CACHEf(params[2]);
+ break;
+ case GL_POSITION:
+ BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_LIGHT_POSITION_X(p), 3);
+ OUT_RING_CACHEf(params[0]);
+ OUT_RING_CACHEf(params[1]);
+ OUT_RING_CACHEf(params[2]);
+ break;
+ case GL_SPOT_DIRECTION:
+ spotlight_update = SPOTLIGHT_UPDATE_DIRECTION;
+ break;
+ case GL_SPOT_EXPONENT:
+ spotlight_update = SPOTLIGHT_UPDATE_EXPONENT;
+ break;
+ case GL_SPOT_CUTOFF:
+ spotlight_update = SPOTLIGHT_UPDATE_ALL;
+ break;
+ case GL_CONSTANT_ATTENUATION:
+ BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_LIGHT_CONSTANT_ATTENUATION(p), 1);
+ OUT_RING_CACHEf(*params);
+ break;
+ case GL_LINEAR_ATTENUATION:
+ BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_LIGHT_LINEAR_ATTENUATION(p), 1);
+ OUT_RING_CACHEf(*params);
+ break;
+ case GL_QUADRATIC_ATTENUATION:
+ BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_LIGHT_QUADRATIC_ATTENUATION(p), 1);
+ OUT_RING_CACHEf(*params);
+ break;
+ default:
+ break;
+ }
+
+ switch(spotlight_update) {
+ case SPOTLIGHT_UPDATE_DIRECTION:
+ {
+ GLfloat x,y,z;
+ GLfloat spot_light_coef_a = 1.0 / (l->_CosCutoff - 1.0);
+ x = spot_light_coef_a * l->_NormDirection[0];
+ y = spot_light_coef_a * l->_NormDirection[1];
+ z = spot_light_coef_a * l->_NormDirection[2];
+ BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_LIGHT_SPOT_DIR_X(p), 3);
+ OUT_RING_CACHEf(x);
+ OUT_RING_CACHEf(y);
+ OUT_RING_CACHEf(z);
+ }
+ break;
+ case SPOTLIGHT_UPDATE_EXPONENT:
+ {
+ GLfloat cc,lc,qc;
+ cc = 1.0; /* FIXME: These need to be correctly computed */
+ lc = 0.0;
+ qc = 2.0;
+ BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_LIGHT_SPOT_CUTOFF_A(p), 3);
+ OUT_RING_CACHEf(cc);
+ OUT_RING_CACHEf(lc);
+ OUT_RING_CACHEf(qc);
+ }
+ break;
+ case SPOTLIGHT_UPDATE_ALL:
+ {
+ GLfloat cc,lc,qc, x,y,z, c;
+ GLfloat spot_light_coef_a = 1.0 / (l->_CosCutoff - 1.0);
+ cc = 1.0; /* FIXME: These need to be correctly computed */
+ lc = 0.0;
+ qc = 2.0;
+ x = spot_light_coef_a * l->_NormDirection[0];
+ y = spot_light_coef_a * l->_NormDirection[1];
+ z = spot_light_coef_a * l->_NormDirection[2];
+ c = spot_light_coef_a + 1.0;
+ BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_LIGHT_SPOT_CUTOFF_A(p), 7);
+ OUT_RING_CACHEf(cc);
+ OUT_RING_CACHEf(lc);
+ OUT_RING_CACHEf(qc);
+ OUT_RING_CACHEf(x);
+ OUT_RING_CACHEf(y);
+ OUT_RING_CACHEf(z);
+ OUT_RING_CACHEf(c);
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+/** Set the lighting model parameters */
+static void (*LightModelfv)(GLcontext *ctx, GLenum pname, const GLfloat *params);
+
+
+static void nv10LineStipple(GLcontext *ctx, GLint factor, GLushort pattern )
+{
+ /* Not for NV10 */
+}
+
+static void nv10LineWidth(GLcontext *ctx, GLfloat width)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_LINE_WIDTH, 1);
+ OUT_RING_CACHE(((int) (width * 8.0)) & -4);
+}
+
+static void nv10LogicOpcode(GLcontext *ctx, GLenum opcode)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_COLOR_LOGIC_OP_OP, 1);
+ OUT_RING_CACHE(opcode);
+}
+
+static void nv10PointParameterfv(GLcontext *ctx, GLenum pname, const GLfloat *params)
+{
+ /*TODO: not sure what goes here. */
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+
+}
+
+static void nv10PointSize(GLcontext *ctx, GLfloat size)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_POINT_SIZE, 1);
+ OUT_RING_CACHE(((int) (size * 8.0)) & -4);
+}
+
+static void nv10PolygonMode(GLcontext *ctx, GLenum face, GLenum mode)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+
+ if (face == GL_FRONT || face == GL_FRONT_AND_BACK) {
+ BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_POLYGON_MODE_FRONT, 1);
+ OUT_RING_CACHE(mode);
+ }
+ if (face == GL_BACK || face == GL_FRONT_AND_BACK) {
+ BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_POLYGON_MODE_BACK, 1);
+ OUT_RING_CACHE(mode);
+ }
+}
+
+/** Set the scale and units used to calculate depth values */
+static void nv10PolygonOffset(GLcontext *ctx, GLfloat factor, GLfloat units)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_POLYGON_OFFSET_FACTOR, 2);
+ OUT_RING_CACHEf(factor);
+ OUT_RING_CACHEf(units);
+}
+
+/** Set the polygon stippling pattern */
+static void nv10PolygonStipple(GLcontext *ctx, const GLubyte *mask )
+{
+ /* Not for NV10 */
+}
+
+/* Specifies the current buffer for reading */
+void (*ReadBuffer)( GLcontext *ctx, GLenum buffer );
+/** Set rasterization mode */
+void (*RenderMode)(GLcontext *ctx, GLenum mode );
+
+/** Define the scissor box */
+static void nv10Scissor(GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h)
+{
+}
+
+/** Select flat or smooth shading */
+static void nv10ShadeModel(GLcontext *ctx, GLenum mode)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+
+ BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_SHADE_MODEL, 1);
+ OUT_RING_CACHE(mode);
+}
+
+/** OpenGL 2.0 two-sided StencilFunc */
+static void nv10StencilFuncSeparate(GLcontext *ctx, GLenum face, GLenum func,
+ GLint ref, GLuint mask)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+
+ /* NV10 do not have separate FRONT and BACK stencils */
+ BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_STENCIL_FUNC_FUNC, 3);
+ OUT_RING_CACHE(func);
+ OUT_RING_CACHE(ref);
+ OUT_RING_CACHE(mask);
+}
+
+/** OpenGL 2.0 two-sided StencilMask */
+static void nv10StencilMaskSeparate(GLcontext *ctx, GLenum face, GLuint mask)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+
+ /* NV10 do not have separate FRONT and BACK stencils */
+ BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_STENCIL_MASK, 1);
+ OUT_RING_CACHE(mask);
+}
+
+/** OpenGL 2.0 two-sided StencilOp */
+static void nv10StencilOpSeparate(GLcontext *ctx, GLenum face, GLenum fail,
+ GLenum zfail, GLenum zpass)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+
+ /* NV10 do not have separate FRONT and BACK stencils */
+ BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_STENCIL_OP_FAIL, 3);
+ OUT_RING_CACHE(fail);
+ OUT_RING_CACHE(zfail);
+ OUT_RING_CACHE(zpass);
+}
+
+/** Control the generation of texture coordinates */
+void (*TexGen)(GLcontext *ctx, GLenum coord, GLenum pname,
+ const GLfloat *params);
+/** Set texture environment parameters */
+void (*TexEnv)(GLcontext *ctx, GLenum target, GLenum pname,
+ const GLfloat *param);
+/** Set texture parameters */
+void (*TexParameter)(GLcontext *ctx, GLenum target,
+ struct gl_texture_object *texObj,
+ GLenum pname, const GLfloat *params);
+
+static void nv10TextureMatrix(GLcontext *ctx, GLuint unit, const GLmatrix *mat)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_TX_MATRIX(unit, 0), 16);
+ /*XXX: This SHOULD work.*/
+ OUT_RING_CACHEp(mat->m, 16);
+}
+
+/* Update anything that depends on the window position/size */
+static void nv10WindowMoved(nouveauContextPtr nmesa)
+{
+ GLcontext *ctx = nmesa->glCtx;
+ GLfloat *v = nmesa->viewport.m;
+ GLuint w = ctx->Viewport.Width;
+ GLuint h = ctx->Viewport.Height;
+ GLuint x = ctx->Viewport.X + nmesa->drawX;
+ GLuint y = ctx->Viewport.Y + nmesa->drawY;
+ int i;
+
+ BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_VIEWPORT_HORIZ, 2);
+ OUT_RING_CACHE((w << 16) | x);
+ OUT_RING_CACHE((h << 16) | y);
+
+ /* something to do with clears, possibly doesn't belong here */
+ BEGIN_RING_CACHE(NvSub3D,
+ NV10_TCL_PRIMITIVE_3D_VIEWPORT_CLIP_HORIZ(0), 2);
+ OUT_RING_CACHE(((w+x) << 16) | x | 0x800);
+ OUT_RING_CACHE(((h+y) << 16) | y | 0x800);
+ for (i=1; i<7; i++) {
+ BEGIN_RING_CACHE(NvSub3D,
+ NV10_TCL_PRIMITIVE_3D_VIEWPORT_CLIP_HORIZ(i), 1);
+ OUT_RING_CACHE(0);
+ BEGIN_RING_CACHE(NvSub3D,
+ NV10_TCL_PRIMITIVE_3D_VIEWPORT_CLIP_VERT(i), 1);
+ OUT_RING_CACHE(0);
+ }
+
+ /* viewport transform */
+ BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_VIEWPORT_ORIGIN_X, 4);
+ OUT_RING_CACHEf ((GLfloat) x);
+ OUT_RING_CACHEf ((GLfloat) (y+h));
+ OUT_RING_CACHEf (0.0);
+ OUT_RING_CACHEf (0.0);
+
+ BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_VIEWPORT_SCALE_X, 4);
+ OUT_RING_CACHEf ((((GLfloat) w) * 0.5) - 2048.0);
+ OUT_RING_CACHEf ((((GLfloat) h) * 0.5) - 2048.0);
+ OUT_RING_CACHEf (16777215.0 * 0.5);
+ OUT_RING_CACHEf (0.0);
+}
+
+/* Initialise any card-specific non-GL related state */
+static GLboolean nv10InitCard(nouveauContextPtr nmesa)
+{
+ nouveauObjectOnSubchannel(nmesa, NvSub3D, Nv3D);
+
+ BEGIN_RING_SIZE(NvSub3D, NV10_TCL_PRIMITIVE_3D_SET_DMA_IN_MEMORY0, 2);
+ OUT_RING(NvDmaFB); /* 184 dma_in_memory0 */
+ OUT_RING(NvDmaFB); /* 188 dma_in_memory1 */
+ BEGIN_RING_SIZE(NvSub3D, NV10_TCL_PRIMITIVE_3D_SET_DMA_IN_MEMORY2, 2);
+ OUT_RING(NvDmaFB); /* 194 dma_in_memory2 */
+ OUT_RING(NvDmaFB); /* 198 dma_in_memory3 */
+
+ BEGIN_RING_SIZE(NvSub3D, 0x02b4, 1);
+ OUT_RING(0);
+ BEGIN_RING_SIZE(NvSub3D, 0x0290, 1);
+ OUT_RING(0x00100001);
+ BEGIN_RING_SIZE(NvSub3D, 0x03f4, 1);
+ OUT_RING(0);
+
+ return GL_FALSE;
+}
+
+/* Update buffer offset/pitch/format */
+static GLboolean nv10BindBuffers(nouveauContextPtr nmesa, int num_color,
+ nouveau_renderbuffer **color,
+ nouveau_renderbuffer *depth)
+{
+ GLuint x, y, w, h;
+ GLuint pitch, format;
+
+ w = color[0]->mesa.Width;
+ h = color[0]->mesa.Height;
+ x = nmesa->drawX;
+ y = nmesa->drawY;
+
+ if (num_color != 1)
+ return GL_FALSE;
+
+ BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_VIEWPORT_HORIZ, 6);
+ OUT_RING_CACHE((w << 16) | x);
+ OUT_RING_CACHE((h << 16) | y);
+ pitch = color[0]->pitch;
+ if (depth) {
+ pitch |= (depth->pitch << 16);
+ }
+ format = 0x108;
+ if (color[0]->mesa._ActualFormat != GL_RGBA8) {
+ format = 0x103; /* R5G6B5 color buffer */
+ }
+ OUT_RING(format);
+ OUT_RING(pitch);
+ OUT_RING(color[0]->offset);
+ OUT_RING(depth ? depth->offset : color[0]->offset);
+
+ return GL_TRUE;
+}
+
+void nv10InitStateFuncs(GLcontext *ctx, struct dd_function_table *func)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+
+ func->AlphaFunc = nv10AlphaFunc;
+ func->BlendColor = nv10BlendColor;
+ func->BlendEquationSeparate = nv10BlendEquationSeparate;
+ func->BlendFuncSeparate = nv10BlendFuncSeparate;
+ func->Clear = nv10Clear;
+ func->ClearColor = nv10ClearColor;
+ func->ClearDepth = nv10ClearDepth;
+ func->ClearStencil = nv10ClearStencil;
+ func->ClipPlane = nv10ClipPlane;
+ func->ColorMask = nv10ColorMask;
+ func->ColorMaterial = nv10ColorMaterial;
+ func->CullFace = nv10CullFace;
+ func->FrontFace = nv10FrontFace;
+ func->DepthFunc = nv10DepthFunc;
+ func->DepthMask = nv10DepthMask;
+ func->DepthRange = nv10DepthRange;
+ func->Enable = nv10Enable;
+ func->Fogfv = nv10Fogfv;
+ func->Hint = nv10Hint;
+ func->Lightfv = nv10Lightfv;
+/* func->LightModelfv = nv10LightModelfv; */
+ func->LineStipple = nv10LineStipple; /* Not for NV10 */
+ func->LineWidth = nv10LineWidth;
+ func->LogicOpcode = nv10LogicOpcode;
+ func->PointParameterfv = nv10PointParameterfv;
+ func->PointSize = nv10PointSize;
+ func->PolygonMode = nv10PolygonMode;
+ func->PolygonOffset = nv10PolygonOffset;
+ func->PolygonStipple = nv10PolygonStipple; /* Not for NV10 */
+/* func->ReadBuffer = nv10ReadBuffer;*/
+/* func->RenderMode = nv10RenderMode;*/
+ func->Scissor = nv10Scissor;
+ func->ShadeModel = nv10ShadeModel;
+ func->StencilFuncSeparate = nv10StencilFuncSeparate;
+ func->StencilMaskSeparate = nv10StencilMaskSeparate;
+ func->StencilOpSeparate = nv10StencilOpSeparate;
+/* func->TexGen = nv10TexGen;*/
+/* func->TexParameter = nv10TexParameter;*/
+ func->TextureMatrix = nv10TextureMatrix;
+
+ nmesa->hw_func.InitCard = nv10InitCard;
+ nmesa->hw_func.BindBuffers = nv10BindBuffers;
+ nmesa->hw_func.WindowMoved = nv10WindowMoved;
+}
diff --git a/src/mesa/drivers/dri/nouveau/nv10_swtcl.c b/src/mesa/drivers/dri/nouveau/nv10_swtcl.c
new file mode 100644
index 0000000000..12b277de45
--- /dev/null
+++ b/src/mesa/drivers/dri/nouveau/nv10_swtcl.c
@@ -0,0 +1,569 @@
+/*
+ * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
+ * Copyright 2006 Stephane Marchesin. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sub license,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/* Software TCL for NV10, NV20, NV30, NV40, G70 */
+
+#include <stdio.h>
+#include <math.h>
+
+#include "glheader.h"
+#include "context.h"
+#include "mtypes.h"
+#include "macros.h"
+#include "colormac.h"
+#include "enums.h"
+
+#include "swrast/swrast.h"
+#include "swrast_setup/swrast_setup.h"
+#include "tnl/t_context.h"
+#include "tnl/t_pipeline.h"
+
+#include "nouveau_swtcl.h"
+#include "nv10_swtcl.h"
+#include "nouveau_context.h"
+#include "nouveau_span.h"
+#include "nouveau_reg.h"
+#include "nouveau_tex.h"
+#include "nouveau_fifo.h"
+#include "nouveau_msg.h"
+#include "nouveau_object.h"
+
+static void nv10RasterPrimitive( GLcontext *ctx, GLenum rprim, GLuint hwprim );
+static void nv10RenderPrimitive( GLcontext *ctx, GLenum prim );
+static void nv10ResetLineStipple( GLcontext *ctx );
+
+
+
+static inline void nv10StartPrimitive(struct nouveau_context* nmesa,uint32_t primitive,uint32_t size)
+{
+ if (nmesa->screen->card->type==NV_10)
+ BEGIN_RING_SIZE(NvSub3D,NV10_TCL_PRIMITIVE_3D_BEGIN_END,1);
+ else if (nmesa->screen->card->type==NV_20)
+ BEGIN_RING_SIZE(NvSub3D,NV20_TCL_PRIMITIVE_3D_BEGIN_END,1);
+ else
+ BEGIN_RING_SIZE(NvSub3D,NV30_TCL_PRIMITIVE_3D_BEGIN_END,1);
+ OUT_RING(primitive);
+
+ if (nmesa->screen->card->type==NV_10)
+ BEGIN_RING_SIZE(NvSub3D,NV10_TCL_PRIMITIVE_3D_VERTEX_ARRAY_DATA|NONINC_METHOD,size);
+ else if (nmesa->screen->card->type==NV_20)
+ BEGIN_RING_SIZE(NvSub3D,NV20_TCL_PRIMITIVE_3D_VERTEX_DATA|NONINC_METHOD,size);
+ else
+ BEGIN_RING_SIZE(NvSub3D,NV30_TCL_PRIMITIVE_3D_VERTEX_DATA|NONINC_METHOD,size);
+}
+
+inline void nv10FinishPrimitive(struct nouveau_context *nmesa)
+{
+ if (nmesa->screen->card->type==NV_10)
+ BEGIN_RING_SIZE(NvSub3D,NV10_TCL_PRIMITIVE_3D_BEGIN_END,1);
+ else if (nmesa->screen->card->type==NV_20)
+ BEGIN_RING_SIZE(NvSub3D,NV20_TCL_PRIMITIVE_3D_BEGIN_END,1);
+ else
+ BEGIN_RING_SIZE(NvSub3D,NV30_TCL_PRIMITIVE_3D_BEGIN_END,1);
+ OUT_RING(0x0);
+ FIRE_RING();
+}
+
+
+static inline void nv10ExtendPrimitive(struct nouveau_context* nmesa, int size)
+{
+ /* make sure there's enough room. if not, wait */
+ if (RING_AVAILABLE()<size)
+ {
+ WAIT_RING(nmesa,size);
+ }
+}
+
+/**********************************************************************/
+/* Render unclipped begin/end objects */
+/**********************************************************************/
+
+static inline void nv10_render_generic_primitive_verts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags,GLuint prim)
+{
+ struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx);
+ GLubyte *vertptr = (GLubyte *)nmesa->verts;
+ GLuint vertsize = nmesa->vertex_size;
+ GLuint size_dword = vertsize*(count-start)/4;
+
+ nv10ExtendPrimitive(nmesa, size_dword);
+ nv10StartPrimitive(nmesa,prim+1,size_dword);
+ OUT_RINGp((nouveauVertex*)(vertptr+(start*vertsize)),size_dword);
+ nv10FinishPrimitive(nmesa);
+}
+
+static void nv10_render_points_verts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
+{
+ nv10_render_generic_primitive_verts(ctx,start,count,flags,GL_POINTS);
+}
+
+static void nv10_render_lines_verts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
+{
+ nv10_render_generic_primitive_verts(ctx,start,count,flags,GL_LINES);
+}
+
+static void nv10_render_line_strip_verts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
+{
+ nv10_render_generic_primitive_verts(ctx,start,count,flags,GL_LINE_STRIP);
+}
+
+static void nv10_render_line_loop_verts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
+{
+ nv10_render_generic_primitive_verts(ctx,start,count,flags,GL_LINE_LOOP);
+}
+
+static void nv10_render_triangles_verts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
+{
+ nv10_render_generic_primitive_verts(ctx,start,count,flags,GL_TRIANGLES);
+}
+
+static void nv10_render_tri_strip_verts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
+{
+ nv10_render_generic_primitive_verts(ctx,start,count,flags,GL_TRIANGLE_STRIP);
+}
+
+static void nv10_render_tri_fan_verts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
+{
+ nv10_render_generic_primitive_verts(ctx,start,count,flags,GL_TRIANGLE_FAN);
+}
+
+static void nv10_render_quads_verts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
+{
+ nv10_render_generic_primitive_verts(ctx,start,count,flags,GL_QUADS);
+}
+
+static void nv10_render_quad_strip_verts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
+{
+ nv10_render_generic_primitive_verts(ctx,start,count,flags,GL_QUAD_STRIP);
+}
+
+static void nv10_render_poly_verts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
+{
+ nv10_render_generic_primitive_verts(ctx,start,count,flags,GL_POLYGON);
+}
+
+static void nv10_render_noop_verts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
+{
+}
+
+static void (*nv10_render_tab_verts[GL_POLYGON+2])(GLcontext *,
+ GLuint,
+ GLuint,
+ GLuint) =
+{
+ nv10_render_points_verts,
+ nv10_render_lines_verts,
+ nv10_render_line_loop_verts,
+ nv10_render_line_strip_verts,
+ nv10_render_triangles_verts,
+ nv10_render_tri_strip_verts,
+ nv10_render_tri_fan_verts,
+ nv10_render_quads_verts,
+ nv10_render_quad_strip_verts,
+ nv10_render_poly_verts,
+ nv10_render_noop_verts,
+};
+
+
+static inline void nv10_render_generic_primitive_elts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags,GLuint prim)
+{
+ struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx);
+ GLubyte *vertptr = (GLubyte *)nmesa->verts;
+ GLuint vertsize = nmesa->vertex_size;
+ GLuint size_dword = vertsize*(count-start)/4;
+ const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts;
+ GLuint j;
+
+ nv10ExtendPrimitive(nmesa, size_dword);
+ nv10StartPrimitive(nmesa,prim+1,size_dword);
+ for (j=start; j<count; j++ ) {
+ OUT_RINGp((nouveauVertex*)(vertptr+(elt[j]*vertsize)),vertsize);
+ }
+ nv10FinishPrimitive(nmesa);
+}
+
+static void nv10_render_points_elts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
+{
+ nv10_render_generic_primitive_elts(ctx,start,count,flags,GL_POINTS);
+}
+
+static void nv10_render_lines_elts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
+{
+ nv10_render_generic_primitive_elts(ctx,start,count,flags,GL_LINES);
+}
+
+static void nv10_render_line_strip_elts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
+{
+ nv10_render_generic_primitive_elts(ctx,start,count,flags,GL_LINE_STRIP);
+}
+
+static void nv10_render_line_loop_elts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
+{
+ nv10_render_generic_primitive_elts(ctx,start,count,flags,GL_LINE_LOOP);
+}
+
+static void nv10_render_triangles_elts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
+{
+ nv10_render_generic_primitive_elts(ctx,start,count,flags,GL_TRIANGLES);
+}
+
+static void nv10_render_tri_strip_elts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
+{
+ nv10_render_generic_primitive_elts(ctx,start,count,flags,GL_TRIANGLE_STRIP);
+}
+
+static void nv10_render_tri_fan_elts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
+{
+ nv10_render_generic_primitive_elts(ctx,start,count,flags,GL_TRIANGLE_FAN);
+}
+
+static void nv10_render_quads_elts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
+{
+ nv10_render_generic_primitive_elts(ctx,start,count,flags,GL_QUADS);
+}
+
+static void nv10_render_quad_strip_elts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
+{
+ nv10_render_generic_primitive_elts(ctx,start,count,flags,GL_QUAD_STRIP);
+}
+
+static void nv10_render_poly_elts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
+{
+ nv10_render_generic_primitive_elts(ctx,start,count,flags,GL_POLYGON);
+}
+
+static void nv10_render_noop_elts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags)
+{
+}
+
+static void (*nv10_render_tab_elts[GL_POLYGON+2])(GLcontext *,
+ GLuint,
+ GLuint,
+ GLuint) =
+{
+ nv10_render_points_elts,
+ nv10_render_lines_elts,
+ nv10_render_line_loop_elts,
+ nv10_render_line_strip_elts,
+ nv10_render_triangles_elts,
+ nv10_render_tri_strip_elts,
+ nv10_render_tri_fan_elts,
+ nv10_render_quads_elts,
+ nv10_render_quad_strip_elts,
+ nv10_render_poly_elts,
+ nv10_render_noop_elts,
+};
+
+
+/**********************************************************************/
+/* Choose render functions */
+/**********************************************************************/
+
+
+#define EMIT_ATTR( ATTR, STYLE ) \
+do { \
+ nmesa->vertex_attrs[nmesa->vertex_attr_count].attrib = (ATTR); \
+ nmesa->vertex_attrs[nmesa->vertex_attr_count].format = (STYLE); \
+ nmesa->vertex_attr_count++; \
+} while (0)
+
+
+static void nv10ChooseRenderState(GLcontext *ctx)
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx);
+
+ tnl->Driver.Render.PrimTabVerts = nv10_render_tab_verts;
+ tnl->Driver.Render.PrimTabElts = nv10_render_tab_elts;
+ tnl->Driver.Render.ClippedLine = NULL;
+ tnl->Driver.Render.ClippedPolygon = NULL;
+}
+
+
+
+static inline void nv10OutputVertexFormat(struct nouveau_context* nmesa)
+{
+ GLcontext* ctx=nmesa->glCtx;
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ DECLARE_RENDERINPUTS(index);
+ struct vertex_buffer *VB = &tnl->vb;
+ int attr_size[16];
+ int default_attr_size[8]={3,3,3,4,3,1,4,4};
+ int i;
+ int slots=0;
+ int total_size=0;
+ /* t_vertex_generic dereferences a NULL pointer if we
+ * pass NULL as the vp transform...
+ */
+ const GLfloat ident_vp[16] = {
+ 1.0, 0.0, 0.0, 0.0,
+ 0.0, 1.0, 0.0, 0.0,
+ 0.0, 0.0, 1.0, 0.0,
+ 0.0, 0.0, 0.0, 1.0
+ };
+
+ RENDERINPUTS_COPY(index, nmesa->render_inputs_bitset);
+
+ /*
+ * Determine attribute sizes
+ */
+ for(i=0;i<8;i++)
+ {
+ if (RENDERINPUTS_TEST(index, i))
+ attr_size[i]=default_attr_size[i];
+ else
+ attr_size[i]=0;
+ }
+ for(i=8;i<16;i++)
+ {
+ if (RENDERINPUTS_TEST(index, i))
+ attr_size[i]=VB->TexCoordPtr[i-8]->size;
+ else
+ attr_size[i]=0;
+ }
+
+ /*
+ * Tell t_vertex about the vertex format
+ */
+ for(i=0;i<16;i++)
+ {
+ if (RENDERINPUTS_TEST(index, i))
+ {
+ slots=i+1;
+ if (i==_TNL_ATTRIB_POS)
+ {
+ /* special-case POS */
+ EMIT_ATTR(_TNL_ATTRIB_POS,EMIT_3F_VIEWPORT);
+ }
+ else
+ {
+ switch(attr_size[i])
+ {
+ case 1:
+ EMIT_ATTR(i,EMIT_1F);
+ break;
+ case 2:
+ EMIT_ATTR(i,EMIT_2F);
+ break;
+ case 3:
+ EMIT_ATTR(i,EMIT_3F);
+ break;
+ case 4:
+ EMIT_ATTR(i,EMIT_4F);
+ break;
+ }
+ }
+ if (i==_TNL_ATTRIB_COLOR0)
+ nmesa->color_offset=total_size;
+ if (i==_TNL_ATTRIB_COLOR1)
+ nmesa->specular_offset=total_size;
+ total_size+=attr_size[i];
+ }
+ }
+
+ nmesa->vertex_size=_tnl_install_attrs( ctx,
+ nmesa->vertex_attrs,
+ nmesa->vertex_attr_count,
+ ident_vp, 0 );
+ assert(nmesa->vertex_size==total_size*4);
+
+ /*
+ * Tell the hardware about the vertex format
+ */
+ if (nmesa->screen->card->type==NV_10) {
+ int size;
+
+#define NV_VERTEX_ATTRIBUTE_TYPE_FLOAT 2
+
+#define NV10_SET_VERTEX_ATTRIB(i,j) \
+ do { \
+ size = attr_size[j] << 4; \
+ size |= (attr_size[j]*4) << 8; \
+ size |= NV_VERTEX_ATTRIBUTE_TYPE_FLOAT; \
+ BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_VERTEX_ATTR(i),1); \
+ OUT_RING_CACHE(size); \
+ } while (0)
+
+ NV10_SET_VERTEX_ATTRIB(0, _TNL_ATTRIB_POS);
+ NV10_SET_VERTEX_ATTRIB(1, _TNL_ATTRIB_COLOR0);
+ NV10_SET_VERTEX_ATTRIB(2, _TNL_ATTRIB_COLOR1);
+ NV10_SET_VERTEX_ATTRIB(3, _TNL_ATTRIB_TEX0);
+ NV10_SET_VERTEX_ATTRIB(4, _TNL_ATTRIB_TEX1);
+ NV10_SET_VERTEX_ATTRIB(5, _TNL_ATTRIB_NORMAL);
+ NV10_SET_VERTEX_ATTRIB(6, _TNL_ATTRIB_WEIGHT);
+ NV10_SET_VERTEX_ATTRIB(7, _TNL_ATTRIB_FOG);
+
+ BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_VERTEX_ARRAY_VALIDATE,1);
+ OUT_RING_CACHE(0);
+ } else if (nmesa->screen->card->type==NV_20) {
+ for(i=0;i<16;i++)
+ {
+ int size=attr_size[i];
+ BEGIN_RING_CACHE(NvSub3D,NV20_TCL_PRIMITIVE_3D_VERTEX_ATTR(i),1);
+ OUT_RING_CACHE(NV_VERTEX_ATTRIBUTE_TYPE_FLOAT|(size*0x10));
+ }
+ } else {
+ BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_DO_VERTICES, 1);
+ OUT_RING(0);
+ BEGIN_RING_CACHE(NvSub3D,NV30_TCL_PRIMITIVE_3D_VERTEX_ATTR0_POS,slots);
+ for(i=0;i<slots;i++)
+ {
+ int size=attr_size[i];
+ OUT_RING_CACHE(NV_VERTEX_ATTRIBUTE_TYPE_FLOAT|(size*0x10));
+ }
+ // FIXME this is probably not needed
+ BEGIN_RING_SIZE(NvSub3D,NV30_TCL_PRIMITIVE_3D_VERTEX_UNK_0,1);
+ OUT_RING(0);
+ BEGIN_RING_SIZE(NvSub3D,NV30_TCL_PRIMITIVE_3D_VERTEX_UNK_0,1);
+ OUT_RING(0);
+ BEGIN_RING_SIZE(NvSub3D,NV30_TCL_PRIMITIVE_3D_VERTEX_UNK_0,1);
+ OUT_RING(0);
+ }
+}
+
+
+static void nv10ChooseVertexState( GLcontext *ctx )
+{
+ struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx);
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ DECLARE_RENDERINPUTS(index);
+
+ RENDERINPUTS_COPY(index, tnl->render_inputs_bitset);
+ if (!RENDERINPUTS_EQUAL(index, nmesa->render_inputs_bitset))
+ {
+ RENDERINPUTS_COPY(nmesa->render_inputs_bitset, index);
+ nv10OutputVertexFormat(nmesa);
+ }
+
+ if (nmesa->screen->card->type >= NV_40) {
+ /* Ensure passthrough shader is being used, and mvp matrix
+ * is up to date
+ */
+ nvsUpdateShader(ctx, nmesa->passthrough_vp);
+ BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_VP_IN_REG, 2);
+ OUT_RING_CACHE (0xff09); /*IN : POS, COL, TC0-7 */
+ OUT_RING_CACHE (0x3fc001); /*OUT: COL, TC0-7, POS implied */
+
+ /* Update texenv shader / user fragprog */
+ nvsUpdateShader(ctx, (nouveauShader*)ctx->FragmentProgram._Current);
+ }
+}
+
+
+/**********************************************************************/
+/* High level hooks for t_vb_render.c */
+/**********************************************************************/
+
+
+static void nv10RenderStart(GLcontext *ctx)
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx);
+
+ if (nmesa->new_state) {
+ nmesa->new_render_state |= nmesa->new_state;
+ }
+
+ if (nmesa->new_render_state) {
+ nv10ChooseVertexState(ctx);
+ nv10ChooseRenderState(ctx);
+ nmesa->new_render_state = 0;
+ }
+}
+
+static void nv10RenderFinish(GLcontext *ctx)
+{
+}
+
+
+/* System to flush dma and emit state changes based on the rasterized
+ * primitive.
+ */
+void nv10RasterPrimitive(GLcontext *ctx,
+ GLenum glprim,
+ GLuint hwprim)
+{
+ struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx);
+
+ assert (!nmesa->new_state);
+
+ if (hwprim != nmesa->current_primitive)
+ {
+ nmesa->current_primitive=hwprim;
+
+ }
+}
+
+static const GLuint hw_prim[GL_POLYGON+1] = {
+ GL_POINTS+1,
+ GL_LINES+1,
+ GL_LINE_STRIP+1,
+ GL_LINE_LOOP+1,
+ GL_TRIANGLES+1,
+ GL_TRIANGLE_STRIP+1,
+ GL_TRIANGLE_FAN+1,
+ GL_QUADS+1,
+ GL_QUAD_STRIP+1,
+ GL_POLYGON+1
+};
+
+/* Callback for mesa:
+ */
+static void nv10RenderPrimitive( GLcontext *ctx, GLuint prim )
+{
+ nv10RasterPrimitive( ctx, prim, hw_prim[prim] );
+}
+
+static void nv10ResetLineStipple( GLcontext *ctx )
+{
+ /* FIXME do something here */
+ WARN_ONCE("Unimplemented nv10ResetLineStipple\n");
+}
+
+
+/**********************************************************************/
+/* Initialization. */
+/**********************************************************************/
+
+void nv10TriInitFunctions(GLcontext *ctx)
+{
+ struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx);
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+
+ tnl->Driver.RunPipeline = nouveauRunPipeline;
+ tnl->Driver.Render.Start = nv10RenderStart;
+ tnl->Driver.Render.Finish = nv10RenderFinish;
+ tnl->Driver.Render.PrimitiveNotify = nv10RenderPrimitive;
+ tnl->Driver.Render.ResetLineStipple = nv10ResetLineStipple;
+ tnl->Driver.Render.BuildVertices = _tnl_build_vertices;
+ tnl->Driver.Render.CopyPV = _tnl_copy_pv;
+ tnl->Driver.Render.Interp = _tnl_interp;
+
+ _tnl_init_vertices( ctx, ctx->Const.MaxArrayLockSize + 12,
+ 64 * sizeof(GLfloat) );
+
+ nmesa->verts = (GLubyte *)tnl->clipspace.vertex_buf;
+}
+
+
diff --git a/src/mesa/drivers/dri/nouveau/nv10_swtcl.h b/src/mesa/drivers/dri/nouveau/nv10_swtcl.h
new file mode 100644
index 0000000000..7c854addd2
--- /dev/null
+++ b/src/mesa/drivers/dri/nouveau/nv10_swtcl.h
@@ -0,0 +1,40 @@
+/**************************************************************************
+
+Copyright 2006 Stephane Marchesin
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+
+
+#ifndef __NV10_SWTCL_H__
+#define __NV10_SWTCL_H__
+
+#include "mtypes.h"
+
+extern void nv10Fallback( GLcontext *ctx, GLuint bit, GLboolean mode );
+extern void nv10FinishPrimitive(struct nouveau_context *nmesa);
+extern void nv10TriInitFunctions(GLcontext *ctx);
+#define FALLBACK( nmesa, bit, mode ) nouveauFallback( nmesa->glCtx, bit, mode )
+
+#endif /* __NV10_SWTCL_H__ */
+
diff --git a/src/mesa/drivers/dri/nouveau/nv20_shader.h b/src/mesa/drivers/dri/nouveau/nv20_shader.h
new file mode 100644
index 0000000000..7d2e29db66
--- /dev/null
+++ b/src/mesa/drivers/dri/nouveau/nv20_shader.h
@@ -0,0 +1,121 @@
+/* NV20_TCL_PRIMITIVE_3D_0x0B00 */
+#define NV20_VP_INST_0B00 0x00000000 /* always 0? */
+#define NV20_VP_INST0_KNOWN 0
+
+/* NV20_TCL_PRIMITIVE_3D_0x0B04 */
+#define NV20_VP_INST_SCA_OPCODE_SHIFT 25
+#define NV20_VP_INST_SCA_OPCODE_MASK (0x0F << 25)
+#define NV20_VP_INST_OPCODE_RCP 0x2
+#define NV20_VP_INST_OPCODE_RCC 0x3
+#define NV20_VP_INST_OPCODE_RSQ 0x4
+#define NV20_VP_INST_OPCODE_EXP 0x5
+#define NV20_VP_INST_OPCODE_LOG 0x6
+#define NV20_VP_INST_OPCODE_LIT 0x7
+#define NV20_VP_INST_VEC_OPCODE_SHIFT 21
+#define NV20_VP_INST_VEC_OPCODE_MASK (0x0F << 21)
+#define NV20_VP_INST_OPCODE_NOP 0x0 /* guess */
+#define NV20_VP_INST_OPCODE_MOV 0x1
+#define NV20_VP_INST_OPCODE_MUL 0x2
+#define NV20_VP_INST_OPCODE_ADD 0x3
+#define NV20_VP_INST_OPCODE_MAD 0x4
+#define NV20_VP_INST_OPCODE_DP3 0x5
+#define NV20_VP_INST_OPCODE_DPH 0x6
+#define NV20_VP_INST_OPCODE_DP4 0x7
+#define NV20_VP_INST_OPCODE_DST 0x8
+#define NV20_VP_INST_OPCODE_MIN 0x9
+#define NV20_VP_INST_OPCODE_MAX 0xA
+#define NV20_VP_INST_OPCODE_SLT 0xB
+#define NV20_VP_INST_OPCODE_SGE 0xC
+#define NV20_VP_INST_OPCODE_ARL 0xD
+#define NV20_VP_INST_CONST_SRC_SHIFT 13
+#define NV20_VP_INST_CONST_SRC_MASK (0xFF << 13)
+#define NV20_VP_INST_INPUT_SRC_SHIFT 9
+#define NV20_VP_INST_INPUT_SRC_MASK (0xF << 9) /* guess */
+#define NV20_VP_INST_INPUT_SRC_POS 0
+#define NV20_VP_INST_INPUT_SRC_COL0 3
+#define NV20_VP_INST_INPUT_SRC_COL1 4
+#define NV20_VP_INST_INPUT_SRC_TC(n) (9+n)
+#define NV20_VP_INST_SRC0H_SHIFT 0
+#define NV20_VP_INST_SRC0H_MASK (0x1FF << 0)
+#define NV20_VP_INST1_KNOWN ( \
+ NV20_VP_INST_OPCODE_MASK | \
+ NV20_VP_INST_CONST_SRC_MASK | \
+ NV20_VP_INST_INPUT_SRC_MASK | \
+ NV20_VP_INST_SRC0H_MASK \
+ )
+
+/* NV20_TCL_PRIMITIVE_3D_0x0B08 */
+#define NV20_VP_INST_SRC0L_SHIFT 26
+#define NV20_VP_INST_SRC0L_MASK (0x3F <<26)
+#define NV20_VP_INST_SRC1_SHIFT 11
+#define NV20_VP_INST_SRC1_MASK (0x7FFF<<11)
+#define NV20_VP_INST_SRC2H_SHIFT 0
+#define NV20_VP_INST_SRC2H_MASK (0x7FF << 0)
+
+/* NV20_TCL_PRIMITIVE_3D_0x0B0C */
+#define NV20_VP_INST_SRC2L_SHIFT 28
+#define NV20_VP_INST_SRC2L_MASK (0x0F <<28)
+#define NV20_VP_INST_VTEMP_WRITEMASK_SHIFT 24
+#define NV20_VP_INST_VTEMP_WRITEMASK_MASK (0x0F <<24)
+# define NV20_VP_INST_TEMP_WRITEMASK_X (1<<27)
+# define NV20_VP_INST_TEMP_WRITEMASK_Y (1<<26)
+# define NV20_VP_INST_TEMP_WRITEMASK_Z (1<<25)
+# define NV20_VP_INST_TEMP_WRITEMASK_W (1<<24)
+#define NV20_VP_INST_DEST_TEMP_ID_SHIFT 20
+#define NV20_VP_INST_DEST_TEMP_ID_MASK (0x0F <<20)
+#define NV20_VP_INST_STEMP_WRITEMASK_SHIFT 16
+#define NV20_VP_INST_STEMP_WRITEMASK_MASK (0x0F <<16)
+# define NV20_VP_INST_STEMP_WRITEMASK_X (1<<19)
+# define NV20_VP_INST_STEMP_WRITEMASK_Y (1<<18)
+# define NV20_VP_INST_STEMP_WRITEMASK_Z (1<<17)
+# define NV20_VP_INST_STEMP_WRITEMASK_W (1<<16)
+#define NV20_VP_INST_DEST_WRITEMASK_SHIFT 12
+#define NV20_VP_INST_DEST_WRITEMASK_MASK (0x0F <<12)
+# define NV20_VP_INST_DEST_WRITEMASK_X (1<<15)
+# define NV20_VP_INST_DEST_WRITEMASK_Y (1<<14)
+# define NV20_VP_INST_DEST_WRITEMASK_Z (1<<13)
+# define NV20_VP_INST_DEST_WRITEMASK_W (1<<12)
+#define NV20_VP_INST_DEST_SHIFT 3
+#define NV20_VP_INST_DEST_MASK (0xF << 3) /* guess */
+#define NV20_VP_INST_DEST_POS 0
+#define NV20_VP_INST_DEST_COL0 3
+#define NV20_VP_INST_DEST_COL1 4
+#define NV20_VP_INST_DEST_TC(n) (9+n)
+#define NV20_VP_INST_INDEX_CONST (1<<1)
+#define NV20_VP_INST3_KNOWN ( \
+ NV20_VP_INST_SRC2L_MASK | \
+ NV20_VP_INST_TEMP_WRITEMASK_MASK | \
+ NV20_VP_INST_DEST_TEMP_ID_MASK | \
+ NV20_VP_INST_STEMP_WRITEMASK_MASK | \
+ NV20_VP_INST_DEST_WRITEMASK_MASK | \
+ NV20_VP_INST_DEST_MASK | \
+ NV20_VP_INST_INDEX_CONST \
+ )
+
+/* Useful to split the source selection regs into their pieces */
+#define NV20_VP_SRC0_HIGH_SHIFT 6
+#define NV20_VP_SRC0_HIGH_MASK 0x00007FC0
+#define NV20_VP_SRC0_LOW_MASK 0x0000003F
+#define NV20_VP_SRC2_HIGH_SHIFT 4
+#define NV20_VP_SRC2_HIGH_MASK 0x00007FF0
+#define NV20_VP_SRC2_LOW_MASK 0x0000000F
+
+#define NV20_VP_SRC_REG_NEGATE (1<<14)
+#define NV20_VP_SRC_REG_SWZ_X_SHIFT 12
+#define NV20_VP_SRC_REG_SWZ_X_MASK (0x03 <<12)
+#define NV20_VP_SRC_REG_SWZ_Y_SHIFT 10
+#define NV20_VP_SRC_REG_SWZ_Y_MASK (0x03 <<10)
+#define NV20_VP_SRC_REG_SWZ_Z_SHIFT 8
+#define NV20_VP_SRC_REG_SWZ_Z_MASK (0x03 << 8)
+#define NV20_VP_SRC_REG_SWZ_W_SHIFT 6
+#define NV20_VP_SRC_REG_SWZ_W_MASK (0x03 << 6)
+#define NV20_VP_SRC_REG_SWZ_ALL_SHIFT 6
+#define NV20_VP_SRC_REG_SWZ_ALL_MASK (0xFF << 6)
+#define NV20_VP_SRC_REG_TEMP_ID_SHIFT 2
+#define NV20_VP_SRC_REG_TEMP_ID_MASK (0x0F << 0)
+#define NV20_VP_SRC_REG_TYPE_SHIFT 0
+#define NV20_VP_SRC_REG_TYPE_MASK (0x03 << 0)
+#define NV20_VP_SRC_REG_TYPE_TEMP 1
+#define NV20_VP_SRC_REG_TYPE_INPUT 2
+#define NV20_VP_SRC_REG_TYPE_CONST 3 /* guess */
+
diff --git a/src/mesa/drivers/dri/nouveau/nv20_state.c b/src/mesa/drivers/dri/nouveau/nv20_state.c
new file mode 100644
index 0000000000..8e38d6eba0
--- /dev/null
+++ b/src/mesa/drivers/dri/nouveau/nv20_state.c
@@ -0,0 +1,662 @@
+/**************************************************************************
+
+Copyright 2006 Nouveau
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+#include "nouveau_context.h"
+#include "nouveau_object.h"
+#include "nouveau_fifo.h"
+#include "nouveau_reg.h"
+
+#include "tnl/t_pipeline.h"
+
+#include "mtypes.h"
+#include "colormac.h"
+
+static void nv20AlphaFunc(GLcontext *ctx, GLenum func, GLfloat ref)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ GLubyte ubRef;
+ CLAMPED_FLOAT_TO_UBYTE(ubRef, ref);
+
+ BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_ALPHA_FUNC_FUNC, 2);
+ OUT_RING_CACHE(func); /* NV20_TCL_PRIMITIVE_3D_ALPHA_FUNC_FUNC */
+ OUT_RING_CACHE(ubRef); /* NV20_TCL_PRIMITIVE_3D_ALPHA_FUNC_REF */
+}
+
+static void nv20BlendColor(GLcontext *ctx, const GLfloat color[4])
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ GLubyte cf[4];
+
+ CLAMPED_FLOAT_TO_UBYTE(cf[0], color[0]);
+ CLAMPED_FLOAT_TO_UBYTE(cf[1], color[1]);
+ CLAMPED_FLOAT_TO_UBYTE(cf[2], color[2]);
+ CLAMPED_FLOAT_TO_UBYTE(cf[3], color[3]);
+
+ BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_BLEND_COLOR, 1);
+ OUT_RING_CACHE(PACK_COLOR_8888(cf[3], cf[1], cf[2], cf[0]));
+}
+
+static void nv20BlendEquationSeparate(GLcontext *ctx, GLenum modeRGB, GLenum modeA)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_BLEND_EQUATION, 1);
+ OUT_RING_CACHE((modeA<<16) | modeRGB);
+}
+
+
+static void nv20BlendFuncSeparate(GLcontext *ctx, GLenum sfactorRGB, GLenum dfactorRGB,
+ GLenum sfactorA, GLenum dfactorA)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_BLEND_FUNC_SRC, 2);
+ OUT_RING_CACHE((sfactorA<<16) | sfactorRGB);
+ OUT_RING_CACHE((dfactorA<<16) | dfactorRGB);
+}
+
+static void nv20ClearColor(GLcontext *ctx, const GLfloat color[4])
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ GLubyte c[4];
+ UNCLAMPED_FLOAT_TO_RGBA_CHAN(c,color);
+ BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_CLEAR_VALUE_ARGB, 1);
+ OUT_RING_CACHE(PACK_COLOR_8888(c[3],c[0],c[1],c[2]));
+}
+
+static void nv20ClearDepth(GLcontext *ctx, GLclampd d)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ nmesa->clear_value=((nmesa->clear_value&0x000000FF)|(((uint32_t)(d*0xFFFFFF))<<8));
+ BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_CLEAR_VALUE_DEPTH, 1);
+ OUT_RING_CACHE(nmesa->clear_value);
+}
+
+/* we're don't support indexed buffers
+ void (*ClearIndex)(GLcontext *ctx, GLuint index)
+ */
+
+static void nv20ClearStencil(GLcontext *ctx, GLint s)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ nmesa->clear_value=((nmesa->clear_value&0xFFFFFF00)|(s&0x000000FF));
+ BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_CLEAR_VALUE_DEPTH, 1);
+ OUT_RING_CACHE(nmesa->clear_value);
+}
+
+static void nv20ClipPlane(GLcontext *ctx, GLenum plane, const GLfloat *equation)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_CLIP_PLANE_A(plane), 4);
+ OUT_RING_CACHEf(equation[0]);
+ OUT_RING_CACHEf(equation[1]);
+ OUT_RING_CACHEf(equation[2]);
+ OUT_RING_CACHEf(equation[3]);
+}
+
+static void nv20ColorMask(GLcontext *ctx, GLboolean rmask, GLboolean gmask,
+ GLboolean bmask, GLboolean amask )
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_COLOR_MASK, 1);
+ OUT_RING_CACHE(((amask && 0x01) << 24) | ((rmask && 0x01) << 16) | ((gmask && 0x01)<< 8) | ((bmask && 0x01) << 0));
+}
+
+static void nv20ColorMaterial(GLcontext *ctx, GLenum face, GLenum mode)
+{
+ // TODO I need love
+}
+
+static void nv20CullFace(GLcontext *ctx, GLenum mode)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_CULL_FACE, 1);
+ OUT_RING_CACHE(mode);
+}
+
+static void nv20FrontFace(GLcontext *ctx, GLenum mode)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_FRONT_FACE, 1);
+ OUT_RING_CACHE(mode);
+}
+
+static void nv20DepthFunc(GLcontext *ctx, GLenum func)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_DEPTH_FUNC, 1);
+ OUT_RING_CACHE(func);
+}
+
+static void nv20DepthMask(GLcontext *ctx, GLboolean flag)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_DEPTH_WRITE_ENABLE, 1);
+ OUT_RING_CACHE(flag);
+}
+
+static void nv20DepthRange(GLcontext *ctx, GLclampd nearval, GLclampd farval)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_DEPTH_RANGE_NEAR, 2);
+ OUT_RING_CACHEf(nearval);
+ OUT_RING_CACHEf(farval);
+}
+
+/** Specify the current buffer for writing */
+//void (*DrawBuffer)( GLcontext *ctx, GLenum buffer );
+/** Specify the buffers for writing for fragment programs*/
+//void (*DrawBuffers)( GLcontext *ctx, GLsizei n, const GLenum *buffers );
+
+static void nv20Enable(GLcontext *ctx, GLenum cap, GLboolean state)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ switch(cap)
+ {
+ case GL_ALPHA_TEST:
+ BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_ALPHA_FUNC_ENABLE, 1);
+ OUT_RING_CACHE(state);
+ break;
+// case GL_AUTO_NORMAL:
+ case GL_BLEND:
+ BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_BLEND_FUNC_ENABLE, 1);
+ OUT_RING_CACHE(state);
+ break;
+ case GL_CLIP_PLANE0:
+ case GL_CLIP_PLANE1:
+ case GL_CLIP_PLANE2:
+ case GL_CLIP_PLANE3:
+ case GL_CLIP_PLANE4:
+ case GL_CLIP_PLANE5:
+ BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_CLIP_PLANE_ENABLE(cap-GL_CLIP_PLANE0), 1);
+ OUT_RING_CACHE(state);
+ break;
+ case GL_COLOR_LOGIC_OP:
+ BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_COLOR_LOGIC_OP_ENABLE, 1);
+ OUT_RING_CACHE(state);
+ break;
+// case GL_COLOR_MATERIAL:
+// case GL_COLOR_SUM_EXT:
+// case GL_COLOR_TABLE:
+// case GL_CONVOLUTION_1D:
+// case GL_CONVOLUTION_2D:
+ case GL_CULL_FACE:
+ BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_CULL_FACE_ENABLE, 1);
+ OUT_RING_CACHE(state);
+ break;
+ case GL_DEPTH_TEST:
+ BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_DEPTH_TEST_ENABLE, 1);
+ OUT_RING_CACHE(state);
+ break;
+ case GL_DITHER:
+ BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_DITHER_ENABLE, 1);
+ OUT_RING_CACHE(state);
+ break;
+ case GL_FOG:
+ BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_FOG_ENABLE, 1);
+ OUT_RING_CACHE(state);
+ break;
+// case GL_HISTOGRAM:
+// case GL_INDEX_LOGIC_OP:
+ case GL_LIGHT0:
+ case GL_LIGHT1:
+ case GL_LIGHT2:
+ case GL_LIGHT3:
+ case GL_LIGHT4:
+ case GL_LIGHT5:
+ case GL_LIGHT6:
+ case GL_LIGHT7:
+ {
+ uint32_t mask=0x11<<(2*(cap-GL_LIGHT0));
+ nmesa->enabled_lights=((nmesa->enabled_lights&mask)|(mask*state));
+ if (nmesa->lighting_enabled)
+ {
+ BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_ENABLED_LIGHTS, 1);
+ OUT_RING_CACHE(nmesa->enabled_lights);
+ }
+ break;
+ }
+ case GL_LIGHTING:
+ nmesa->lighting_enabled=state;
+ BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_ENABLED_LIGHTS, 1);
+ if (nmesa->lighting_enabled)
+ OUT_RING_CACHE(nmesa->enabled_lights);
+ else
+ OUT_RING_CACHE(0x0);
+ break;
+ case GL_LINE_SMOOTH:
+ BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_LINE_SMOOTH_ENABLE, 1);
+ OUT_RING_CACHE(state);
+ break;
+// case GL_LINE_STIPPLE:
+// case GL_MAP1_COLOR_4:
+// case GL_MAP1_INDEX:
+// case GL_MAP1_NORMAL:
+// case GL_MAP1_TEXTURE_COORD_1:
+// case GL_MAP1_TEXTURE_COORD_2:
+// case GL_MAP1_TEXTURE_COORD_3:
+// case GL_MAP1_TEXTURE_COORD_4:
+// case GL_MAP1_VERTEX_3:
+// case GL_MAP1_VERTEX_4:
+// case GL_MAP2_COLOR_4:
+// case GL_MAP2_INDEX:
+// case GL_MAP2_NORMAL:
+// case GL_MAP2_TEXTURE_COORD_1:
+// case GL_MAP2_TEXTURE_COORD_2:
+// case GL_MAP2_TEXTURE_COORD_3:
+// case GL_MAP2_TEXTURE_COORD_4:
+// case GL_MAP2_VERTEX_3:
+// case GL_MAP2_VERTEX_4:
+// case GL_MINMAX:
+ case GL_NORMALIZE:
+ BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_NORMALIZE_ENABLE, 1);
+ OUT_RING_CACHE(state);
+ break;
+// case GL_POINT_SMOOTH:
+ case GL_POLYGON_OFFSET_POINT:
+ BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_POLYGON_OFFSET_POINT_ENABLE, 1);
+ OUT_RING_CACHE(state);
+ break;
+ case GL_POLYGON_OFFSET_LINE:
+ BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_POLYGON_OFFSET_LINE_ENABLE, 1);
+ OUT_RING_CACHE(state);
+ break;
+ case GL_POLYGON_OFFSET_FILL:
+ BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_POLYGON_OFFSET_FILL_ENABLE, 1);
+ OUT_RING_CACHE(state);
+ break;
+ case GL_POLYGON_SMOOTH:
+ BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_POLYGON_SMOOTH_ENABLE, 1);
+ OUT_RING_CACHE(state);
+ break;
+ case GL_POLYGON_STIPPLE:
+ BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_POLYGON_STIPPLE_ENABLE, 1);
+ OUT_RING_CACHE(state);
+ break;
+// case GL_POST_COLOR_MATRIX_COLOR_TABLE:
+// case GL_POST_CONVOLUTION_COLOR_TABLE:
+// case GL_RESCALE_NORMAL:
+// case GL_SCISSOR_TEST:
+// case GL_SEPARABLE_2D:
+ case GL_STENCIL_TEST:
+ // TODO BACK and FRONT ?
+ BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_STENCIL_ENABLE, 1);
+ OUT_RING_CACHE(state);
+ break;
+// case GL_TEXTURE_GEN_Q:
+// case GL_TEXTURE_GEN_R:
+// case GL_TEXTURE_GEN_S:
+// case GL_TEXTURE_GEN_T:
+// case GL_TEXTURE_1D:
+// case GL_TEXTURE_2D:
+// case GL_TEXTURE_3D:
+ }
+}
+
+static void nv20Fogfv(GLcontext *ctx, GLenum pname, const GLfloat *params)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ switch(pname)
+ {
+ case GL_FOG_MODE:
+ BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_FOG_MODE, 1);
+ //OUT_RING_CACHE (params);
+ break;
+ /* TODO: unsure about the rest.*/
+ default:
+ break;
+ }
+
+}
+
+static void nv20Hint(GLcontext *ctx, GLenum target, GLenum mode)
+{
+ // TODO I need love (fog and line_smooth hints)
+}
+
+// void (*IndexMask)(GLcontext *ctx, GLuint mask);
+
+enum {
+ SPOTLIGHT_NO_UPDATE,
+ SPOTLIGHT_UPDATE_EXPONENT,
+ SPOTLIGHT_UPDATE_DIRECTION,
+ SPOTLIGHT_UPDATE_ALL
+};
+
+static void nv20Lightfv(GLcontext *ctx, GLenum light, GLenum pname, const GLfloat *params )
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ GLint p = light - GL_LIGHT0;
+ struct gl_light *l = &ctx->Light.Light[p];
+ int spotlight_update = SPOTLIGHT_NO_UPDATE;
+
+ /* not sure where the fourth param value goes...*/
+ switch(pname)
+ {
+ case GL_AMBIENT:
+ BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_AMBIENT_R(p), 3);
+ OUT_RING_CACHEf(params[0]);
+ OUT_RING_CACHEf(params[1]);
+ OUT_RING_CACHEf(params[2]);
+ break;
+ case GL_DIFFUSE:
+ BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_DIFFUSE_R(p), 3);
+ OUT_RING_CACHEf(params[0]);
+ OUT_RING_CACHEf(params[1]);
+ OUT_RING_CACHEf(params[2]);
+ break;
+ case GL_SPECULAR:
+ BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_SPECULAR_R(p), 3);
+ OUT_RING_CACHEf(params[0]);
+ OUT_RING_CACHEf(params[1]);
+ OUT_RING_CACHEf(params[2]);
+ break;
+ case GL_POSITION:
+ BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_LIGHT_POSITION_X(p), 3);
+ OUT_RING_CACHEf(params[0]);
+ OUT_RING_CACHEf(params[1]);
+ OUT_RING_CACHEf(params[2]);
+ break;
+ case GL_SPOT_DIRECTION:
+ spotlight_update = SPOTLIGHT_UPDATE_DIRECTION;
+ break;
+ case GL_SPOT_EXPONENT:
+ spotlight_update = SPOTLIGHT_UPDATE_EXPONENT;
+ break;
+ case GL_SPOT_CUTOFF:
+ spotlight_update = SPOTLIGHT_UPDATE_ALL;
+ break;
+ case GL_CONSTANT_ATTENUATION:
+ BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_LIGHT_CONSTANT_ATTENUATION(p), 1);
+ OUT_RING_CACHEf(*params);
+ break;
+ case GL_LINEAR_ATTENUATION:
+ BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_LIGHT_LINEAR_ATTENUATION(p), 1);
+ OUT_RING_CACHEf(*params);
+ break;
+ case GL_QUADRATIC_ATTENUATION:
+ BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_LIGHT_QUADRATIC_ATTENUATION(p), 1);
+ OUT_RING_CACHEf(*params);
+ break;
+ default:
+ break;
+ }
+
+ switch(spotlight_update) {
+ case SPOTLIGHT_UPDATE_DIRECTION:
+ {
+ GLfloat x,y,z;
+ GLfloat spot_light_coef_a = 1.0 / (l->_CosCutoff - 1.0);
+ x = spot_light_coef_a * l->_NormDirection[0];
+ y = spot_light_coef_a * l->_NormDirection[1];
+ z = spot_light_coef_a * l->_NormDirection[2];
+ BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_LIGHT_SPOT_DIR_X(p), 3);
+ OUT_RING_CACHEf(x);
+ OUT_RING_CACHEf(y);
+ OUT_RING_CACHEf(z);
+ }
+ break;
+ case SPOTLIGHT_UPDATE_EXPONENT:
+ {
+ GLfloat cc,lc,qc;
+ cc = 1.0; /* FIXME: These need to be correctly computed */
+ lc = 0.0;
+ qc = 2.0;
+ BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_LIGHT_SPOT_CUTOFF_A(p), 3);
+ OUT_RING_CACHEf(cc);
+ OUT_RING_CACHEf(lc);
+ OUT_RING_CACHEf(qc);
+ }
+ break;
+ case SPOTLIGHT_UPDATE_ALL:
+ {
+ GLfloat cc,lc,qc, x,y,z, c;
+ GLfloat spot_light_coef_a = 1.0 / (l->_CosCutoff - 1.0);
+ cc = 1.0; /* FIXME: These need to be correctly computed */
+ lc = 0.0;
+ qc = 2.0;
+ x = spot_light_coef_a * l->_NormDirection[0];
+ y = spot_light_coef_a * l->_NormDirection[1];
+ z = spot_light_coef_a * l->_NormDirection[2];
+ c = spot_light_coef_a + 1.0;
+ BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_LIGHT_SPOT_CUTOFF_A(p), 7);
+ OUT_RING_CACHEf(cc);
+ OUT_RING_CACHEf(lc);
+ OUT_RING_CACHEf(qc);
+ OUT_RING_CACHEf(x);
+ OUT_RING_CACHEf(y);
+ OUT_RING_CACHEf(z);
+ OUT_RING_CACHEf(c);
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+/** Set the lighting model parameters */
+static void (*LightModelfv)(GLcontext *ctx, GLenum pname, const GLfloat *params);
+
+
+static void nv20LineStipple(GLcontext *ctx, GLint factor, GLushort pattern )
+{
+/* nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_LINE_STIPPLE_PATTERN, 1);
+ OUT_RING_CACHE((pattern << 16) | factor);*/
+}
+
+static void nv20LineWidth(GLcontext *ctx, GLfloat width)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_LINE_WIDTH, 1);
+ OUT_RING_CACHEf(width);
+}
+
+static void nv20LogicOpcode(GLcontext *ctx, GLenum opcode)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_COLOR_LOGIC_OP_OP, 1);
+ OUT_RING_CACHE(opcode);
+}
+
+static void nv20PointParameterfv(GLcontext *ctx, GLenum pname, const GLfloat *params)
+{
+ /*TODO: not sure what goes here. */
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+
+}
+
+/** Specify the diameter of rasterized points */
+static void nv20PointSize(GLcontext *ctx, GLfloat size)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_POINT_SIZE, 1);
+ OUT_RING_CACHEf(size);
+}
+
+/** Select a polygon rasterization mode */
+static void nv20PolygonMode(GLcontext *ctx, GLenum face, GLenum mode)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+
+ if (face == GL_FRONT || face == GL_FRONT_AND_BACK) {
+ BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_POLYGON_MODE_FRONT, 1);
+ OUT_RING_CACHE(mode);
+ }
+ if (face == GL_BACK || face == GL_FRONT_AND_BACK) {
+ BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_POLYGON_MODE_BACK, 1);
+ OUT_RING_CACHE(mode);
+ }
+}
+
+/** Set the scale and units used to calculate depth values */
+void (*PolygonOffset)(GLcontext *ctx, GLfloat factor, GLfloat units);
+/** Set the polygon stippling pattern */
+void (*PolygonStipple)(GLcontext *ctx, const GLubyte *mask );
+/* Specifies the current buffer for reading */
+void (*ReadBuffer)( GLcontext *ctx, GLenum buffer );
+/** Set rasterization mode */
+void (*RenderMode)(GLcontext *ctx, GLenum mode );
+
+/** Define the scissor box */
+static void nv20Scissor(GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h)
+{
+}
+
+/** Select flat or smooth shading */
+static void nv20ShadeModel(GLcontext *ctx, GLenum mode)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+
+ BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_SHADE_MODEL, 1);
+ OUT_RING_CACHE(mode);
+}
+
+/** OpenGL 2.0 two-sided StencilFunc */
+static void nv20StencilFuncSeparate(GLcontext *ctx, GLenum face, GLenum func,
+ GLint ref, GLuint mask)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+
+ BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_STENCIL_FUNC_FUNC, 3);
+ OUT_RING_CACHE(func);
+ OUT_RING_CACHE(ref);
+ OUT_RING_CACHE(mask);
+}
+
+/** OpenGL 2.0 two-sided StencilMask */
+static void nv20StencilMaskSeparate(GLcontext *ctx, GLenum face, GLuint mask)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+
+ BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_STENCIL_MASK, 1);
+ OUT_RING_CACHE(mask);
+}
+
+/** OpenGL 2.0 two-sided StencilOp */
+static void nv20StencilOpSeparate(GLcontext *ctx, GLenum face, GLenum fail,
+ GLenum zfail, GLenum zpass)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+
+ BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_STENCIL_OP_FAIL, 1);
+ OUT_RING_CACHE(fail);
+ OUT_RING_CACHE(zfail);
+ OUT_RING_CACHE(zpass);
+}
+
+/** Control the generation of texture coordinates */
+void (*TexGen)(GLcontext *ctx, GLenum coord, GLenum pname,
+ const GLfloat *params);
+/** Set texture environment parameters */
+void (*TexEnv)(GLcontext *ctx, GLenum target, GLenum pname,
+ const GLfloat *param);
+/** Set texture parameters */
+void (*TexParameter)(GLcontext *ctx, GLenum target,
+ struct gl_texture_object *texObj,
+ GLenum pname, const GLfloat *params);
+void (*TextureMatrix)(GLcontext *ctx, GLuint unit, const GLmatrix *mat);
+
+/** Set the viewport */
+static void nv20Viewport(GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h)
+{
+ /* TODO: Where do the VIEWPORT_XFRM_* regs come in? */
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_VIEWPORT_HORIZ, 2);
+ OUT_RING_CACHE((w << 16) | x);
+ OUT_RING_CACHE((h << 16) | y);
+}
+
+/* Initialise any card-specific non-GL related state */
+static GLboolean nv20InitCard(nouveauContextPtr nmesa)
+{
+ return GL_TRUE;
+}
+
+/* Update buffer offset/pitch/format */
+static GLboolean nv20BindBuffers(nouveauContextPtr nmesa, int num_color,
+ nouveau_renderbuffer **color,
+ nouveau_renderbuffer *depth)
+{
+ return GL_TRUE;
+}
+
+/* Update anything that depends on the window position/size */
+static void nv20WindowMoved(nouveauContextPtr nmesa)
+{
+}
+
+void nv20InitStateFuncs(GLcontext *ctx, struct dd_function_table *func)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+
+ nmesa->hw_func.InitCard = nv20InitCard;
+ nmesa->hw_func.BindBuffers = nv20BindBuffers;
+ nmesa->hw_func.WindowMoved = nv20WindowMoved;
+
+ func->AlphaFunc = nv20AlphaFunc;
+ func->BlendColor = nv20BlendColor;
+ func->BlendEquationSeparate = nv20BlendEquationSeparate;
+ func->BlendFuncSeparate = nv20BlendFuncSeparate;
+ func->ClearColor = nv20ClearColor;
+ func->ClearDepth = nv20ClearDepth;
+ func->ClearStencil = nv20ClearStencil;
+ func->ClipPlane = nv20ClipPlane;
+ func->ColorMask = nv20ColorMask;
+ func->ColorMaterial = nv20ColorMaterial;
+ func->CullFace = nv20CullFace;
+ func->FrontFace = nv20FrontFace;
+ func->DepthFunc = nv20DepthFunc;
+ func->DepthMask = nv20DepthMask;
+ func->DepthRange = nv20DepthRange;
+ func->Enable = nv20Enable;
+ func->Fogfv = nv20Fogfv;
+ func->Hint = nv20Hint;
+ func->Lightfv = nv20Lightfv;
+/* func->LightModelfv = nv20LightModelfv; */
+ func->LineStipple = nv20LineStipple;
+ func->LineWidth = nv20LineWidth;
+ func->LogicOpcode = nv20LogicOpcode;
+ func->PointParameterfv = nv20PointParameterfv;
+ func->PointSize = nv20PointSize;
+ func->PolygonMode = nv20PolygonMode;
+#if 0
+ func->PolygonOffset = nv20PolygonOffset;
+ func->PolygonStipple = nv20PolygonStipple;
+ func->ReadBuffer = nv20ReadBuffer;
+ func->RenderMode = nv20RenderMode;
+#endif
+ func->Scissor = nv20Scissor;
+ func->ShadeModel = nv20ShadeModel;
+ func->StencilFuncSeparate = nv20StencilFuncSeparate;
+ func->StencilMaskSeparate = nv20StencilMaskSeparate;
+ func->StencilOpSeparate = nv20StencilOpSeparate;
+#if 0
+ func->TexGen = nv20TexGen;
+ func->TexParameter = nv20TexParameter;
+ func->TextureMatrix = nv20TextureMatrix;
+#endif
+ func->Viewport = nv20Viewport;
+}
+
diff --git a/src/mesa/drivers/dri/nouveau/nv20_vertprog.c b/src/mesa/drivers/dri/nouveau/nv20_vertprog.c
new file mode 100644
index 0000000000..60cfcd7056
--- /dev/null
+++ b/src/mesa/drivers/dri/nouveau/nv20_vertprog.c
@@ -0,0 +1,447 @@
+#include "nouveau_context.h"
+#include "nouveau_object.h"
+#include "nouveau_fifo.h"
+#include "nouveau_reg.h"
+
+#include "nouveau_shader.h"
+#include "nv20_shader.h"
+
+unsigned int NVVP_TX_VOP_COUNT = 16;
+unsigned int NVVP_TX_NVS_OP_COUNT = 16;
+struct _op_xlat NVVP_TX_VOP[32];
+struct _op_xlat NVVP_TX_SOP[32];
+
+nvsSwzComp NV20VP_TX_SWIZZLE[4] = { NVS_SWZ_X, NVS_SWZ_Y, NVS_SWZ_Z, NVS_SWZ_W };
+
+/*****************************************************************************
+ * Support routines
+ */
+static void
+NV20VPUploadToHW(GLcontext *ctx, nouveauShader *nvs)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ int i;
+
+ /* XXX: missing a way to say what insn we're uploading from, and possible
+ * the program start position (if NV20 has one) */
+ for (i=0; i<nvs->program_size; i+=4) {
+ BEGIN_RING_SIZE(NvSub3D, NV20_TCL_PRIMITIVE_3D_VP_UPLOAD_INST0, 4);
+ OUT_RING(nvs->program[i + 0]);
+ OUT_RING(nvs->program[i + 1]);
+ OUT_RING(nvs->program[i + 2]);
+ OUT_RING(nvs->program[i + 3]);
+ }
+}
+
+static void
+NV20VPUpdateConst(GLcontext *ctx, nouveauShader *nvs, int id)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+
+ /* Worth checking if the value *actually* changed? Mesa doesn't tell us this
+ * as far as I know..
+ */
+ BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_VP_UPLOAD_CONST_ID, 1);
+ OUT_RING (id);
+ BEGIN_RING_SIZE(NvSub3D, NV20_TCL_PRIMITIVE_3D_VP_UPLOAD_CONST_X, 4);
+ OUT_RINGf(nvs->params[id].source_val[0]);
+ OUT_RINGf(nvs->params[id].source_val[1]);
+ OUT_RINGf(nvs->params[id].source_val[2]);
+ OUT_RINGf(nvs->params[id].source_val[3]);
+}
+
+/*****************************************************************************
+ * Assembly routines
+ */
+
+/*****************************************************************************
+ * Disassembly routines
+ */
+void
+NV20VPTXSwizzle(int hwswz, nvsSwzComp *swz)
+{
+ swz[NVS_SWZ_X] = NV20VP_TX_SWIZZLE[(hwswz & 0xC0) >> 6];
+ swz[NVS_SWZ_Y] = NV20VP_TX_SWIZZLE[(hwswz & 0x30) >> 4];
+ swz[NVS_SWZ_Z] = NV20VP_TX_SWIZZLE[(hwswz & 0x0C) >> 2];
+ swz[NVS_SWZ_W] = NV20VP_TX_SWIZZLE[(hwswz & 0x03) >> 0];
+}
+
+static int
+NV20VPHasMergedInst(nvsFunc * shader)
+{
+ if (shader->GetOpcodeHW(shader, 0) != NV20_VP_INST_OPCODE_NOP &&
+ shader->GetOpcodeHW(shader, 1) != NV20_VP_INST_OPCODE_NOP)
+ printf
+ ("\n\n*****both opcode fields have values - PLEASE REPORT*****\n");
+ return 0;
+}
+
+static int
+NV20VPIsLastInst(nvsFunc * shader)
+{
+ return ((shader->inst[3] & (1 << 0)) ? 1 : 0);
+}
+
+static int
+NV20VPGetOffsetNext(nvsFunc * shader)
+{
+ return 4;
+}
+
+static struct _op_xlat *
+NV20VPGetOPTXRec(nvsFunc * shader, int merged)
+{
+ struct _op_xlat *opr;
+ int op;
+
+ if (shader->GetOpcodeSlot(shader, merged)) {
+ opr = NVVP_TX_SOP;
+ op = shader->GetOpcodeHW(shader, 1);
+ if (op >= NVVP_TX_NVS_OP_COUNT)
+ return NULL;
+ }
+ else {
+ opr = NVVP_TX_VOP;
+ op = shader->GetOpcodeHW(shader, 0);
+ if (op >= NVVP_TX_VOP_COUNT)
+ return NULL;
+ }
+
+ if (opr[op].SOP == NVS_OP_UNKNOWN)
+ return NULL;
+ return &opr[op];
+}
+
+static struct _op_xlat *
+NV20VPGetOPTXFromSOP(nvsOpcode sop, int *id)
+{
+ int i;
+
+ for (i=0;i<NVVP_TX_VOP_COUNT;i++) {
+ if (NVVP_TX_VOP[i].SOP == sop) {
+ if (id) *id = 0;
+ return &NVVP_TX_VOP[i];
+ }
+ }
+
+ for (i=0;i<NVVP_TX_NVS_OP_COUNT;i++) {
+ if (NVVP_TX_SOP[i].SOP == sop) {
+ if (id) *id = 1;
+ return &NVVP_TX_SOP[i];
+ }
+ }
+
+ return NULL;
+}
+
+static int
+NV20VPGetOpcodeSlot(nvsFunc * shader, int merged)
+{
+ if (shader->HasMergedInst(shader))
+ return merged;
+ if (shader->GetOpcodeHW(shader, 0) == NV20_VP_INST_OPCODE_NOP)
+ return 1;
+ return 0;
+}
+
+static nvsOpcode
+NV20VPGetOpcode(nvsFunc * shader, int merged)
+{
+ struct _op_xlat *opr;
+
+ opr = shader->GetOPTXRec(shader, merged);
+ if (!opr)
+ return NVS_OP_UNKNOWN;
+
+ return opr->SOP;
+}
+
+static nvsOpcode
+NV20VPGetOpcodeHW(nvsFunc * shader, int slot)
+{
+ if (slot)
+ return (shader->inst[1] & NV20_VP_INST_SCA_OPCODE_MASK)
+ >> NV20_VP_INST_SCA_OPCODE_SHIFT;
+ return (shader->inst[1] & NV20_VP_INST_VEC_OPCODE_MASK)
+ >> NV20_VP_INST_VEC_OPCODE_SHIFT;
+}
+
+static nvsRegFile
+NV20VPGetDestFile(nvsFunc * shader, int merged)
+{
+ switch (shader->GetOpcode(shader, merged)) {
+ case NVS_OP_ARL:
+ return NVS_FILE_ADDRESS;
+ default:
+ /*FIXME: This probably isn't correct.. */
+ if ((shader->inst[3] & NV20_VP_INST_DEST_WRITEMASK_MASK) == 0)
+ return NVS_FILE_TEMP;
+ return NVS_FILE_RESULT;
+ }
+}
+
+static unsigned int
+NV20VPGetDestID(nvsFunc * shader, int merged)
+{
+ int id;
+
+ switch (shader->GetDestFile(shader, merged)) {
+ case NVS_FILE_RESULT:
+ id = ((shader->inst[3] & NV20_VP_INST_DEST_MASK)
+ >> NV20_VP_INST_DEST_SHIFT);
+ switch (id) {
+ case NV20_VP_INST_DEST_POS : return NVS_FR_POSITION;
+ case NV20_VP_INST_DEST_COL0 : return NVS_FR_COL0;
+ case NV20_VP_INST_DEST_COL1 : return NVS_FR_COL1;
+ case NV20_VP_INST_DEST_TC(0): return NVS_FR_TEXCOORD0;
+ case NV20_VP_INST_DEST_TC(1): return NVS_FR_TEXCOORD1;
+ case NV20_VP_INST_DEST_TC(2): return NVS_FR_TEXCOORD2;
+ case NV20_VP_INST_DEST_TC(3): return NVS_FR_TEXCOORD3;
+ default:
+ return -1;
+ }
+ case NVS_FILE_ADDRESS:
+ return 0;
+ case NVS_FILE_TEMP:
+ id = ((shader->inst[3] & NV20_VP_INST_DEST_TEMP_ID_MASK)
+ >> NV20_VP_INST_DEST_TEMP_ID_SHIFT);
+ return id;
+ default:
+ return -1;
+ }
+}
+
+static unsigned int
+NV20VPGetDestMask(nvsFunc * shader, int merged)
+{
+ int hwmask, mask = 0;
+
+ /* Special handling for ARL - hardware only supports a
+ * 1-component address reg
+ */
+ if (shader->GetOpcode(shader, merged) == NVS_OP_ARL)
+ return SMASK_X;
+
+ if (shader->GetDestFile(shader, merged) == NVS_FILE_RESULT)
+ hwmask = (shader->inst[3] & NV20_VP_INST_DEST_WRITEMASK_MASK)
+ >> NV20_VP_INST_DEST_WRITEMASK_SHIFT;
+ else if (shader->GetOpcodeSlot(shader, merged))
+ hwmask = (shader->inst[3] & NV20_VP_INST_STEMP_WRITEMASK_MASK)
+ >> NV20_VP_INST_STEMP_WRITEMASK_SHIFT;
+ else
+ hwmask = (shader->inst[3] & NV20_VP_INST_VTEMP_WRITEMASK_MASK)
+ >> NV20_VP_INST_VTEMP_WRITEMASK_SHIFT;
+
+ if (hwmask & (1 << 3)) mask |= SMASK_X;
+ if (hwmask & (1 << 2)) mask |= SMASK_Y;
+ if (hwmask & (1 << 1)) mask |= SMASK_Z;
+ if (hwmask & (1 << 0)) mask |= SMASK_W;
+
+ return mask;
+}
+
+static unsigned int
+NV20VPGetSourceHW(nvsFunc * shader, int merged, int pos)
+{
+ struct _op_xlat *opr;
+ unsigned int src;
+
+ opr = shader->GetOPTXRec(shader, merged);
+ if (!opr)
+ return -1;
+
+ switch (opr->srcpos[pos]) {
+ case 0:
+ src = ((shader->inst[1] & NV20_VP_INST_SRC0H_MASK)
+ >> NV20_VP_INST_SRC0H_SHIFT)
+ << NV20_VP_SRC0_HIGH_SHIFT;
+ src |= ((shader->inst[2] & NV20_VP_INST_SRC0L_MASK)
+ >> NV20_VP_INST_SRC0L_SHIFT);
+ break;
+ case 1:
+ src = ((shader->inst[2] & NV20_VP_INST_SRC1_MASK)
+ >> NV20_VP_INST_SRC1_SHIFT);
+ break;
+ case 2:
+ src = ((shader->inst[2] & NV20_VP_INST_SRC2H_MASK)
+ >> NV20_VP_INST_SRC2H_SHIFT)
+ << NV20_VP_SRC2_HIGH_SHIFT;
+ src |= ((shader->inst[3] & NV20_VP_INST_SRC2L_MASK)
+ >> NV20_VP_INST_SRC2L_SHIFT);
+ break;
+ default:
+ src = -1;
+ }
+
+ return src;
+}
+
+static nvsRegFile
+NV20VPGetSourceFile(nvsFunc * shader, int merged, int pos)
+{
+ unsigned int src;
+ struct _op_xlat *opr;
+ int file;
+
+ opr = shader->GetOPTXRec(shader, merged);
+ if (!opr || opr->srcpos[pos] == -1)
+ return -1;
+
+ switch (opr->srcpos[pos]) {
+ case SPOS_ADDRESS:
+ return NVS_FILE_ADDRESS;
+ default:
+ src = NV20VPGetSourceHW(shader, merged, pos);
+ file = (src & NV20_VP_SRC_REG_TYPE_MASK) >> NV20_VP_SRC_REG_TYPE_SHIFT;
+
+ switch (file) {
+ case NV20_VP_SRC_REG_TYPE_TEMP : return NVS_FILE_TEMP;
+ case NV20_VP_SRC_REG_TYPE_INPUT: return NVS_FILE_ATTRIB;
+ case NV20_VP_SRC_REG_TYPE_CONST: return NVS_FILE_CONST;
+ default:
+ return NVS_FILE_UNKNOWN;
+ }
+ }
+}
+
+static int
+NV20VPGetSourceID(nvsFunc * shader, int merged, int pos)
+{
+ unsigned int src;
+
+ switch (shader->GetSourceFile(shader, merged, pos)) {
+ case NVS_FILE_TEMP:
+ src = shader->GetSourceHW(shader, merged, pos);
+ return ((src & NV20_VP_SRC_REG_TEMP_ID_MASK) >>
+ NV20_VP_SRC_REG_TEMP_ID_SHIFT);
+ case NVS_FILE_CONST:
+ return ((shader->inst[1] & NV20_VP_INST_CONST_SRC_MASK)
+ >> NV20_VP_INST_CONST_SRC_SHIFT);
+ case NVS_FILE_ATTRIB:
+ src = ((shader->inst[1] & NV20_VP_INST_INPUT_SRC_MASK)
+ >> NV20_VP_INST_INPUT_SRC_SHIFT);
+ switch (src) {
+ case NV20_VP_INST_INPUT_SRC_POS : return NVS_FR_POSITION;
+ case NV20_VP_INST_INPUT_SRC_COL0 : return NVS_FR_COL0;
+ case NV20_VP_INST_INPUT_SRC_COL1 : return NVS_FR_COL1;
+ case NV20_VP_INST_INPUT_SRC_TC(0): return NVS_FR_TEXCOORD0;
+ case NV20_VP_INST_INPUT_SRC_TC(1): return NVS_FR_TEXCOORD1;
+ case NV20_VP_INST_INPUT_SRC_TC(2): return NVS_FR_TEXCOORD2;
+ case NV20_VP_INST_INPUT_SRC_TC(3): return NVS_FR_TEXCOORD3;
+ default:
+ return NVS_FR_UNKNOWN;
+ }
+ default:
+ return -1;
+ }
+}
+
+static int
+NV20VPGetSourceNegate(nvsFunc * shader, int merged, int pos)
+{
+ unsigned int src;
+
+ src = shader->GetSourceHW(shader, merged, pos);
+
+ return ((src & NV20_VP_SRC_REG_NEGATE) ? 1 : 0);
+}
+
+static int
+NV20VPGetSourceAbs(nvsFunc * shader, int merged, int pos)
+{
+ /* NV20 can't do ABS on sources? Appears to be emulated with
+ * MAX reg, reg, -reg
+ */
+ return 0;
+}
+
+static void
+NV20VPGetSourceSwizzle(nvsFunc * shader, int merged, int pos, nvsSwzComp *swz)
+{
+ unsigned int src;
+ int swzbits;
+
+ src = shader->GetSourceHW(shader, merged, pos);
+ swzbits =
+ (src & NV20_VP_SRC_REG_SWZ_ALL_MASK) >> NV20_VP_SRC_REG_SWZ_ALL_SHIFT;
+ return NV20VPTXSwizzle(swzbits, swz);
+}
+
+static int
+NV20VPGetSourceIndexed(nvsFunc * shader, int merged, int pos)
+{
+ /* I don't think NV20 can index into attribs, at least no GL
+ * extension is exposed that will allow it.
+ */
+ if (shader->GetSourceFile(shader, merged, pos) != NVS_FILE_CONST)
+ return 0;
+ if (shader->inst[3] & NV20_VP_INST_INDEX_CONST)
+ return 1;
+ return 0;
+}
+
+static int
+NV20VPGetAddressRegID(nvsFunc * shader)
+{
+ /* Only 1 address reg */
+ return 0;
+}
+
+static nvsSwzComp
+NV20VPGetAddressRegSwizzle(nvsFunc * shader)
+{
+ /* Only A0.x available */
+ return NVS_SWZ_X;
+}
+
+void
+NV20VPInitShaderFuncs(nvsFunc * shader)
+{
+ MOD_OPCODE(NVVP_TX_VOP, NV20_VP_INST_OPCODE_NOP, NVS_OP_NOP, -1, -1, -1);
+ MOD_OPCODE(NVVP_TX_VOP, NV20_VP_INST_OPCODE_MOV, NVS_OP_MOV, 0, -1, -1);
+ MOD_OPCODE(NVVP_TX_VOP, NV20_VP_INST_OPCODE_MUL, NVS_OP_MUL, 0, 1, -1);
+ MOD_OPCODE(NVVP_TX_VOP, NV20_VP_INST_OPCODE_ADD, NVS_OP_ADD, 0, 2, -1);
+ MOD_OPCODE(NVVP_TX_VOP, NV20_VP_INST_OPCODE_MAD, NVS_OP_MAD, 0, 1, 2);
+ MOD_OPCODE(NVVP_TX_VOP, NV20_VP_INST_OPCODE_DP3, NVS_OP_DP3, 0, 1, -1);
+ MOD_OPCODE(NVVP_TX_VOP, NV20_VP_INST_OPCODE_DPH, NVS_OP_DPH, 0, 1, -1);
+ MOD_OPCODE(NVVP_TX_VOP, NV20_VP_INST_OPCODE_DP4, NVS_OP_DP4, 0, 1, -1);
+ MOD_OPCODE(NVVP_TX_VOP, NV20_VP_INST_OPCODE_DST, NVS_OP_DST, 0, 1, -1);
+ MOD_OPCODE(NVVP_TX_VOP, NV20_VP_INST_OPCODE_MIN, NVS_OP_MIN, 0, 1, -1);
+ MOD_OPCODE(NVVP_TX_VOP, NV20_VP_INST_OPCODE_MAX, NVS_OP_MAX, 0, 1, -1);
+ MOD_OPCODE(NVVP_TX_VOP, NV20_VP_INST_OPCODE_SLT, NVS_OP_SLT, 0, 1, -1);
+ MOD_OPCODE(NVVP_TX_VOP, NV20_VP_INST_OPCODE_SGE, NVS_OP_SGE, 0, 1, -1);
+ MOD_OPCODE(NVVP_TX_VOP, NV20_VP_INST_OPCODE_ARL, NVS_OP_ARL, 0, -1, -1);
+
+ MOD_OPCODE(NVVP_TX_SOP, NV20_VP_INST_OPCODE_NOP, NVS_OP_NOP, -1, -1, -1);
+ MOD_OPCODE(NVVP_TX_SOP, NV20_VP_INST_OPCODE_RCP, NVS_OP_RCP, 2, -1, -1);
+ MOD_OPCODE(NVVP_TX_SOP, NV20_VP_INST_OPCODE_RCC, NVS_OP_RCC, 2, -1, -1);
+ MOD_OPCODE(NVVP_TX_SOP, NV20_VP_INST_OPCODE_RSQ, NVS_OP_RSQ, 2, -1, -1);
+ MOD_OPCODE(NVVP_TX_SOP, NV20_VP_INST_OPCODE_EXP, NVS_OP_EXP, 2, -1, -1);
+ MOD_OPCODE(NVVP_TX_SOP, NV20_VP_INST_OPCODE_LOG, NVS_OP_LOG, 2, -1, -1);
+ MOD_OPCODE(NVVP_TX_SOP, NV20_VP_INST_OPCODE_LIT, NVS_OP_LIT, 2, -1, -1);
+
+ shader->UploadToHW = NV20VPUploadToHW;
+ shader->UpdateConst = NV20VPUpdateConst;
+
+ shader->GetOPTXRec = NV20VPGetOPTXRec;
+ shader->GetOPTXFromSOP = NV20VPGetOPTXFromSOP;
+
+ shader->HasMergedInst = NV20VPHasMergedInst;
+ shader->IsLastInst = NV20VPIsLastInst;
+ shader->GetOffsetNext = NV20VPGetOffsetNext;
+ shader->GetOpcodeSlot = NV20VPGetOpcodeSlot;
+ shader->GetOpcode = NV20VPGetOpcode;
+ shader->GetOpcodeHW = NV20VPGetOpcodeHW;
+ shader->GetDestFile = NV20VPGetDestFile;
+ shader->GetDestID = NV20VPGetDestID;
+ shader->GetDestMask = NV20VPGetDestMask;
+ shader->GetSourceHW = NV20VPGetSourceHW;
+ shader->GetSourceFile = NV20VPGetSourceFile;
+ shader->GetSourceID = NV20VPGetSourceID;
+ shader->GetSourceNegate = NV20VPGetSourceNegate;
+ shader->GetSourceAbs = NV20VPGetSourceAbs;
+ shader->GetSourceSwizzle = NV20VPGetSourceSwizzle;
+ shader->GetSourceIndexed = NV20VPGetSourceIndexed;
+ shader->GetRelAddressRegID = NV20VPGetAddressRegID;
+ shader->GetRelAddressSwizzle = NV20VPGetAddressRegSwizzle;
+}
diff --git a/src/mesa/drivers/dri/nouveau/nv30_fragprog.c b/src/mesa/drivers/dri/nouveau/nv30_fragprog.c
new file mode 100644
index 0000000000..cd7c955c9e
--- /dev/null
+++ b/src/mesa/drivers/dri/nouveau/nv30_fragprog.c
@@ -0,0 +1,716 @@
+#include <stdint.h>
+
+#include "glheader.h"
+#include "macros.h"
+
+#include "nouveau_context.h"
+#include "nouveau_fifo.h"
+#include "nouveau_reg.h"
+#include "nouveau_drm.h"
+#include "nouveau_shader.h"
+#include "nouveau_object.h"
+#include "nouveau_msg.h"
+#include "nouveau_bufferobj.h"
+#include "nv30_shader.h"
+
+unsigned int NVFP_TX_AOP_COUNT = 64;
+struct _op_xlat NVFP_TX_AOP[64];
+
+/*******************************************************************************
+ * Support routines
+ */
+
+static void
+NV30FPUploadToHW(GLcontext *ctx, nouveauShader *nvs)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ uint32_t offset;
+
+ if (!nvs->program_buffer)
+ nvs->program_buffer = ctx->Driver.NewBufferObject(ctx, 0,
+ GL_ARRAY_BUFFER_ARB);
+
+ /* Should use STATIC_DRAW_ARB if shader doesn't use changable params */
+ ctx->Driver.BufferData(ctx, GL_ARRAY_BUFFER_ARB,
+ nvs->program_size * sizeof(uint32_t),
+ (const GLvoid *)nvs->program,
+ GL_DYNAMIC_DRAW_ARB,
+ nvs->program_buffer);
+
+ offset = nouveau_bufferobj_gpu_ref(ctx, GL_READ_ONLY_ARB,
+ nvs->program_buffer);
+
+ /* Not using state cache here, updated programs at the same address don't
+ * seem to take effect unless the ACTIVE_PROGRAM method is called again.
+ * HW caches the program somewhere?
+ */
+ BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_FP_ACTIVE_PROGRAM, 1);
+ OUT_RING (offset | 1);
+}
+
+static void
+NV30FPUpdateConst(GLcontext *ctx, nouveauShader *nvs, int id)
+{
+ uint32_t *new = nvs->params[id].source_val ?
+ (uint32_t*)nvs->params[id].source_val : (uint32_t*)nvs->params[id].val;
+ uint32_t *current;
+ int i;
+
+ for (i=0; i<nvs->params[id].hw_index_cnt; i++) {
+ current = nvs->program + nvs->params[id].hw_index[i];
+ COPY_4V(current, new);
+ }
+ nvs->on_hardware = 0;
+}
+
+/*******************************************************************************
+ * Assembly helpers
+ */
+static struct _op_xlat *
+NV30FPGetOPTXFromSOP(nvsOpcode op, int *id)
+{
+ int i;
+
+ for (i=0; i<NVFP_TX_AOP_COUNT; i++) {
+ if (NVFP_TX_AOP[i].SOP == op) {
+ if (id) *id = 0;
+ return &NVFP_TX_AOP[i];
+ }
+ }
+
+ return NULL;
+}
+
+static int
+NV30FPSupportsOpcode(nvsFunc *shader, nvsOpcode op)
+{
+ if (shader->GetOPTXFromSOP(op, NULL))
+ return 1;
+ return 0;
+}
+
+static void
+NV30FPSetOpcode(nvsFunc *shader, unsigned int opcode, int slot)
+{
+ shader->inst[0] &= ~NV30_FP_OP_OPCODE_MASK;
+ shader->inst[0] |= (opcode << NV30_FP_OP_OPCODE_SHIFT);
+}
+
+static void
+NV30FPSetCCUpdate(nvsFunc *shader)
+{
+ shader->inst[0] |= NV30_FP_OP_COND_WRITE_ENABLE;
+}
+
+static void
+NV30FPSetCondition(nvsFunc *shader, int on, nvsCond cond, int reg,
+ nvsSwzComp *swz)
+{
+ nvsSwzComp default_swz[4] = { NVS_SWZ_X, NVS_SWZ_Y, NVS_SWZ_Z, NVS_SWZ_W };
+ unsigned int hwcond;
+
+ /* cond masking is always enabled */
+ if (!on) {
+ cond = NVS_COND_TR;
+ reg = 0;
+ swz = default_swz;
+ }
+
+ switch (cond) {
+ case NVS_COND_TR: hwcond = NV30_FP_OP_COND_TR; break;
+ case NVS_COND_FL: hwcond = NV30_FP_OP_COND_FL; break;
+ case NVS_COND_LT: hwcond = NV30_FP_OP_COND_LT; break;
+ case NVS_COND_GT: hwcond = NV30_FP_OP_COND_GT; break;
+ case NVS_COND_LE: hwcond = NV30_FP_OP_COND_LE; break;
+ case NVS_COND_GE: hwcond = NV30_FP_OP_COND_GE; break;
+ case NVS_COND_EQ: hwcond = NV30_FP_OP_COND_EQ; break;
+ case NVS_COND_NE: hwcond = NV30_FP_OP_COND_NE; break;
+ default:
+ WARN_ONCE("unknown fp condmask=%d\n", cond);
+ hwcond = NV30_FP_OP_COND_TR;
+ break;
+ }
+
+ shader->inst[1] &= ~NV30_FP_OP_COND_MASK;
+ shader->inst[1] |= (hwcond << NV30_FP_OP_COND_SHIFT);
+
+ shader->inst[1] &= ~NV30_FP_OP_COND_SWZ_ALL_MASK;
+ shader->inst[1] |= (swz[NVS_SWZ_X] << NV30_FP_OP_COND_SWZ_X_SHIFT);
+ shader->inst[1] |= (swz[NVS_SWZ_Y] << NV30_FP_OP_COND_SWZ_Y_SHIFT);
+ shader->inst[1] |= (swz[NVS_SWZ_Z] << NV30_FP_OP_COND_SWZ_Z_SHIFT);
+ shader->inst[1] |= (swz[NVS_SWZ_W] << NV30_FP_OP_COND_SWZ_W_SHIFT);
+}
+
+static void
+NV30FPSetResult(nvsFunc *shader, nvsRegister *reg, unsigned int mask, int slot)
+{
+ unsigned int hwreg;
+
+ if (mask & SMASK_X) shader->inst[0] |= NV30_FP_OP_OUT_X;
+ if (mask & SMASK_Y) shader->inst[0] |= NV30_FP_OP_OUT_Y;
+ if (mask & SMASK_Z) shader->inst[0] |= NV30_FP_OP_OUT_Z;
+ if (mask & SMASK_W) shader->inst[0] |= NV30_FP_OP_OUT_W;
+
+ if (reg->file == NVS_FILE_RESULT) {
+ hwreg = 0; /* FIXME: this is only fragment.color */
+ /* This is *not* correct, I have no idea what it is either */
+ shader->inst[0] |= NV30_FP_OP_UNK0_7;
+ } else {
+ shader->inst[0] &= ~NV30_FP_OP_UNK0_7;
+ hwreg = reg->index;
+ }
+ shader->inst[0] &= ~NV30_FP_OP_OUT_REG_SHIFT;
+ shader->inst[0] |= (hwreg << NV30_FP_OP_OUT_REG_SHIFT);
+}
+
+static void
+NV30FPSetSource(nvsFunc *shader, nvsRegister *reg, int pos)
+{
+ unsigned int hwsrc = 0;
+
+ switch (reg->file) {
+ case NVS_FILE_TEMP:
+ hwsrc |= (NV30_FP_REG_TYPE_TEMP << NV30_FP_REG_TYPE_SHIFT);
+ hwsrc |= (reg->index << NV30_FP_REG_SRC_SHIFT);
+ break;
+ case NVS_FILE_ATTRIB:
+ {
+ unsigned int hwin;
+
+ switch (reg->index) {
+ case NVS_FR_POSITION : hwin = NV30_FP_OP_INPUT_SRC_POSITION; break;
+ case NVS_FR_COL0 : hwin = NV30_FP_OP_INPUT_SRC_COL0; break;
+ case NVS_FR_COL1 : hwin = NV30_FP_OP_INPUT_SRC_COL1; break;
+ case NVS_FR_FOGCOORD : hwin = NV30_FP_OP_INPUT_SRC_FOGC; break;
+ case NVS_FR_TEXCOORD0: hwin = NV30_FP_OP_INPUT_SRC_TC(0); break;
+ case NVS_FR_TEXCOORD1: hwin = NV30_FP_OP_INPUT_SRC_TC(1); break;
+ case NVS_FR_TEXCOORD2: hwin = NV30_FP_OP_INPUT_SRC_TC(2); break;
+ case NVS_FR_TEXCOORD3: hwin = NV30_FP_OP_INPUT_SRC_TC(3); break;
+ case NVS_FR_TEXCOORD4: hwin = NV30_FP_OP_INPUT_SRC_TC(4); break;
+ case NVS_FR_TEXCOORD5: hwin = NV30_FP_OP_INPUT_SRC_TC(5); break;
+ case NVS_FR_TEXCOORD6: hwin = NV30_FP_OP_INPUT_SRC_TC(6); break;
+ case NVS_FR_TEXCOORD7: hwin = NV30_FP_OP_INPUT_SRC_TC(7); break;
+ default:
+ WARN_ONCE("unknown fp input %d\n", reg->index);
+ hwin = NV30_FP_OP_INPUT_SRC_COL0;
+ break;
+ }
+ shader->inst[0] &= ~NV30_FP_OP_INPUT_SRC_MASK;
+ shader->inst[0] |= (hwin << NV30_FP_OP_INPUT_SRC_SHIFT);
+ hwsrc |= (hwin << NV30_FP_REG_SRC_SHIFT);
+ }
+ hwsrc |= (NV30_FP_REG_TYPE_INPUT << NV30_FP_REG_TYPE_SHIFT);
+ break;
+ case NVS_FILE_CONST:
+ /* consts are inlined after the inst */
+ hwsrc |= (NV30_FP_REG_TYPE_CONST << NV30_FP_REG_TYPE_SHIFT);
+ break;
+ default:
+ assert(0);
+ break;
+ }
+
+ if (reg->negate)
+ hwsrc |= NV30_FP_REG_NEGATE;
+ if (reg->abs)
+ shader->inst[1] |= (1 << (29+pos));
+ hwsrc |= (reg->swizzle[NVS_SWZ_X] << NV30_FP_REG_SWZ_X_SHIFT);
+ hwsrc |= (reg->swizzle[NVS_SWZ_Y] << NV30_FP_REG_SWZ_Y_SHIFT);
+ hwsrc |= (reg->swizzle[NVS_SWZ_Z] << NV30_FP_REG_SWZ_Z_SHIFT);
+ hwsrc |= (reg->swizzle[NVS_SWZ_W] << NV30_FP_REG_SWZ_W_SHIFT);
+
+ shader->inst[pos+1] &= ~NV30_FP_REG_ALL_MASK;
+ shader->inst[pos+1] |= hwsrc;
+}
+
+static void
+NV30FPSetTexImageUnit(nvsFunc *shader, int unit)
+{
+ shader->inst[0] &= ~NV30_FP_OP_TEX_UNIT_SHIFT;
+ shader->inst[0] |= (unit << NV30_FP_OP_TEX_UNIT_SHIFT);
+}
+
+static void
+NV30FPSetSaturate(nvsFunc *shader)
+{
+ shader->inst[0] |= NV30_FP_OP_OUT_SAT;
+}
+
+static void
+NV30FPInitInstruction(nvsFunc *shader)
+{
+ unsigned int hwsrc;
+
+ shader->inst[0] = 0;
+
+ hwsrc = (NV30_FP_REG_TYPE_INPUT << NV30_FP_REG_TYPE_SHIFT) |
+ (NVS_SWZ_X << NV30_FP_REG_SWZ_X_SHIFT) |
+ (NVS_SWZ_Y << NV30_FP_REG_SWZ_Y_SHIFT) |
+ (NVS_SWZ_Z << NV30_FP_REG_SWZ_Z_SHIFT) |
+ (NVS_SWZ_W << NV30_FP_REG_SWZ_W_SHIFT);
+ shader->inst[1] = hwsrc;
+ shader->inst[2] = hwsrc;
+ shader->inst[3] = hwsrc;
+}
+
+static void
+NV30FPSetLastInst(nvsFunc *shader)
+{
+ shader->inst[0] |= 1;
+}
+
+/*******************************************************************************
+ * Disassembly helpers
+ */
+static struct _op_xlat *
+NV30FPGetOPTXRec(nvsFunc * shader, int merged)
+{
+ int op;
+
+ op = shader->GetOpcodeHW(shader, 0);
+ if (op > NVFP_TX_AOP_COUNT)
+ return NULL;
+ if (NVFP_TX_AOP[op].SOP == NVS_OP_UNKNOWN)
+ return NULL;
+ return &NVFP_TX_AOP[op];
+}
+
+static int
+NV30FPHasMergedInst(nvsFunc * shader)
+{
+ return 0;
+}
+
+static int
+NV30FPIsLastInst(nvsFunc * shader)
+{
+ return ((shader->inst[0] & NV30_FP_OP_PROGRAM_END) ? 1 : 0);
+}
+
+static int
+NV30FPGetOffsetNext(nvsFunc * shader)
+{
+ int i;
+
+ for (i = 0; i < 3; i++)
+ if (shader->GetSourceFile(shader, 0, i) == NVS_FILE_CONST)
+ return 8;
+ return 4;
+}
+
+static nvsOpcode
+NV30FPGetOpcode(nvsFunc * shader, int merged)
+{
+ struct _op_xlat *opr;
+
+ opr = shader->GetOPTXRec(shader, merged);
+ if (!opr)
+ return NVS_OP_UNKNOWN;
+
+ return opr->SOP;
+}
+
+static unsigned int
+NV30FPGetOpcodeHW(nvsFunc * shader, int slot)
+{
+ int op;
+
+ op = (shader->inst[0] & NV30_FP_OP_OPCODE_MASK) >> NV30_FP_OP_OPCODE_SHIFT;
+
+ return op;
+}
+
+static nvsRegFile
+NV30FPGetDestFile(nvsFunc * shader, int merged)
+{
+ /* Result regs overlap temporary regs */
+ return NVS_FILE_TEMP;
+}
+
+static unsigned int
+NV30FPGetDestID(nvsFunc * shader, int merged)
+{
+ int id;
+
+ switch (shader->GetDestFile(shader, merged)) {
+ case NVS_FILE_TEMP:
+ id = ((shader->inst[0] & NV30_FP_OP_OUT_REG_MASK)
+ >> NV30_FP_OP_OUT_REG_SHIFT);
+ return id;
+ default:
+ return -1;
+ }
+}
+
+static unsigned int
+NV30FPGetDestMask(nvsFunc * shader, int merged)
+{
+ unsigned int mask = 0;
+
+ if (shader->inst[0] & NV30_FP_OP_OUT_X) mask |= SMASK_X;
+ if (shader->inst[0] & NV30_FP_OP_OUT_Y) mask |= SMASK_Y;
+ if (shader->inst[0] & NV30_FP_OP_OUT_Z) mask |= SMASK_Z;
+ if (shader->inst[0] & NV30_FP_OP_OUT_W) mask |= SMASK_W;
+
+ return mask;
+}
+
+static unsigned int
+NV30FPGetSourceHW(nvsFunc * shader, int merged, int pos)
+{
+ struct _op_xlat *opr;
+
+ opr = shader->GetOPTXRec(shader, merged);
+ if (!opr || opr->srcpos[pos] == -1)
+ return -1;
+
+ return shader->inst[opr->srcpos[pos] + 1];
+}
+
+static nvsRegFile
+NV30FPGetSourceFile(nvsFunc * shader, int merged, int pos)
+{
+ unsigned int src;
+ struct _op_xlat *opr;
+ int file;
+
+ opr = shader->GetOPTXRec(shader, merged);
+ if (!opr || opr->srcpos[pos] == -1)
+ return NVS_FILE_UNKNOWN;
+
+ switch (opr->srcpos[pos]) {
+ case SPOS_ADDRESS: return NVS_FILE_ADDRESS;
+ default:
+ src = shader->GetSourceHW(shader, merged, pos);
+ file = (src & NV30_FP_REG_TYPE_MASK) >> NV30_FP_REG_TYPE_SHIFT;
+
+ switch (file) {
+ case NV30_FP_REG_TYPE_TEMP : return NVS_FILE_TEMP;
+ case NV30_FP_REG_TYPE_INPUT: return NVS_FILE_ATTRIB;
+ case NV30_FP_REG_TYPE_CONST: return NVS_FILE_CONST;
+ default:
+ return NVS_FILE_UNKNOWN;
+ }
+ }
+}
+
+static int
+NV30FPGetSourceID(nvsFunc * shader, int merged, int pos)
+{
+ switch (shader->GetSourceFile(shader, merged, pos)) {
+ case NVS_FILE_ATTRIB:
+ switch ((shader->inst[0] & NV30_FP_OP_INPUT_SRC_MASK)
+ >> NV30_FP_OP_INPUT_SRC_SHIFT) {
+ case NV30_FP_OP_INPUT_SRC_POSITION: return NVS_FR_POSITION;
+ case NV30_FP_OP_INPUT_SRC_COL0 : return NVS_FR_COL0;
+ case NV30_FP_OP_INPUT_SRC_COL1 : return NVS_FR_COL1;
+ case NV30_FP_OP_INPUT_SRC_FOGC : return NVS_FR_FOGCOORD;
+ case NV30_FP_OP_INPUT_SRC_TC(0) : return NVS_FR_TEXCOORD0;
+ case NV30_FP_OP_INPUT_SRC_TC(1) : return NVS_FR_TEXCOORD1;
+ case NV30_FP_OP_INPUT_SRC_TC(2) : return NVS_FR_TEXCOORD2;
+ case NV30_FP_OP_INPUT_SRC_TC(3) : return NVS_FR_TEXCOORD3;
+ case NV30_FP_OP_INPUT_SRC_TC(4) : return NVS_FR_TEXCOORD4;
+ case NV30_FP_OP_INPUT_SRC_TC(5) : return NVS_FR_TEXCOORD5;
+ case NV30_FP_OP_INPUT_SRC_TC(6) : return NVS_FR_TEXCOORD6;
+ case NV30_FP_OP_INPUT_SRC_TC(7) : return NVS_FR_TEXCOORD7;
+ default:
+ return -1;
+ }
+ break;
+ case NVS_FILE_TEMP:
+ {
+ unsigned int src;
+
+ src = shader->GetSourceHW(shader, merged, pos);
+ return ((src & NV30_FP_REG_SRC_MASK) >> NV30_FP_REG_SRC_SHIFT);
+ }
+ case NVS_FILE_CONST: /* inlined into fragprog */
+ default:
+ return -1;
+ }
+}
+
+static int
+NV30FPGetTexImageUnit(nvsFunc *shader)
+{
+ return ((shader->inst[0] & NV30_FP_OP_TEX_UNIT_MASK)
+ >> NV30_FP_OP_TEX_UNIT_SHIFT);
+}
+
+static int
+NV30FPGetSourceNegate(nvsFunc * shader, int merged, int pos)
+{
+ unsigned int src;
+
+ src = shader->GetSourceHW(shader, merged, pos);
+
+ if (src == -1)
+ return -1;
+ return ((src & NV30_FP_REG_NEGATE) ? 1 : 0);
+}
+
+static int
+NV30FPGetSourceAbs(nvsFunc * shader, int merged, int pos)
+{
+ struct _op_xlat *opr;
+ static unsigned int abspos[3] = {
+ NV30_FP_OP_OUT_ABS,
+ (1 << 30), /* guess */
+ (1 << 31) /* guess */
+ };
+
+ opr = shader->GetOPTXRec(shader, merged);
+ if (!opr || opr->srcpos[pos] == -1)
+ return -1;
+
+ return ((shader->inst[1] & abspos[opr->srcpos[pos]]) ? 1 : 0);
+}
+
+nvsSwzComp NV30FP_TX_SWIZZLE[4] = {NVS_SWZ_X, NVS_SWZ_Y, NVS_SWZ_Z, NVS_SWZ_W };
+
+static void
+NV30FPTXSwizzle(int hwswz, nvsSwzComp *swz)
+{
+ swz[NVS_SWZ_W] = NV30FP_TX_SWIZZLE[(hwswz & 0xC0) >> 6];
+ swz[NVS_SWZ_Z] = NV30FP_TX_SWIZZLE[(hwswz & 0x30) >> 4];
+ swz[NVS_SWZ_Y] = NV30FP_TX_SWIZZLE[(hwswz & 0x0C) >> 2];
+ swz[NVS_SWZ_X] = NV30FP_TX_SWIZZLE[(hwswz & 0x03) >> 0];
+}
+
+static void
+NV30FPGetSourceSwizzle(nvsFunc * shader, int merged, int pos, nvsSwzComp *swz)
+{
+ unsigned int src;
+ int swzbits;
+
+ src = shader->GetSourceHW(shader, merged, pos);
+ swzbits = (src & NV30_FP_REG_SWZ_ALL_MASK) >> NV30_FP_REG_SWZ_ALL_SHIFT;
+ NV30FPTXSwizzle(swzbits, swz);
+}
+
+static int
+NV30FPGetSourceIndexed(nvsFunc * shader, int merged, int pos)
+{
+ switch (shader->GetSourceFile(shader, merged, pos)) {
+ case NVS_FILE_ATTRIB:
+ return ((shader->inst[3] & NV30_FP_OP_INDEX_INPUT) ? 1 : 0);
+ default:
+ return 0;
+ }
+}
+
+static void
+NV30FPGetSourceConstVal(nvsFunc * shader, int merged, int pos, float *val)
+{
+ val[0] = *(float *) &(shader->inst[4]);
+ val[1] = *(float *) &(shader->inst[5]);
+ val[2] = *(float *) &(shader->inst[6]);
+ val[3] = *(float *) &(shader->inst[7]);
+}
+
+static int
+NV30FPGetSourceScale(nvsFunc * shader, int merged, int pos)
+{
+/*FIXME: is this per-source, only for a specific source, or all sources??*/
+ return (1 << ((shader->inst[2] & NV30_FP_OP_SRC_SCALE_MASK)
+ >> NV30_FP_OP_SRC_SCALE_SHIFT));
+}
+
+static int
+NV30FPGetAddressRegID(nvsFunc * shader)
+{
+ return 0;
+}
+
+static nvsSwzComp
+NV30FPGetAddressRegSwizzle(nvsFunc * shader)
+{
+ return NVS_SWZ_X;
+}
+
+static int
+NV30FPSupportsConditional(nvsFunc * shader)
+{
+ /*FIXME: Is this true of all ops? */
+ return 1;
+}
+
+static int
+NV30FPGetConditionUpdate(nvsFunc * shader)
+{
+ return ((shader->inst[0] & NV30_FP_OP_COND_WRITE_ENABLE) ? 1 : 0);
+}
+
+static int
+NV30FPGetConditionTest(nvsFunc * shader)
+{
+ /*FIXME: always? */
+ return 1;
+}
+
+static nvsCond
+NV30FPGetCondition(nvsFunc * shader)
+{
+ int cond;
+
+ cond = ((shader->inst[1] & NV30_FP_OP_COND_MASK)
+ >> NV30_FP_OP_COND_SHIFT);
+
+ switch (cond) {
+ case NV30_FP_OP_COND_FL: return NVS_COND_FL;
+ case NV30_FP_OP_COND_LT: return NVS_COND_LT;
+ case NV30_FP_OP_COND_EQ: return NVS_COND_EQ;
+ case NV30_FP_OP_COND_LE: return NVS_COND_LE;
+ case NV30_FP_OP_COND_GT: return NVS_COND_GT;
+ case NV30_FP_OP_COND_NE: return NVS_COND_NE;
+ case NV30_FP_OP_COND_GE: return NVS_COND_GE;
+ case NV30_FP_OP_COND_TR: return NVS_COND_TR;
+ default:
+ return NVS_COND_UNKNOWN;
+ }
+}
+
+static void
+NV30FPGetCondRegSwizzle(nvsFunc * shader, nvsSwzComp *swz)
+{
+ int swzbits;
+
+ swzbits = (shader->inst[1] & NV30_FP_OP_COND_SWZ_ALL_MASK)
+ >> NV30_FP_OP_COND_SWZ_ALL_SHIFT;
+ NV30FPTXSwizzle(swzbits, swz);
+}
+
+static int
+NV30FPGetCondRegID(nvsFunc * shader)
+{
+ return 0;
+}
+
+static nvsPrecision
+NV30FPGetPrecision(nvsFunc * shader)
+{
+ int p;
+
+ p = (shader->inst[0] & NV30_FP_OP_PRECISION_MASK)
+ >> NV30_FP_OP_PRECISION_SHIFT;
+
+ switch (p) {
+ case NV30_FP_PRECISION_FP32: return NVS_PREC_FLOAT32;
+ case NV30_FP_PRECISION_FP16: return NVS_PREC_FLOAT16;
+ case NV30_FP_PRECISION_FX12: return NVS_PREC_FIXED12;
+ default:
+ return NVS_PREC_UNKNOWN;
+ }
+}
+
+static int
+NV30FPGetSaturate(nvsFunc * shader)
+{
+ return ((shader->inst[0] & NV30_FP_OP_OUT_SAT) ? 1 : 0);
+}
+
+/*******************************************************************************
+ * Init
+ */
+void
+NV30FPInitShaderFuncs(nvsFunc * shader)
+{
+ /* These are probably bogus, I made them up... */
+ shader->MaxInst = 1024;
+ shader->MaxAttrib = 16;
+ shader->MaxTemp = 32;
+ shader->MaxAddress = 1;
+ shader->MaxConst = 256;
+ shader->caps = SCAP_SRC_ABS;
+
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_MOV, NVS_OP_MOV, 0, -1, -1);
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_MUL, NVS_OP_MUL, 0, 1, -1);
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_ADD, NVS_OP_ADD, 0, 1, -1);
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_MAD, NVS_OP_MAD, 0, 1, 2);
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_DP3, NVS_OP_DP3, 0, 1, -1);
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_DP4, NVS_OP_DP4, 0, 1, -1);
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_DST, NVS_OP_DST, 0, 1, -1);
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_MIN, NVS_OP_MIN, 0, 1, -1);
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_MAX, NVS_OP_MAX, 0, 1, -1);
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_SLT, NVS_OP_SLT, 0, 1, -1);
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_SGE, NVS_OP_SGE, 0, 1, -1);
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_FRC, NVS_OP_FRC, 0, -1, -1);
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_FLR, NVS_OP_FLR, 0, -1, -1);
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_TEX, NVS_OP_TEX, 0, -1, -1);
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_TXD, NVS_OP_TXD, 0, 1, 2);
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_TXP, NVS_OP_TXP, 0, -1, -1);
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_TXB, NVS_OP_TXB, 0, -1, -1);
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_SEQ, NVS_OP_SEQ, 0, 1, -1);
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_SGT, NVS_OP_SGT, 0, 1, -1);
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_SLE, NVS_OP_SLE, 0, 1, -1);
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_SNE, NVS_OP_SNE, 0, 1, -1);
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_RCP, NVS_OP_RCP, 0, -1, -1);
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_LG2, NVS_OP_LG2, 0, -1, -1);
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_EX2, NVS_OP_EX2, 0, -1, -1);
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_COS, NVS_OP_COS, 0, -1, -1);
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_SIN, NVS_OP_SIN, 0, -1, -1);
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_NOP, NVS_OP_NOP, -1, -1, -1);
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_DDX, NVS_OP_DDX, 0, -1, -1);
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_DDY, NVS_OP_DDY, 0, -1, -1);
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_KIL, NVS_OP_KIL, -1, -1, -1);
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_PK4B, NVS_OP_PK4B, 0, -1, -1);
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_UP4B, NVS_OP_UP4B, 0, -1, -1);
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_PK2H, NVS_OP_PK2H, 0, -1, -1);
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_UP2H, NVS_OP_UP2H, 0, -1, -1);
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_PK4UB, NVS_OP_PK4UB, 0, -1, -1);
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_UP4UB, NVS_OP_UP4UB, 0, -1, -1);
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_PK2US, NVS_OP_PK2US, 0, -1, -1);
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_UP2US, NVS_OP_UP2US, 0, -1, -1);
+ /*FIXME: Haven't confirmed the source positions for the below opcodes */
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_LIT, NVS_OP_LIT, 0, -1, -1);
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_LRP, NVS_OP_LRP, 0, 1, 2);
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_POW, NVS_OP_POW, 0, 1, -1);
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_RSQ, NVS_OP_RSQ, 0, -1, -1);
+ MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_RFL, NVS_OP_RFL, 0, 1, -1);
+
+ shader->GetOPTXRec = NV30FPGetOPTXRec;
+ shader->GetOPTXFromSOP = NV30FPGetOPTXFromSOP;
+
+ shader->UploadToHW = NV30FPUploadToHW;
+ shader->UpdateConst = NV30FPUpdateConst;
+
+ shader->InitInstruction = NV30FPInitInstruction;
+ shader->SupportsOpcode = NV30FPSupportsOpcode;
+ shader->SetOpcode = NV30FPSetOpcode;
+ shader->SetCCUpdate = NV30FPSetCCUpdate;
+ shader->SetCondition = NV30FPSetCondition;
+ shader->SetResult = NV30FPSetResult;
+ shader->SetSource = NV30FPSetSource;
+ shader->SetTexImageUnit = NV30FPSetTexImageUnit;
+ shader->SetSaturate = NV30FPSetSaturate;
+ shader->SetLastInst = NV30FPSetLastInst;
+
+ shader->HasMergedInst = NV30FPHasMergedInst;
+ shader->IsLastInst = NV30FPIsLastInst;
+ shader->GetOffsetNext = NV30FPGetOffsetNext;
+ shader->GetOpcode = NV30FPGetOpcode;
+ shader->GetOpcodeHW = NV30FPGetOpcodeHW;
+ shader->GetDestFile = NV30FPGetDestFile;
+ shader->GetDestID = NV30FPGetDestID;
+ shader->GetDestMask = NV30FPGetDestMask;
+ shader->GetSourceHW = NV30FPGetSourceHW;
+ shader->GetSourceFile = NV30FPGetSourceFile;
+ shader->GetSourceID = NV30FPGetSourceID;
+ shader->GetTexImageUnit = NV30FPGetTexImageUnit;
+ shader->GetSourceNegate = NV30FPGetSourceNegate;
+ shader->GetSourceAbs = NV30FPGetSourceAbs;
+ shader->GetSourceSwizzle = NV30FPGetSourceSwizzle;
+ shader->GetSourceIndexed = NV30FPGetSourceIndexed;
+ shader->GetSourceConstVal = NV30FPGetSourceConstVal;
+ shader->GetSourceScale = NV30FPGetSourceScale;
+ shader->GetRelAddressRegID = NV30FPGetAddressRegID;
+ shader->GetRelAddressSwizzle = NV30FPGetAddressRegSwizzle;
+ shader->GetPrecision = NV30FPGetPrecision;
+ shader->GetSaturate = NV30FPGetSaturate;
+ shader->SupportsConditional = NV30FPSupportsConditional;
+ shader->GetConditionUpdate = NV30FPGetConditionUpdate;
+ shader->GetConditionTest = NV30FPGetConditionTest;
+ shader->GetCondition = NV30FPGetCondition;
+ shader->GetCondRegSwizzle = NV30FPGetCondRegSwizzle;
+ shader->GetCondRegID = NV30FPGetCondRegID;
+}
diff --git a/src/mesa/drivers/dri/nouveau/nv30_shader.h b/src/mesa/drivers/dri/nouveau/nv30_shader.h
new file mode 100644
index 0000000000..7a027dd427
--- /dev/null
+++ b/src/mesa/drivers/dri/nouveau/nv30_shader.h
@@ -0,0 +1,379 @@
+#ifndef __NV30_SHADER_H__
+#define __NV30_SHADER_H__
+
+/* Vertex programs instruction set
+ *
+ * 128bit opcodes, split into 4 32-bit ones for ease of use.
+ *
+ * Non-native instructions
+ * ABS - MOV + NV40_VP_INST0_DEST_ABS
+ * POW - EX2 + MUL + LG2
+ * SUB - ADD, second source negated
+ * SWZ - MOV
+ * XPD -
+ *
+ * Register access
+ * - Only one INPUT can be accessed per-instruction (move extras into TEMPs)
+ * - Only one CONST can be accessed per-instruction (move extras into TEMPs)
+ *
+ * Relative Addressing
+ * According to the value returned for MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB
+ * there are only two address registers available. The destination in the ARL
+ * instruction is set to TEMP <n> (The temp isn't actually written).
+ *
+ * When using vanilla ARB_v_p, the proprietary driver will squish both the available
+ * ADDRESS regs into the first hardware reg in the X and Y components.
+ *
+ * To use an address reg as an index into consts, the CONST_SRC is set to
+ * (const_base + offset) and INDEX_CONST is set.
+ *
+ * To access the second address reg use ADDR_REG_SELECT_1. A particular component
+ * of the address regs is selected with ADDR_SWZ.
+ *
+ * Only one address register can be accessed per instruction.
+ *
+ * Conditional execution (see NV_vertex_program{2,3} for details)
+ * Conditional execution of an instruction is enabled by setting COND_TEST_ENABLE, and
+ * selecting the condition which will allow the test to pass with COND_{FL,LT,...}.
+ * It is possible to swizzle the values in the condition register, which allows for
+ * testing against an individual component.
+ *
+ * Branching
+ * The BRA/CAL instructions seem to follow a slightly different opcode layout. The
+ * destination instruction ID (IADDR) overlaps a source field. Instruction ID's seem to
+ * be numbered based on the UPLOAD_FROM_ID FIFO command, and is incremented automatically
+ * on each UPLOAD_INST FIFO command.
+ *
+ * Conditional branching is achieved by using the condition tests described above.
+ * There doesn't appear to be dedicated looping instructions, but this can be done
+ * using a temp reg + conditional branching.
+ *
+ * Subroutines may be uploaded before the main program itself, but the first executed
+ * instruction is determined by the PROGRAM_START_ID FIFO command.
+ *
+ */
+
+/* DWORD 0 */
+#define NV30_VP_INST_ADDR_REG_SELECT_1 (1 << 24)
+#define NV30_VP_INST_SRC2_ABS (1 << 23) /* guess */
+#define NV30_VP_INST_SRC1_ABS (1 << 22) /* guess */
+#define NV30_VP_INST_SRC0_ABS (1 << 21) /* guess */
+#define NV30_VP_INST_OUT_RESULT (1 << 20)
+#define NV30_VP_INST_DEST_TEMP_ID_SHIFT 16
+#define NV30_VP_INST_DEST_TEMP_ID_MASK (0x0F << 16)
+#define NV30_VP_INST_COND_UPDATE_ENABLE (1<<15)
+#define NV30_VP_INST_COND_TEST_ENABLE (1<<14)
+#define NV30_VP_INST_COND_SHIFT 11
+#define NV30_VP_INST_COND_MASK (0x07 << 11)
+# define NV30_VP_INST_COND_FL 0 /* guess */
+# define NV30_VP_INST_COND_LT 1
+# define NV30_VP_INST_COND_EQ 2
+# define NV30_VP_INST_COND_LE 3
+# define NV30_VP_INST_COND_GT 4
+# define NV30_VP_INST_COND_NE 5
+# define NV30_VP_INST_COND_GE 6
+# define NV30_VP_INST_COND_TR 7 /* guess */
+#define NV30_VP_INST_COND_SWZ_X_SHIFT 9
+#define NV30_VP_INST_COND_SWZ_X_MASK (0x03 << 9)
+#define NV30_VP_INST_COND_SWZ_Y_SHIFT 7
+#define NV30_VP_INST_COND_SWZ_Y_MASK (0x03 << 7)
+#define NV30_VP_INST_COND_SWZ_Z_SHIFT 5
+#define NV30_VP_INST_COND_SWZ_Z_MASK (0x03 << 5)
+#define NV30_VP_INST_COND_SWZ_W_SHIFT 3
+#define NV30_VP_INST_COND_SWZ_W_MASK (0x03 << 3)
+#define NV30_VP_INST_COND_SWZ_ALL_SHIFT 3
+#define NV30_VP_INST_COND_SWZ_ALL_MASK (0xFF << 3)
+#define NV30_VP_INST_ADDR_SWZ_SHIFT 1
+#define NV30_VP_INST_ADDR_SWZ_MASK (0x03 << 1)
+#define NV30_VP_INST_SCA_OPCODEH_SHIFT 0
+#define NV30_VP_INST_SCA_OPCODEH_MASK (0x01 << 0)
+
+/* DWORD 1 */
+#define NV30_VP_INST_SCA_OPCODEL_SHIFT 28
+#define NV30_VP_INST_SCA_OPCODEL_MASK (0x0F << 28)
+# define NV30_VP_INST_OP_NOP 0x00
+# define NV30_VP_INST_OP_RCP 0x02
+# define NV30_VP_INST_OP_RCC 0x03
+# define NV30_VP_INST_OP_RSQ 0x04
+# define NV30_VP_INST_OP_EXP 0x05
+# define NV30_VP_INST_OP_LOG 0x06
+# define NV30_VP_INST_OP_LIT 0x07
+# define NV30_VP_INST_OP_BRA 0x09
+# define NV30_VP_INST_OP_CAL 0x0B
+# define NV30_VP_INST_OP_RET 0x0C
+# define NV30_VP_INST_OP_LG2 0x0D
+# define NV30_VP_INST_OP_EX2 0x0E
+# define NV30_VP_INST_OP_SIN 0x0F
+# define NV30_VP_INST_OP_COS 0x10
+#define NV30_VP_INST_VEC_OPCODE_SHIFT 23
+#define NV30_VP_INST_VEC_OPCODE_MASK (0x1F << 23)
+# define NV30_VP_INST_OP_NOPV 0x00
+# define NV30_VP_INST_OP_MOV 0x01
+# define NV30_VP_INST_OP_MUL 0x02
+# define NV30_VP_INST_OP_ADD 0x03
+# define NV30_VP_INST_OP_MAD 0x04
+# define NV30_VP_INST_OP_DP3 0x05
+# define NV30_VP_INST_OP_DP4 0x07
+# define NV30_VP_INST_OP_DPH 0x06
+# define NV30_VP_INST_OP_DST 0x08
+# define NV30_VP_INST_OP_MIN 0x09
+# define NV30_VP_INST_OP_MAX 0x0A
+# define NV30_VP_INST_OP_SLT 0x0B
+# define NV30_VP_INST_OP_SGE 0x0C
+# define NV30_VP_INST_OP_ARL 0x0D
+# define NV30_VP_INST_OP_FRC 0x0E
+# define NV30_VP_INST_OP_FLR 0x0F
+# define NV30_VP_INST_OP_SEQ 0x10
+# define NV30_VP_INST_OP_SFL 0x11
+# define NV30_VP_INST_OP_SGT 0x12
+# define NV30_VP_INST_OP_SLE 0x13
+# define NV30_VP_INST_OP_SNE 0x14
+# define NV30_VP_INST_OP_STR 0x15
+# define NV30_VP_INST_OP_SSG 0x16
+# define NV30_VP_INST_OP_ARR 0x17
+# define NV30_VP_INST_OP_ARA 0x18
+#define NV30_VP_INST_CONST_SRC_SHIFT 14
+#define NV30_VP_INST_CONST_SRC_MASK (0xFF << 14)
+#define NV30_VP_INST_INPUT_SRC_SHIFT 9 /*NV20*/
+#define NV30_VP_INST_INPUT_SRC_MASK (0x0F << 9) /*NV20*/
+# define NV30_VP_INST_IN_POS 0 /* These seem to match the bindings specified in */
+# define NV30_VP_INST_IN_WEIGHT 1 /* the ARB_v_p spec (2.14.3.1) */
+# define NV30_VP_INST_IN_NORMAL 2
+# define NV30_VP_INST_IN_COL0 3 /* Should probably confirm them all though */
+# define NV30_VP_INST_IN_COL1 4
+# define NV30_VP_INST_IN_FOGC 5
+# define NV30_VP_INST_IN_TC0 8
+# define NV30_VP_INST_IN_TC(n) (8+n)
+#define NV30_VP_INST_SRC0H_SHIFT 0 /*NV20*/
+#define NV30_VP_INST_SRC0H_MASK (0x1FF << 0) /*NV20*/
+
+/* DWORD 2 */
+#define NV30_VP_INST_SRC0L_SHIFT 26 /*NV20*/
+#define NV30_VP_INST_SRC0L_MASK (0x3F <<26) /*NV20*/
+#define NV30_VP_INST_SRC1_SHIFT 11 /*NV20*/
+#define NV30_VP_INST_SRC1_MASK (0x7FFF<<11) /*NV20*/
+#define NV30_VP_INST_SRC2H_SHIFT 0 /*NV20*/
+#define NV30_VP_INST_SRC2H_MASK (0x7FF << 0) /*NV20*/
+#define NV30_VP_INST_IADDR_SHIFT 2
+#define NV30_VP_INST_IADDR_MASK (0xFF << 2) /* guess */
+
+/* DWORD 3 */
+#define NV30_VP_INST_SRC2L_SHIFT 28 /*NV20*/
+#define NV30_VP_INST_SRC2L_MASK (0x0F <<28) /*NV20*/
+#define NV30_VP_INST_STEMP_WRITEMASK_SHIFT 24
+#define NV30_VP_INST_STEMP_WRITEMASK_MASK (0x0F << 24)
+#define NV30_VP_INST_VTEMP_WRITEMASK_SHIFT 20
+#define NV30_VP_INST_VTEMP_WRITEMASK_MASK (0x0F << 20)
+#define NV30_VP_INST_SDEST_WRITEMASK_SHIFT 16
+#define NV30_VP_INST_SDEST_WRITEMASK_MASK (0x0F << 16)
+#define NV30_VP_INST_VDEST_WRITEMASK_SHIFT 12 /*NV20*/
+#define NV30_VP_INST_VDEST_WRITEMASK_MASK (0x0F << 12) /*NV20*/
+#define NV30_VP_INST_DEST_ID_SHIFT 2
+#define NV30_VP_INST_DEST_ID_MASK (0x0F << 2)
+# define NV30_VP_INST_DEST_POS 0
+# define NV30_VP_INST_DEST_COL0 3
+# define NV30_VP_INST_DEST_COL1 4
+# define NV30_VP_INST_DEST_TC(n) (8+n)
+
+/* Source-register definition - matches NV20 exactly */
+#define NV30_VP_SRC_REG_NEGATE (1<<14)
+#define NV30_VP_SRC_REG_SWZ_X_SHIFT 12
+#define NV30_VP_SRC_REG_SWZ_X_MASK (0x03 <<12)
+#define NV30_VP_SRC_REG_SWZ_Y_SHIFT 10
+#define NV30_VP_SRC_REG_SWZ_Y_MASK (0x03 <<10)
+#define NV30_VP_SRC_REG_SWZ_Z_SHIFT 8
+#define NV30_VP_SRC_REG_SWZ_Z_MASK (0x03 << 8)
+#define NV30_VP_SRC_REG_SWZ_W_SHIFT 6
+#define NV30_VP_SRC_REG_SWZ_W_MASK (0x03 << 6)
+#define NV30_VP_SRC_REG_SWZ_ALL_SHIFT 6
+#define NV30_VP_SRC_REG_SWZ_ALL_MASK (0xFF << 6)
+#define NV30_VP_SRC_REG_TEMP_ID_SHIFT 2
+#define NV30_VP_SRC_REG_TEMP_ID_MASK (0x0F << 0)
+#define NV30_VP_SRC_REG_TYPE_SHIFT 0
+#define NV30_VP_SRC_REG_TYPE_MASK (0x03 << 0)
+#define NV30_VP_SRC_REG_TYPE_TEMP 1
+#define NV30_VP_SRC_REG_TYPE_INPUT 2
+#define NV30_VP_SRC_REG_TYPE_CONST 3 /* guess */
+
+/*
+ * Each fragment program opcode appears to be comprised of 4 32-bit values.
+ *
+ * 0 - Opcode, output reg/mask, ATTRIB source
+ * 1 - Source 0
+ * 2 - Source 1
+ * 3 - Source 2
+ *
+ * There appears to be no special difference between result regs and temp regs.
+ * result.color == R0.xyzw
+ * result.depth == R1.z
+ * When the fragprog contains instructions to write depth, NV30_TCL_PRIMITIVE_3D_UNK1D78=0
+ * otherwise it is set to 1.
+ *
+ * Constants are inserted directly after the instruction that uses them.
+ *
+ * It appears that it's not possible to use two input registers in one
+ * instruction as the input sourcing is done in the instruction dword
+ * and not the source selection dwords. As such instructions such as:
+ *
+ * ADD result.color, fragment.color, fragment.texcoord[0];
+ *
+ * must be split into two MOV's and then an ADD (nvidia does this) but
+ * I'm not sure why it's not just one MOV and then source the second input
+ * in the ADD instruction..
+ *
+ * Negation of the full source is done with NV30_FP_REG_NEGATE, arbitrary
+ * negation requires multiplication with a const.
+ *
+ * Arbitrary swizzling is supported with the exception of SWIZZLE_ZERO/SWIZZLE_ONE
+ * The temp/result regs appear to be initialised to (0.0, 0.0, 0.0, 0.0) as SWIZZLE_ZERO
+ * is implemented simply by not writing to the relevant components of the destination.
+ *
+ * Conditional execution
+ * TODO
+ *
+ * Non-native instructions:
+ * LIT
+ * LRP - MAD+MAD
+ * SUB - ADD, negate second source
+ * RSQ - LG2 + EX2
+ * POW - LG2 + MUL + EX2
+ * SCS - COS + SIN
+ * XPD
+ */
+
+//== Opcode / Destination selection ==
+#define NV30_FP_OP_PROGRAM_END (1 << 0)
+#define NV30_FP_OP_OUT_REG_SHIFT 1
+#define NV30_FP_OP_OUT_REG_MASK (31 << 1) /* uncertain */
+/* Needs to be set when writing outputs to get expected result.. */
+#define NV30_FP_OP_UNK0_7 (1 << 7)
+#define NV30_FP_OP_COND_WRITE_ENABLE (1 << 8)
+#define NV30_FP_OP_OUTMASK_SHIFT 9
+#define NV30_FP_OP_OUTMASK_MASK (0xF << 9)
+# define NV30_FP_OP_OUT_X (1<<9)
+# define NV30_FP_OP_OUT_Y (1<<10)
+# define NV30_FP_OP_OUT_Z (1<<11)
+# define NV30_FP_OP_OUT_W (1<<12)
+/* Uncertain about these, especially the input_src values.. it's possible that
+ * they can be dynamically changed.
+ */
+#define NV30_FP_OP_INPUT_SRC_SHIFT 13
+#define NV30_FP_OP_INPUT_SRC_MASK (15 << 13)
+# define NV30_FP_OP_INPUT_SRC_POSITION 0x0
+# define NV30_FP_OP_INPUT_SRC_COL0 0x1
+# define NV30_FP_OP_INPUT_SRC_COL1 0x2
+# define NV30_FP_OP_INPUT_SRC_FOGC 0x3
+# define NV30_FP_OP_INPUT_SRC_TC0 0x4
+# define NV30_FP_OP_INPUT_SRC_TC(n) (0x4 + n)
+#define NV30_FP_OP_TEX_UNIT_SHIFT 17
+#define NV30_FP_OP_TEX_UNIT_MASK (0xF << 17) /* guess */
+#define NV30_FP_OP_PRECISION_SHIFT 22
+#define NV30_FP_OP_PRECISION_MASK (3 << 22)
+# define NV30_FP_PRECISION_FP32 0
+# define NV30_FP_PRECISION_FP16 1
+# define NV30_FP_PRECISION_FX12 2
+#define NV30_FP_OP_OPCODE_SHIFT 24
+#define NV30_FP_OP_OPCODE_MASK (0x3F << 24)
+# define NV30_FP_OP_OPCODE_NOP 0x00
+# define NV30_FP_OP_OPCODE_MOV 0x01
+# define NV30_FP_OP_OPCODE_MUL 0x02
+# define NV30_FP_OP_OPCODE_ADD 0x03
+# define NV30_FP_OP_OPCODE_MAD 0x04
+# define NV30_FP_OP_OPCODE_DP3 0x05
+# define NV30_FP_OP_OPCODE_DP4 0x06
+# define NV30_FP_OP_OPCODE_DST 0x07
+# define NV30_FP_OP_OPCODE_MIN 0x08
+# define NV30_FP_OP_OPCODE_MAX 0x09
+# define NV30_FP_OP_OPCODE_SLT 0x0A
+# define NV30_FP_OP_OPCODE_SGE 0x0B
+# define NV30_FP_OP_OPCODE_SLE 0x0C
+# define NV30_FP_OP_OPCODE_SGT 0x0D
+# define NV30_FP_OP_OPCODE_SNE 0x0E
+# define NV30_FP_OP_OPCODE_SEQ 0x0F
+# define NV30_FP_OP_OPCODE_FRC 0x10
+# define NV30_FP_OP_OPCODE_FLR 0x11
+# define NV30_FP_OP_OPCODE_KIL 0x12
+# define NV30_FP_OP_OPCODE_PK4B 0x13
+# define NV30_FP_OP_OPCODE_UP4B 0x14
+# define NV30_FP_OP_OPCODE_DDX 0x15 /* can only write XY */
+# define NV30_FP_OP_OPCODE_DDY 0x16 /* can only write XY */
+# define NV30_FP_OP_OPCODE_TEX 0x17
+# define NV30_FP_OP_OPCODE_TXP 0x18
+# define NV30_FP_OP_OPCODE_TXD 0x19
+# define NV30_FP_OP_OPCODE_RCP 0x1A
+# define NV30_FP_OP_OPCODE_RSQ 0x1B
+# define NV30_FP_OP_OPCODE_EX2 0x1C
+# define NV30_FP_OP_OPCODE_LG2 0x1D
+# define NV30_FP_OP_OPCODE_LIT 0x1E
+# define NV30_FP_OP_OPCODE_LRP 0x1F
+# define NV30_FP_OP_OPCODE_COS 0x22
+# define NV30_FP_OP_OPCODE_SIN 0x23
+# define NV30_FP_OP_OPCODE_PK2H 0x24
+# define NV30_FP_OP_OPCODE_UP2H 0x25
+# define NV30_FP_OP_OPCODE_POW 0x26
+# define NV30_FP_OP_OPCODE_PK4UB 0x27
+# define NV30_FP_OP_OPCODE_UP4UB 0x28
+# define NV30_FP_OP_OPCODE_PK2US 0x29
+# define NV30_FP_OP_OPCODE_UP2US 0x2A
+# define NV30_FP_OP_OPCODE_DP2A 0x2E
+# define NV30_FP_OP_OPCODE_TXB 0x31
+# define NV30_FP_OP_OPCODE_RFL 0x36
+#define NV30_FP_OP_OUT_SAT (1 << 31)
+
+/* high order bits of SRC0 */
+#define NV30_FP_OP_OUT_ABS (1 << 29)
+#define NV30_FP_OP_COND_SWZ_W_SHIFT 27
+#define NV30_FP_OP_COND_SWZ_W_MASK (3 << 27)
+#define NV30_FP_OP_COND_SWZ_Z_SHIFT 25
+#define NV30_FP_OP_COND_SWZ_Z_MASK (3 << 25)
+#define NV30_FP_OP_COND_SWZ_Y_SHIFT 23
+#define NV30_FP_OP_COND_SWZ_Y_MASK (3 << 23)
+#define NV30_FP_OP_COND_SWZ_X_SHIFT 21
+#define NV30_FP_OP_COND_SWZ_X_MASK (3 << 21)
+#define NV30_FP_OP_COND_SWZ_ALL_SHIFT 21
+#define NV30_FP_OP_COND_SWZ_ALL_MASK (0xFF << 21)
+#define NV30_FP_OP_COND_SHIFT 18
+#define NV30_FP_OP_COND_MASK (0x07 << 18)
+# define NV30_FP_OP_COND_FL 0
+# define NV30_FP_OP_COND_LT 1
+# define NV30_FP_OP_COND_EQ 2
+# define NV30_FP_OP_COND_LE 3
+# define NV30_FP_OP_COND_GT 4
+# define NV30_FP_OP_COND_NE 5
+# define NV30_FP_OP_COND_GE 6
+# define NV30_FP_OP_COND_TR 7
+
+/* high order bits of SRC1 */
+#define NV30_FP_OP_SRC_SCALE_SHIFT 28
+#define NV30_FP_OP_SRC_SCALE_MASK (3 << 28)
+
+/* high order bits of SRC2 */
+#define NV30_FP_OP_INDEX_INPUT (1 << 30)
+
+//== Register selection ==
+#define NV30_FP_REG_ALL_MASK (0x1FFFF<<0)
+#define NV30_FP_REG_TYPE_SHIFT 0
+#define NV30_FP_REG_TYPE_MASK (3 << 0)
+# define NV30_FP_REG_TYPE_TEMP 0
+# define NV30_FP_REG_TYPE_INPUT 1
+# define NV30_FP_REG_TYPE_CONST 2
+#define NV30_FP_REG_SRC_SHIFT 2 /* uncertain */
+#define NV30_FP_REG_SRC_MASK (31 << 2)
+#define NV30_FP_REG_UNK_0 (1 << 8)
+#define NV30_FP_REG_SWZ_ALL_SHIFT 9
+#define NV30_FP_REG_SWZ_ALL_MASK (255 << 9)
+#define NV30_FP_REG_SWZ_X_SHIFT 9
+#define NV30_FP_REG_SWZ_X_MASK (3 << 9)
+#define NV30_FP_REG_SWZ_Y_SHIFT 11
+#define NV30_FP_REG_SWZ_Y_MASK (3 << 11)
+#define NV30_FP_REG_SWZ_Z_SHIFT 13
+#define NV30_FP_REG_SWZ_Z_MASK (3 << 13)
+#define NV30_FP_REG_SWZ_W_SHIFT 15
+#define NV30_FP_REG_SWZ_W_MASK (3 << 15)
+# define NV30_FP_SWIZZLE_X 0
+# define NV30_FP_SWIZZLE_Y 1
+# define NV30_FP_SWIZZLE_Z 2
+# define NV30_FP_SWIZZLE_W 3
+#define NV30_FP_REG_NEGATE (1 << 17)
+
+#endif
diff --git a/src/mesa/drivers/dri/nouveau/nv30_state.c b/src/mesa/drivers/dri/nouveau/nv30_state.c
new file mode 100644
index 0000000000..4d79bb6127
--- /dev/null
+++ b/src/mesa/drivers/dri/nouveau/nv30_state.c
@@ -0,0 +1,901 @@
+/**************************************************************************
+
+Copyright 2006 Nouveau
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+#include "nouveau_context.h"
+#include "nouveau_object.h"
+#include "nouveau_fifo.h"
+#include "nouveau_reg.h"
+#include "nouveau_state.h"
+
+#include "tnl/t_pipeline.h"
+
+#include "mtypes.h"
+#include "colormac.h"
+
+#define NOUVEAU_CARD_USING_SHADERS (nmesa->screen->card->type >= NV_40)
+
+static void nv30AlphaFunc(GLcontext *ctx, GLenum func, GLfloat ref)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ GLubyte ubRef;
+ CLAMPED_FLOAT_TO_UBYTE(ubRef, ref);
+
+ BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_ALPHA_FUNC_FUNC, 2);
+ OUT_RING_CACHE(func); /* NV30_TCL_PRIMITIVE_3D_ALPHA_FUNC_FUNC */
+ OUT_RING_CACHE(ubRef); /* NV30_TCL_PRIMITIVE_3D_ALPHA_FUNC_REF */
+}
+
+static void nv30BlendColor(GLcontext *ctx, const GLfloat color[4])
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ GLubyte cf[4];
+
+ CLAMPED_FLOAT_TO_UBYTE(cf[0], color[0]);
+ CLAMPED_FLOAT_TO_UBYTE(cf[1], color[1]);
+ CLAMPED_FLOAT_TO_UBYTE(cf[2], color[2]);
+ CLAMPED_FLOAT_TO_UBYTE(cf[3], color[3]);
+
+ BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_BLEND_COLOR, 1);
+ OUT_RING_CACHE(PACK_COLOR_8888(cf[3], cf[1], cf[2], cf[0]));
+}
+
+static void nv30BlendEquationSeparate(GLcontext *ctx, GLenum modeRGB, GLenum modeA)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_BLEND_EQUATION, 1);
+ OUT_RING_CACHE((modeA<<16) | modeRGB);
+}
+
+
+static void nv30BlendFuncSeparate(GLcontext *ctx, GLenum sfactorRGB, GLenum dfactorRGB,
+ GLenum sfactorA, GLenum dfactorA)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_BLEND_FUNC_SRC, 2);
+ OUT_RING_CACHE((sfactorA<<16) | sfactorRGB);
+ OUT_RING_CACHE((dfactorA<<16) | dfactorRGB);
+}
+
+static void nv30Clear(GLcontext *ctx, GLbitfield mask)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ GLuint hw_bufs = 0;
+
+ if (mask & (BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT))
+ hw_bufs |= 0xf0;
+ if (mask & (BUFFER_BIT_DEPTH))
+ hw_bufs |= 0x03;
+
+ if (hw_bufs) {
+ BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_CLEAR_WHICH_BUFFERS, 1);
+ OUT_RING(hw_bufs);
+ }
+}
+
+static void nv30ClearColor(GLcontext *ctx, const GLfloat color[4])
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ GLubyte c[4];
+ UNCLAMPED_FLOAT_TO_RGBA_CHAN(c,color);
+ BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_CLEAR_VALUE_ARGB, 1);
+ OUT_RING_CACHE(PACK_COLOR_8888(c[3],c[0],c[1],c[2]));
+}
+
+static void nv30ClearDepth(GLcontext *ctx, GLclampd d)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ nmesa->clear_value=((nmesa->clear_value&0x000000FF)|(((uint32_t)(d*0xFFFFFF))<<8));
+ BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_CLEAR_VALUE_DEPTH, 1);
+ OUT_RING_CACHE(nmesa->clear_value);
+}
+
+/* we're don't support indexed buffers
+ void (*ClearIndex)(GLcontext *ctx, GLuint index)
+ */
+
+static void nv30ClearStencil(GLcontext *ctx, GLint s)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ nmesa->clear_value=((nmesa->clear_value&0xFFFFFF00)|(s&0x000000FF));
+ BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_CLEAR_VALUE_DEPTH, 1);
+ OUT_RING_CACHE(nmesa->clear_value);
+}
+
+static void nv30ClipPlane(GLcontext *ctx, GLenum plane, const GLfloat *equation)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_CLIP_PLANE_A(plane), 4);
+ OUT_RING_CACHEf(equation[0]);
+ OUT_RING_CACHEf(equation[1]);
+ OUT_RING_CACHEf(equation[2]);
+ OUT_RING_CACHEf(equation[3]);
+}
+
+static void nv30ColorMask(GLcontext *ctx, GLboolean rmask, GLboolean gmask,
+ GLboolean bmask, GLboolean amask )
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_COLOR_MASK, 1);
+ OUT_RING_CACHE(((amask && 0x01) << 24) | ((rmask && 0x01) << 16) | ((gmask && 0x01)<< 8) | ((bmask && 0x01) << 0));
+}
+
+static void nv30ColorMaterial(GLcontext *ctx, GLenum face, GLenum mode)
+{
+ // TODO I need love
+}
+
+static void nv30CullFace(GLcontext *ctx, GLenum mode)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_CULL_FACE, 1);
+ OUT_RING_CACHE(mode);
+}
+
+static void nv30FrontFace(GLcontext *ctx, GLenum mode)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_FRONT_FACE, 1);
+ OUT_RING_CACHE(mode);
+}
+
+static void nv30DepthFunc(GLcontext *ctx, GLenum func)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_DEPTH_FUNC, 1);
+ OUT_RING_CACHE(func);
+}
+
+static void nv30DepthMask(GLcontext *ctx, GLboolean flag)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_DEPTH_WRITE_ENABLE, 1);
+ OUT_RING_CACHE(flag);
+}
+
+static void nv30DepthRange(GLcontext *ctx, GLclampd nearval, GLclampd farval)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_DEPTH_RANGE_NEAR, 2);
+ OUT_RING_CACHEf(nearval);
+ OUT_RING_CACHEf(farval);
+}
+
+/** Specify the current buffer for writing */
+//void (*DrawBuffer)( GLcontext *ctx, GLenum buffer );
+/** Specify the buffers for writing for fragment programs*/
+//void (*DrawBuffers)( GLcontext *ctx, GLsizei n, const GLenum *buffers );
+
+static void nv30Enable(GLcontext *ctx, GLenum cap, GLboolean state)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ switch(cap)
+ {
+ case GL_ALPHA_TEST:
+ BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_ALPHA_FUNC_ENABLE, 1);
+ OUT_RING_CACHE(state);
+ break;
+// case GL_AUTO_NORMAL:
+ case GL_BLEND:
+ BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_BLEND_FUNC_ENABLE, 1);
+ OUT_RING_CACHE(state);
+ break;
+ case GL_CLIP_PLANE0:
+ case GL_CLIP_PLANE1:
+ case GL_CLIP_PLANE2:
+ case GL_CLIP_PLANE3:
+ case GL_CLIP_PLANE4:
+ case GL_CLIP_PLANE5:
+ BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_CLIP_PLANE_ENABLE(cap-GL_CLIP_PLANE0), 1);
+ OUT_RING_CACHE(state);
+ break;
+ case GL_COLOR_LOGIC_OP:
+ BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_COLOR_LOGIC_OP_ENABLE, 1);
+ OUT_RING_CACHE(state);
+ break;
+// case GL_COLOR_MATERIAL:
+// case GL_COLOR_SUM_EXT:
+// case GL_COLOR_TABLE:
+// case GL_CONVOLUTION_1D:
+// case GL_CONVOLUTION_2D:
+ case GL_CULL_FACE:
+ BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_CULL_FACE_ENABLE, 1);
+ OUT_RING_CACHE(state);
+ break;
+ case GL_DEPTH_TEST:
+ BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_DEPTH_TEST_ENABLE, 1);
+ OUT_RING_CACHE(state);
+ break;
+ case GL_DITHER:
+ BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_DITHER_ENABLE, 1);
+ OUT_RING_CACHE(state);
+ break;
+ case GL_FOG:
+ BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_FOG_ENABLE, 1);
+ OUT_RING_CACHE(state);
+ break;
+// case GL_HISTOGRAM:
+// case GL_INDEX_LOGIC_OP:
+ case GL_LIGHT0:
+ case GL_LIGHT1:
+ case GL_LIGHT2:
+ case GL_LIGHT3:
+ case GL_LIGHT4:
+ case GL_LIGHT5:
+ case GL_LIGHT6:
+ case GL_LIGHT7:
+ {
+ uint32_t mask=0x11<<(2*(cap-GL_LIGHT0));
+
+ if (NOUVEAU_CARD_USING_SHADERS)
+ break;
+
+ nmesa->enabled_lights=((nmesa->enabled_lights&mask)|(mask*state));
+ if (nmesa->lighting_enabled)
+ {
+ BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_ENABLED_LIGHTS, 1);
+ OUT_RING_CACHE(nmesa->enabled_lights);
+ }
+ break;
+ }
+ case GL_LIGHTING:
+ if (NOUVEAU_CARD_USING_SHADERS)
+ break;
+
+ nmesa->lighting_enabled=state;
+ BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_ENABLED_LIGHTS, 1);
+ if (nmesa->lighting_enabled)
+ OUT_RING_CACHE(nmesa->enabled_lights);
+ else
+ OUT_RING_CACHE(0x0);
+ break;
+// case GL_LINE_SMOOTH:
+// case GL_LINE_STIPPLE:
+// case GL_MAP1_COLOR_4:
+// case GL_MAP1_INDEX:
+// case GL_MAP1_NORMAL:
+// case GL_MAP1_TEXTURE_COORD_1:
+// case GL_MAP1_TEXTURE_COORD_2:
+// case GL_MAP1_TEXTURE_COORD_3:
+// case GL_MAP1_TEXTURE_COORD_4:
+// case GL_MAP1_VERTEX_3:
+// case GL_MAP1_VERTEX_4:
+// case GL_MAP2_COLOR_4:
+// case GL_MAP2_INDEX:
+// case GL_MAP2_NORMAL:
+// case GL_MAP2_TEXTURE_COORD_1:
+// case GL_MAP2_TEXTURE_COORD_2:
+// case GL_MAP2_TEXTURE_COORD_3:
+// case GL_MAP2_TEXTURE_COORD_4:
+// case GL_MAP2_VERTEX_3:
+// case GL_MAP2_VERTEX_4:
+// case GL_MINMAX:
+ case GL_NORMALIZE:
+ if (nmesa->screen->card->type != NV_44) {
+ BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_NORMALIZE_ENABLE, 1);
+ OUT_RING_CACHE(state);
+ }
+ break;
+// case GL_POINT_SMOOTH:
+ case GL_POLYGON_OFFSET_POINT:
+ BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_POLYGON_OFFSET_POINT_ENABLE, 1);
+ OUT_RING_CACHE(state);
+ break;
+ case GL_POLYGON_OFFSET_LINE:
+ BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_POLYGON_OFFSET_LINE_ENABLE, 1);
+ OUT_RING_CACHE(state);
+ break;
+ case GL_POLYGON_OFFSET_FILL:
+ BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_POLYGON_OFFSET_FILL_ENABLE, 1);
+ OUT_RING_CACHE(state);
+ break;
+ case GL_POLYGON_SMOOTH:
+ BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_POLYGON_SMOOTH_ENABLE, 1);
+ OUT_RING_CACHE(state);
+ break;
+ case GL_POLYGON_STIPPLE:
+ BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_POLYGON_STIPPLE_ENABLE, 1);
+ OUT_RING_CACHE(state);
+ break;
+// case GL_POST_COLOR_MATRIX_COLOR_TABLE:
+// case GL_POST_CONVOLUTION_COLOR_TABLE:
+// case GL_RESCALE_NORMAL:
+ case GL_SCISSOR_TEST:
+ /* No enable bit, nv30Scissor will adjust to max range */
+ ctx->Driver.Scissor(ctx, ctx->Scissor.X, ctx->Scissor.Y,
+ ctx->Scissor.Width, ctx->Scissor.Height);
+ break;
+// case GL_SEPARABLE_2D:
+ case GL_STENCIL_TEST:
+ // TODO BACK and FRONT ?
+ BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_STENCIL_FRONT_ENABLE, 1);
+ OUT_RING_CACHE(state);
+ BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_STENCIL_BACK_ENABLE, 1);
+ OUT_RING_CACHE(state);
+ break;
+// case GL_TEXTURE_GEN_Q:
+// case GL_TEXTURE_GEN_R:
+// case GL_TEXTURE_GEN_S:
+// case GL_TEXTURE_GEN_T:
+// case GL_TEXTURE_1D:
+// case GL_TEXTURE_2D:
+// case GL_TEXTURE_3D:
+ }
+}
+
+static void nv30Fogfv(GLcontext *ctx, GLenum pname, const GLfloat *params)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+
+ if (NOUVEAU_CARD_USING_SHADERS)
+ return;
+
+ switch(pname)
+ {
+ case GL_FOG_MODE:
+ {
+ int mode = 0;
+ /* The modes are different in GL and the card. */
+ switch(ctx->Fog.Mode)
+ {
+ case GL_LINEAR:
+ mode = 0x804;
+ break;
+ case GL_EXP:
+ mode = 0x802;
+ break;
+ case GL_EXP2:
+ mode = 0x803;
+ break;
+ }
+ BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_FOG_MODE, 1);
+ OUT_RING_CACHE (mode);
+ break;
+ }
+ case GL_FOG_COLOR:
+ {
+ GLubyte c[4];
+ UNCLAMPED_FLOAT_TO_RGBA_CHAN(c,params);
+ BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_FOG_COLOR, 1);
+ /* nvidia ignores the alpha channel */
+ OUT_RING_CACHE(PACK_COLOR_8888_REV(c[0],c[1],c[2],c[3]));
+ break;
+ }
+ case GL_FOG_DENSITY:
+ case GL_FOG_START:
+ case GL_FOG_END:
+ {
+ GLfloat f=0., c=0.;
+ switch(ctx->Fog.Mode)
+ {
+ case GL_LINEAR:
+ f = -1.0/(ctx->Fog.End - ctx->Fog.Start);
+ c = ctx->Fog.Start/(ctx->Fog.End - ctx->Fog.Start) + 2.001953;
+ break;
+ case GL_EXP:
+ f = -0.090168*ctx->Fog.Density;
+ c = 1.5;
+ case GL_EXP2:
+ f = -0.212330*ctx->Fog.Density;
+ c = 1.5;
+ }
+ BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_FOG_EQUATION_LINEAR, 1);
+ OUT_RING_CACHE(f);
+ BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_FOG_EQUATION_CONSTANT, 1);
+ OUT_RING_CACHE(c);
+ BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_FOG_EQUATION_QUADRATIC, 1);
+ OUT_RING_CACHE(0); /* Is this always the same? */
+ break;
+ }
+// case GL_FOG_COORD_SRC:
+ default:
+ break;
+ }
+}
+
+static void nv30Hint(GLcontext *ctx, GLenum target, GLenum mode)
+{
+ // TODO I need love (fog and line_smooth hints)
+}
+
+// void (*IndexMask)(GLcontext *ctx, GLuint mask);
+
+enum {
+ SPOTLIGHT_NO_UPDATE,
+ SPOTLIGHT_UPDATE_EXPONENT,
+ SPOTLIGHT_UPDATE_DIRECTION,
+ SPOTLIGHT_UPDATE_ALL
+};
+
+static void nv30Lightfv(GLcontext *ctx, GLenum light, GLenum pname, const GLfloat *params )
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ GLint p = light - GL_LIGHT0;
+ struct gl_light *l = &ctx->Light.Light[p];
+ int spotlight_update = SPOTLIGHT_NO_UPDATE;
+
+ if (NOUVEAU_CARD_USING_SHADERS)
+ return;
+
+ /* not sure where the fourth param value goes...*/
+ switch(pname)
+ {
+ case GL_AMBIENT:
+ BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_AMBIENT_R(p), 3);
+ OUT_RING_CACHEf(params[0]);
+ OUT_RING_CACHEf(params[1]);
+ OUT_RING_CACHEf(params[2]);
+ break;
+ case GL_DIFFUSE:
+ BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_DIFFUSE_R(p), 3);
+ OUT_RING_CACHEf(params[0]);
+ OUT_RING_CACHEf(params[1]);
+ OUT_RING_CACHEf(params[2]);
+ break;
+ case GL_SPECULAR:
+ BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_SPECULAR_R(p), 3);
+ OUT_RING_CACHEf(params[0]);
+ OUT_RING_CACHEf(params[1]);
+ OUT_RING_CACHEf(params[2]);
+ break;
+ case GL_POSITION:
+ BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_LIGHT_POSITION_X(p), 3);
+ OUT_RING_CACHEf(params[0]);
+ OUT_RING_CACHEf(params[1]);
+ OUT_RING_CACHEf(params[2]);
+ break;
+ case GL_SPOT_DIRECTION:
+ spotlight_update = SPOTLIGHT_UPDATE_DIRECTION;
+ break;
+ case GL_SPOT_EXPONENT:
+ spotlight_update = SPOTLIGHT_UPDATE_EXPONENT;
+ break;
+ case GL_SPOT_CUTOFF:
+ spotlight_update = SPOTLIGHT_UPDATE_ALL;
+ break;
+ case GL_CONSTANT_ATTENUATION:
+ BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_LIGHT_CONSTANT_ATTENUATION(p), 1);
+ OUT_RING_CACHEf(*params);
+ break;
+ case GL_LINEAR_ATTENUATION:
+ BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_LIGHT_LINEAR_ATTENUATION(p), 1);
+ OUT_RING_CACHEf(*params);
+ break;
+ case GL_QUADRATIC_ATTENUATION:
+ BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_LIGHT_QUADRATIC_ATTENUATION(p), 1);
+ OUT_RING_CACHEf(*params);
+ break;
+ default:
+ break;
+ }
+
+ switch(spotlight_update) {
+ case SPOTLIGHT_UPDATE_DIRECTION:
+ {
+ GLfloat x,y,z;
+ GLfloat spot_light_coef_a = 1.0 / (l->_CosCutoff - 1.0);
+ x = spot_light_coef_a * l->_NormDirection[0];
+ y = spot_light_coef_a * l->_NormDirection[1];
+ z = spot_light_coef_a * l->_NormDirection[2];
+ BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_LIGHT_SPOT_DIR_X(p), 3);
+ OUT_RING_CACHEf(x);
+ OUT_RING_CACHEf(y);
+ OUT_RING_CACHEf(z);
+ }
+ break;
+ case SPOTLIGHT_UPDATE_EXPONENT:
+ {
+ GLfloat cc,lc,qc;
+ cc = 1.0; /* FIXME: These need to be correctly computed */
+ lc = 0.0;
+ qc = 2.0;
+ BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_LIGHT_SPOT_CUTOFF_A(p), 3);
+ OUT_RING_CACHEf(cc);
+ OUT_RING_CACHEf(lc);
+ OUT_RING_CACHEf(qc);
+ }
+ break;
+ case SPOTLIGHT_UPDATE_ALL:
+ {
+ GLfloat cc,lc,qc, x,y,z, c;
+ GLfloat spot_light_coef_a = 1.0 / (l->_CosCutoff - 1.0);
+ cc = 1.0; /* FIXME: These need to be correctly computed */
+ lc = 0.0;
+ qc = 2.0;
+ x = spot_light_coef_a * l->_NormDirection[0];
+ y = spot_light_coef_a * l->_NormDirection[1];
+ z = spot_light_coef_a * l->_NormDirection[2];
+ c = spot_light_coef_a + 1.0;
+ BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_LIGHT_SPOT_CUTOFF_A(p), 7);
+ OUT_RING_CACHEf(cc);
+ OUT_RING_CACHEf(lc);
+ OUT_RING_CACHEf(qc);
+ OUT_RING_CACHEf(x);
+ OUT_RING_CACHEf(y);
+ OUT_RING_CACHEf(z);
+ OUT_RING_CACHEf(c);
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+/** Set the lighting model parameters */
+void (*LightModelfv)(GLcontext *ctx, GLenum pname, const GLfloat *params);
+
+
+static void nv30LineStipple(GLcontext *ctx, GLint factor, GLushort pattern )
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_LINE_STIPPLE_PATTERN, 1);
+ OUT_RING_CACHE((pattern << 16) | factor);
+}
+
+static void nv30LineWidth(GLcontext *ctx, GLfloat width)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ GLubyte ubWidth;
+
+ CLAMPED_FLOAT_TO_UBYTE(ubWidth, width);
+
+ BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_LINE_WIDTH_SMOOTH, 1);
+ OUT_RING_CACHE(ubWidth);
+}
+
+static void nv30LogicOpcode(GLcontext *ctx, GLenum opcode)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_COLOR_LOGIC_OP_OP, 1);
+ OUT_RING_CACHE(opcode);
+}
+
+static void nv30PointParameterfv(GLcontext *ctx, GLenum pname, const GLfloat *params)
+{
+ /*TODO: not sure what goes here. */
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+
+}
+
+/** Specify the diameter of rasterized points */
+static void nv30PointSize(GLcontext *ctx, GLfloat size)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_POINT_SIZE, 1);
+ OUT_RING_CACHEf(size);
+}
+
+/** Select a polygon rasterization mode */
+static void nv30PolygonMode(GLcontext *ctx, GLenum face, GLenum mode)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+
+ if (face == GL_FRONT || face == GL_FRONT_AND_BACK) {
+ BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_POLYGON_MODE_FRONT, 1);
+ OUT_RING_CACHE(mode);
+ }
+ if (face == GL_BACK || face == GL_FRONT_AND_BACK) {
+ BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_POLYGON_MODE_BACK, 1);
+ OUT_RING_CACHE(mode);
+ }
+}
+
+/** Set the scale and units used to calculate depth values */
+static void nv30PolygonOffset(GLcontext *ctx, GLfloat factor, GLfloat units)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_POLYGON_OFFSET_FACTOR, 2);
+ OUT_RING_CACHEf(factor);
+
+ /* Looks like we always multiply units by 2.0... according to the dumps.*/
+ OUT_RING_CACHEf(units * 2.0);
+}
+
+/** Set the polygon stippling pattern */
+static void nv30PolygonStipple(GLcontext *ctx, const GLubyte *mask )
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_POLYGON_STIPPLE_PATTERN(0), 32);
+ OUT_RING_CACHEp(mask, 32);
+}
+
+/* Specifies the current buffer for reading */
+void (*ReadBuffer)( GLcontext *ctx, GLenum buffer );
+/** Set rasterization mode */
+void (*RenderMode)(GLcontext *ctx, GLenum mode );
+
+/** Define the scissor box */
+static void nv30Scissor(GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+
+ /* There's no scissor enable bit, so adjust the scissor to cover the
+ * maximum draw buffer bounds
+ */
+ if (!ctx->Scissor.Enabled) {
+ x = y = 0;
+ w = h = 4095;
+ } else {
+ x += nmesa->drawX;
+ y += nmesa->drawY;
+ }
+
+ BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_SCISSOR_WIDTH_XPOS, 2);
+ OUT_RING_CACHE(((w) << 16) | x);
+ OUT_RING_CACHE(((h) << 16) | y);
+}
+
+/** Select flat or smooth shading */
+static void nv30ShadeModel(GLcontext *ctx, GLenum mode)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+
+ BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_SHADE_MODEL, 1);
+ OUT_RING_CACHE(mode);
+}
+
+/** OpenGL 2.0 two-sided StencilFunc */
+static void nv30StencilFuncSeparate(GLcontext *ctx, GLenum face, GLenum func,
+ GLint ref, GLuint mask)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+
+ if (face == GL_FRONT || face == GL_FRONT_AND_BACK) {
+ BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_STENCIL_FRONT_FUNC_FUNC, 3);
+ OUT_RING_CACHE(func);
+ OUT_RING_CACHE(ref);
+ OUT_RING_CACHE(mask);
+ }
+ if (face == GL_BACK || face == GL_FRONT_AND_BACK) {
+ BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_STENCIL_BACK_FUNC_FUNC, 3);
+ OUT_RING_CACHE(func);
+ OUT_RING_CACHE(ref);
+ OUT_RING_CACHE(mask);
+ }
+}
+
+/** OpenGL 2.0 two-sided StencilMask */
+static void nv30StencilMaskSeparate(GLcontext *ctx, GLenum face, GLuint mask)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+
+ if (face == GL_FRONT || face == GL_FRONT_AND_BACK) {
+ BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_STENCIL_FRONT_MASK, 1);
+ OUT_RING_CACHE(mask);
+ }
+ if (face == GL_BACK || face == GL_FRONT_AND_BACK) {
+ BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_STENCIL_BACK_MASK, 1);
+ OUT_RING_CACHE(mask);
+ }
+}
+
+/** OpenGL 2.0 two-sided StencilOp */
+static void nv30StencilOpSeparate(GLcontext *ctx, GLenum face, GLenum fail,
+ GLenum zfail, GLenum zpass)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+
+ if (face == GL_FRONT || face == GL_FRONT_AND_BACK) {
+ BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_STENCIL_FRONT_OP_FAIL, 3);
+ OUT_RING_CACHE(fail);
+ OUT_RING_CACHE(zfail);
+ OUT_RING_CACHE(zpass);
+ }
+ if (face == GL_BACK || face == GL_FRONT_AND_BACK) {
+ BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_STENCIL_BACK_OP_FAIL, 3);
+ OUT_RING_CACHE(fail);
+ OUT_RING_CACHE(zfail);
+ OUT_RING_CACHE(zpass);
+ }
+}
+
+/** Control the generation of texture coordinates */
+void (*TexGen)(GLcontext *ctx, GLenum coord, GLenum pname,
+ const GLfloat *params);
+/** Set texture environment parameters */
+void (*TexEnv)(GLcontext *ctx, GLenum target, GLenum pname,
+ const GLfloat *param);
+/** Set texture parameters */
+void (*TexParameter)(GLcontext *ctx, GLenum target,
+ struct gl_texture_object *texObj,
+ GLenum pname, const GLfloat *params);
+
+static void nv30TextureMatrix(GLcontext *ctx, GLuint unit, const GLmatrix *mat)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_TX_MATRIX(unit, 0), 16);
+ /*XXX: This SHOULD work.*/
+ OUT_RING_CACHEp(mat->m, 16);
+}
+
+static void nv30WindowMoved(nouveauContextPtr nmesa)
+{
+ GLcontext *ctx = nmesa->glCtx;
+ GLfloat *v = nmesa->viewport.m;
+ GLuint w = ctx->Viewport.Width;
+ GLuint h = ctx->Viewport.Height;
+ GLuint x = ctx->Viewport.X + nmesa->drawX;
+ GLuint y = ctx->Viewport.Y + nmesa->drawY;
+
+ BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_VIEWPORT_DIMS_0, 2);
+ OUT_RING_CACHE((w << 16) | x);
+ OUT_RING_CACHE((h << 16) | y);
+ /* something to do with clears, possibly doesn't belong here */
+ BEGIN_RING_CACHE(NvSub3D,
+ NV30_TCL_PRIMITIVE_3D_VIEWPORT_COLOR_BUFFER_OFS0, 2);
+ OUT_RING_CACHE(((w+x) << 16) | x);
+ OUT_RING_CACHE(((h+y) << 16) | y);
+ /* viewport transform */
+ BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_VIEWPORT_XFRM_OX, 8);
+ OUT_RING_CACHEf (v[MAT_TX]);
+ OUT_RING_CACHEf (v[MAT_TY]);
+ OUT_RING_CACHEf (v[MAT_TZ]);
+ OUT_RING_CACHEf (0.0);
+ OUT_RING_CACHEf (v[MAT_SX]);
+ OUT_RING_CACHEf (v[MAT_SY]);
+ OUT_RING_CACHEf (v[MAT_SZ]);
+ OUT_RING_CACHEf (0.0);
+
+ ctx->Driver.Scissor(ctx, ctx->Scissor.X, ctx->Scissor.Y,
+ ctx->Scissor.Width, ctx->Scissor.Height);
+}
+
+static GLboolean nv30InitCard(nouveauContextPtr nmesa)
+{
+ /* Need some love.. */
+ return GL_FALSE;
+}
+
+static GLboolean nv40InitCard(nouveauContextPtr nmesa)
+{
+ nouveauObjectOnSubchannel(nmesa, NvSub3D, Nv3D);
+
+ BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_SET_OBJECT1, 2);
+ OUT_RING(NvDmaFB);
+ OUT_RING(NvDmaFB);
+ BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_SET_OBJECT8, 1);
+ OUT_RING(NvDmaFB);
+ BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_SET_OBJECT4, 2);
+ OUT_RING(NvDmaFB);
+ OUT_RING(NvDmaFB);
+ BEGIN_RING_SIZE(NvSub3D, 0x0220, 1);
+ OUT_RING(1);
+
+ BEGIN_RING_SIZE(NvSub3D, 0x1ea4, 3);
+ OUT_RING(0x00000010);
+ OUT_RING(0x01000100);
+ OUT_RING(0xff800006);
+ BEGIN_RING_SIZE(NvSub3D, 0x1fc4, 1);
+ OUT_RING(0x06144321);
+ BEGIN_RING_SIZE(NvSub3D, 0x1fc8, 2);
+ OUT_RING(0xedcba987);
+ OUT_RING(0x00000021);
+ BEGIN_RING_SIZE(NvSub3D, 0x1fd0, 1);
+ OUT_RING(0x00171615);
+ BEGIN_RING_SIZE(NvSub3D, 0x1fd4, 1);
+ OUT_RING(0x001b1a19);
+
+ BEGIN_RING_SIZE(NvSub3D, 0x1ef8, 1);
+ OUT_RING(0x0020ffff);
+ BEGIN_RING_SIZE(NvSub3D, 0x1d64, 1);
+ OUT_RING(0x00d30000);
+ BEGIN_RING_SIZE(NvSub3D, 0x1e94, 1);
+ OUT_RING(0x00000001);
+
+ BEGIN_RING_SIZE(NvSub3D, 0x1d60, 1);
+ OUT_RING(0x03008000);
+
+ return GL_TRUE;
+}
+
+static GLboolean nv30BindBuffers(nouveauContextPtr nmesa, int num_color,
+ nouveau_renderbuffer **color,
+ nouveau_renderbuffer *depth)
+{
+ GLuint x, y, w, h;
+
+ w = color[0]->mesa.Width;
+ h = color[0]->mesa.Height;
+ x = nmesa->drawX;
+ y = nmesa->drawY;
+
+ if (num_color != 1)
+ return GL_FALSE;
+ BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_VIEWPORT_COLOR_BUFFER_DIM0, 5);
+ OUT_RING (((w+x)<<16)|x);
+ OUT_RING (((h+y)<<16)|y);
+ if (color[0]->mesa._ActualFormat == GL_RGBA8)
+ OUT_RING (0x148);
+ else
+ OUT_RING (0x143);
+ OUT_RING (color[0]->pitch);
+ OUT_RING (color[0]->offset);
+
+ if (depth) {
+ BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_DEPTH_OFFSET, 1);
+ OUT_RING (depth->offset);
+ BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_LMA_DEPTH_BUFFER_PITCH, 1);
+ OUT_RING (depth->pitch);
+ }
+
+ return GL_TRUE;
+}
+
+void nv30InitStateFuncs(GLcontext *ctx, struct dd_function_table *func)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+
+ func->AlphaFunc = nv30AlphaFunc;
+ func->BlendColor = nv30BlendColor;
+ func->BlendEquationSeparate = nv30BlendEquationSeparate;
+ func->BlendFuncSeparate = nv30BlendFuncSeparate;
+ func->Clear = nv30Clear;
+ func->ClearColor = nv30ClearColor;
+ func->ClearDepth = nv30ClearDepth;
+ func->ClearStencil = nv30ClearStencil;
+ func->ClipPlane = nv30ClipPlane;
+ func->ColorMask = nv30ColorMask;
+ func->ColorMaterial = nv30ColorMaterial;
+ func->CullFace = nv30CullFace;
+ func->FrontFace = nv30FrontFace;
+ func->DepthFunc = nv30DepthFunc;
+ func->DepthMask = nv30DepthMask;
+ func->Enable = nv30Enable;
+ func->Fogfv = nv30Fogfv;
+ func->Hint = nv30Hint;
+ func->Lightfv = nv30Lightfv;
+/* func->LightModelfv = nv30LightModelfv; */
+ func->LineStipple = nv30LineStipple;
+ func->LineWidth = nv30LineWidth;
+ func->LogicOpcode = nv30LogicOpcode;
+ func->PointParameterfv = nv30PointParameterfv;
+ func->PointSize = nv30PointSize;
+ func->PolygonMode = nv30PolygonMode;
+ func->PolygonOffset = nv30PolygonOffset;
+ func->PolygonStipple = nv30PolygonStipple;
+#if 0
+ func->ReadBuffer = nv30ReadBuffer;
+ func->RenderMode = nv30RenderMode;
+#endif
+ func->Scissor = nv30Scissor;
+ func->ShadeModel = nv30ShadeModel;
+ func->StencilFuncSeparate = nv30StencilFuncSeparate;
+ func->StencilMaskSeparate = nv30StencilMaskSeparate;
+ func->StencilOpSeparate = nv30StencilOpSeparate;
+#if 0
+ func->TexGen = nv30TexGen;
+ func->TexParameter = nv30TexParameter;
+#endif
+ func->TextureMatrix = nv30TextureMatrix;
+
+
+ if (nmesa->screen->card->type >= NV_40)
+ nmesa->hw_func.InitCard = nv40InitCard;
+ else
+ nmesa->hw_func.InitCard = nv30InitCard;
+ nmesa->hw_func.BindBuffers = nv30BindBuffers;
+ nmesa->hw_func.WindowMoved = nv30WindowMoved;
+}
+
diff --git a/src/mesa/drivers/dri/nouveau/nv30_vertprog.c b/src/mesa/drivers/dri/nouveau/nv30_vertprog.c
new file mode 100644
index 0000000000..6ba8e35d55
--- /dev/null
+++ b/src/mesa/drivers/dri/nouveau/nv30_vertprog.c
@@ -0,0 +1,353 @@
+#include "nouveau_context.h"
+#include "nouveau_object.h"
+#include "nouveau_fifo.h"
+#include "nouveau_reg.h"
+
+#include "nouveau_shader.h"
+#include "nv30_shader.h"
+
+/*****************************************************************************
+ * Support routines
+ */
+static void
+NV30VPUploadToHW(GLcontext *ctx, nouveauShader *nvs)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ int i;
+
+ /* We can do better here and keep more than one VP on the hardware, and
+ * switch between them with PROGRAM_START_ID..
+ */
+ BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_VP_UPLOAD_FROM_ID, 1);
+ OUT_RING(0);
+ for (i=0; i<nvs->program_size; i+=4) {
+ BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_VP_UPLOAD_INST0, 4);
+ OUT_RING(nvs->program[i + 0]);
+ OUT_RING(nvs->program[i + 1]);
+ OUT_RING(nvs->program[i + 2]);
+ OUT_RING(nvs->program[i + 3]);
+ }
+ BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_VP_PROGRAM_START_ID, 1);
+ OUT_RING(0);
+}
+
+static void
+NV30VPUpdateConst(GLcontext *ctx, nouveauShader *nvs, int id)
+{
+ nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+ GLfloat *val;
+
+ val = nvs->params[id].source_val ?
+ nvs->params[id].source_val : nvs->params[id].val;
+
+ BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_VP_UPLOAD_CONST_ID, 5);
+ OUT_RING (id);
+ OUT_RINGp(val, 4);
+}
+
+/*****************************************************************************
+ * Assembly routines
+ */
+
+/*****************************************************************************
+ * Disassembly routines
+ */
+static unsigned int
+NV30VPGetOpcodeHW(nvsFunc * shader, int slot)
+{
+ int op;
+
+ if (slot) {
+ op = (shader->inst[1] & NV30_VP_INST_SCA_OPCODEL_MASK)
+ >> NV30_VP_INST_SCA_OPCODEL_SHIFT;
+ op |= ((shader->inst[0] & NV30_VP_INST_SCA_OPCODEH_MASK)
+ >> NV30_VP_INST_SCA_OPCODEH_SHIFT) << 4;
+ }
+ else {
+ op = (shader->inst[1] & NV30_VP_INST_VEC_OPCODE_MASK)
+ >> NV30_VP_INST_VEC_OPCODE_SHIFT;
+ }
+
+ return op;
+}
+
+static nvsRegFile
+NV30VPGetDestFile(nvsFunc * shader, int merged)
+{
+ switch (shader->GetOpcode(shader, merged)) {
+ case NVS_OP_ARL:
+ case NVS_OP_ARR:
+ case NVS_OP_ARA:
+ return NVS_FILE_ADDRESS;
+ default:
+ /*FIXME: This probably isn't correct.. */
+ if ((shader->inst[3] & NV30_VP_INST_VDEST_WRITEMASK_MASK) != 0)
+ return NVS_FILE_RESULT;
+ if ((shader->inst[3] & NV30_VP_INST_SDEST_WRITEMASK_MASK) != 0)
+ return NVS_FILE_RESULT;
+ return NVS_FILE_TEMP;
+ }
+}
+
+static unsigned int
+NV30VPGetDestID(nvsFunc * shader, int merged)
+{
+ int id;
+
+ switch (shader->GetDestFile(shader, merged)) {
+ case NVS_FILE_RESULT:
+ id = ((shader->inst[3] & NV30_VP_INST_DEST_ID_MASK)
+ >> NV30_VP_INST_DEST_ID_SHIFT);
+ switch (id) {
+ case NV30_VP_INST_DEST_POS : return NVS_FR_POSITION;
+ case NV30_VP_INST_DEST_COL0 : return NVS_FR_COL0;
+ case NV30_VP_INST_DEST_COL1 : return NVS_FR_COL1;
+ case NV30_VP_INST_DEST_TC(0): return NVS_FR_TEXCOORD0;
+ case NV30_VP_INST_DEST_TC(1): return NVS_FR_TEXCOORD1;
+ case NV30_VP_INST_DEST_TC(2): return NVS_FR_TEXCOORD2;
+ case NV30_VP_INST_DEST_TC(3): return NVS_FR_TEXCOORD3;
+ case NV30_VP_INST_DEST_TC(4): return NVS_FR_TEXCOORD4;
+ case NV30_VP_INST_DEST_TC(5): return NVS_FR_TEXCOORD5;
+ case NV30_VP_INST_DEST_TC(6): return NVS_FR_TEXCOORD6;
+ case NV30_VP_INST_DEST_TC(7): return NVS_FR_TEXCOORD7;
+ default:
+ return -1;
+ }
+ case NVS_FILE_ADDRESS:
+ case NVS_FILE_TEMP:
+ return (shader->inst[0] & NV30_VP_INST_DEST_TEMP_ID_MASK)
+ >> NV30_VP_INST_DEST_TEMP_ID_SHIFT;
+ default:
+ return -1;
+ }
+}
+
+static unsigned int
+NV30VPGetDestMask(nvsFunc * shader, int merged)
+{
+ int hwmask, mask = 0;
+
+ if (shader->GetDestFile(shader, merged) == NVS_FILE_RESULT)
+ if (shader->GetOpcodeSlot(shader, merged))
+ hwmask = (shader->inst[3] & NV30_VP_INST_SDEST_WRITEMASK_MASK)
+ >> NV30_VP_INST_SDEST_WRITEMASK_SHIFT;
+ else
+ hwmask = (shader->inst[3] & NV30_VP_INST_VDEST_WRITEMASK_MASK)
+ >> NV30_VP_INST_VDEST_WRITEMASK_SHIFT;
+ else if (shader->GetOpcodeSlot(shader, merged))
+ hwmask = (shader->inst[3] & NV30_VP_INST_STEMP_WRITEMASK_MASK)
+ >> NV30_VP_INST_STEMP_WRITEMASK_SHIFT;
+ else
+ hwmask = (shader->inst[3] & NV30_VP_INST_VTEMP_WRITEMASK_MASK)
+ >> NV30_VP_INST_VTEMP_WRITEMASK_SHIFT;
+
+ if (hwmask & (1 << 3)) mask |= SMASK_X;
+ if (hwmask & (1 << 2)) mask |= SMASK_Y;
+ if (hwmask & (1 << 1)) mask |= SMASK_Z;
+ if (hwmask & (1 << 0)) mask |= SMASK_W;
+
+ return mask;
+}
+
+static int
+NV30VPGetSourceID(nvsFunc * shader, int merged, int pos)
+{
+ unsigned int src;
+
+ switch (shader->GetSourceFile(shader, merged, pos)) {
+ case NVS_FILE_TEMP:
+ src = shader->GetSourceHW(shader, merged, pos);
+ return ((src & NV30_VP_SRC_REG_TEMP_ID_MASK) >>
+ NV30_VP_SRC_REG_TEMP_ID_SHIFT);
+ case NVS_FILE_CONST:
+ return ((shader->inst[1] & NV30_VP_INST_CONST_SRC_MASK)
+ >> NV30_VP_INST_CONST_SRC_SHIFT);
+ case NVS_FILE_ATTRIB:
+ src = ((shader->inst[1] & NV30_VP_INST_INPUT_SRC_MASK)
+ >> NV30_VP_INST_INPUT_SRC_SHIFT);
+ switch (src) {
+ case NV30_VP_INST_IN_POS : return NVS_FR_POSITION;
+ case NV30_VP_INST_IN_COL0 : return NVS_FR_COL0;
+ case NV30_VP_INST_IN_COL1 : return NVS_FR_COL1;
+ case NV30_VP_INST_IN_TC(0): return NVS_FR_TEXCOORD0;
+ case NV30_VP_INST_IN_TC(1): return NVS_FR_TEXCOORD1;
+ case NV30_VP_INST_IN_TC(2): return NVS_FR_TEXCOORD2;
+ case NV30_VP_INST_IN_TC(3): return NVS_FR_TEXCOORD3;
+ case NV30_VP_INST_IN_TC(4): return NVS_FR_TEXCOORD4;
+ case NV30_VP_INST_IN_TC(5): return NVS_FR_TEXCOORD5;
+ case NV30_VP_INST_IN_TC(6): return NVS_FR_TEXCOORD6;
+ case NV30_VP_INST_IN_TC(7): return NVS_FR_TEXCOORD7;
+ default:
+ return NVS_FR_UNKNOWN;
+ }
+ default:
+ return -1;
+ }
+}
+
+static int
+NV30VPGetSourceAbs(nvsFunc * shader, int merged, int pos)
+{
+ struct _op_xlat *opr;
+ static unsigned int abspos[3] = {
+ NV30_VP_INST_SRC0_ABS,
+ NV30_VP_INST_SRC1_ABS,
+ NV30_VP_INST_SRC2_ABS,
+ };
+
+ opr = shader->GetOPTXRec(shader, merged);
+ if (!opr || opr->srcpos[pos] == -1 || opr->srcpos[pos] > 2)
+ return 0;
+
+ return ((shader->inst[0] & abspos[opr->srcpos[pos]]) ? 1 : 0);
+}
+
+static int
+NV30VPGetRelAddressRegID(nvsFunc * shader)
+{
+ return ((shader->inst[0] & NV30_VP_INST_ADDR_REG_SELECT_1) ? 1 : 0);
+}
+
+static nvsSwzComp
+NV30VPGetRelAddressSwizzle(nvsFunc * shader)
+{
+ nvsSwzComp swz;
+
+ swz = NV20VP_TX_SWIZZLE[(shader->inst[0] & NV30_VP_INST_ADDR_SWZ_MASK)
+ >> NV30_VP_INST_ADDR_SWZ_SHIFT];
+ return swz;
+}
+
+static int
+NV30VPSupportsConditional(nvsFunc * shader)
+{
+ /*FIXME: Is this true of all ops? */
+ return 1;
+}
+
+static int
+NV30VPGetConditionUpdate(nvsFunc * shader)
+{
+ return ((shader->inst[0] & NV30_VP_INST_COND_UPDATE_ENABLE) ? 1 : 0);
+}
+
+static int
+NV30VPGetConditionTest(nvsFunc * shader)
+{
+ int op;
+
+ /* The condition test is unconditionally enabled on some
+ * instructions. ie: the condition test bit does *NOT* have
+ * to be set.
+ *
+ * FIXME: check other relevant ops for this situation.
+ */
+ op = shader->GetOpcodeHW(shader, 1);
+ switch (op) {
+ case NV30_VP_INST_OP_BRA:
+ return 1;
+ default:
+ return ((shader->inst[0] & NV30_VP_INST_COND_TEST_ENABLE) ? 1 : 0);
+ }
+}
+
+static nvsCond
+NV30VPGetCondition(nvsFunc * shader)
+{
+ int cond;
+
+ cond = ((shader->inst[0] & NV30_VP_INST_COND_MASK)
+ >> NV30_VP_INST_COND_SHIFT);
+
+ switch (cond) {
+ case NV30_VP_INST_COND_FL: return NVS_COND_FL;
+ case NV30_VP_INST_COND_LT: return NVS_COND_LT;
+ case NV30_VP_INST_COND_EQ: return NVS_COND_EQ;
+ case NV30_VP_INST_COND_LE: return NVS_COND_LE;
+ case NV30_VP_INST_COND_GT: return NVS_COND_GT;
+ case NV30_VP_INST_COND_NE: return NVS_COND_NE;
+ case NV30_VP_INST_COND_GE: return NVS_COND_GE;
+ case NV30_VP_INST_COND_TR: return NVS_COND_TR;
+ default:
+ return NVS_COND_UNKNOWN;
+ }
+}
+
+static void
+NV30VPGetCondRegSwizzle(nvsFunc * shader, nvsSwzComp *swz)
+{
+ int swzbits;
+
+ swzbits = (shader->inst[0] & NV30_VP_INST_COND_SWZ_ALL_MASK)
+ >> NV30_VP_INST_COND_SWZ_ALL_SHIFT;
+ NV20VPTXSwizzle(swzbits, swz);
+}
+
+static int
+NV30VPGetCondRegID(nvsFunc * shader)
+{
+ return 0;
+}
+
+
+static int
+NV30VPGetBranch(nvsFunc * shader)
+{
+ return ((shader->inst[2] & NV30_VP_INST_IADDR_MASK)
+ >> NV30_VP_INST_IADDR_SHIFT);
+}
+
+void
+NV30VPInitShaderFuncs(nvsFunc * shader)
+{
+ /* Inherit NV20 code, a lot of it is the same */
+ NV20VPInitShaderFuncs(shader);
+
+ /* Increase max valid opcode ID, and add new instructions */
+ NVVP_TX_VOP_COUNT = NVVP_TX_NVS_OP_COUNT = 32;
+
+ MOD_OPCODE(NVVP_TX_VOP, NV30_VP_INST_OP_FRC, NVS_OP_FRC, 0, -1, -1);
+ MOD_OPCODE(NVVP_TX_VOP, NV30_VP_INST_OP_FLR, NVS_OP_FLR, 0, -1, -1);
+ MOD_OPCODE(NVVP_TX_VOP, NV30_VP_INST_OP_SEQ, NVS_OP_SEQ, 0, 1, -1);
+ MOD_OPCODE(NVVP_TX_VOP, NV30_VP_INST_OP_SFL, NVS_OP_SFL, 0, 1, -1);
+ MOD_OPCODE(NVVP_TX_VOP, NV30_VP_INST_OP_SGT, NVS_OP_SGT, 0, 1, -1);
+ MOD_OPCODE(NVVP_TX_VOP, NV30_VP_INST_OP_SLE, NVS_OP_SLE, 0, 1, -1);
+ MOD_OPCODE(NVVP_TX_VOP, NV30_VP_INST_OP_SNE, NVS_OP_SNE, 0, 1, -1);
+ MOD_OPCODE(NVVP_TX_VOP, NV30_VP_INST_OP_STR, NVS_OP_STR, 0, 1, -1);
+ MOD_OPCODE(NVVP_TX_VOP, NV30_VP_INST_OP_SSG, NVS_OP_SSG, 0, -1, -1);
+ MOD_OPCODE(NVVP_TX_VOP, NV30_VP_INST_OP_ARR, NVS_OP_ARR, 0, -1, -1);
+ MOD_OPCODE(NVVP_TX_VOP, NV30_VP_INST_OP_ARA, NVS_OP_ARA, 3, -1, -1);
+
+ MOD_OPCODE(NVVP_TX_SOP, NV30_VP_INST_OP_BRA, NVS_OP_BRA, -1, -1, -1);
+ MOD_OPCODE(NVVP_TX_SOP, NV30_VP_INST_OP_CAL, NVS_OP_CAL, -1, -1, -1);
+ MOD_OPCODE(NVVP_TX_SOP, NV30_VP_INST_OP_RET, NVS_OP_RET, -1, -1, -1);
+ MOD_OPCODE(NVVP_TX_SOP, NV30_VP_INST_OP_LG2, NVS_OP_LG2, 2, -1, -1);
+ MOD_OPCODE(NVVP_TX_SOP, NV30_VP_INST_OP_EX2, NVS_OP_EX2, 2, -1, -1);
+ MOD_OPCODE(NVVP_TX_SOP, NV30_VP_INST_OP_SIN, NVS_OP_SIN, 2, -1, -1);
+ MOD_OPCODE(NVVP_TX_SOP, NV30_VP_INST_OP_COS, NVS_OP_COS, 2, -1, -1);
+
+ shader->UploadToHW = NV30VPUploadToHW;
+ shader->UpdateConst = NV30VPUpdateConst;
+
+ shader->GetOpcodeHW = NV30VPGetOpcodeHW;
+
+ shader->GetDestFile = NV30VPGetDestFile;
+ shader->GetDestID = NV30VPGetDestID;
+ shader->GetDestMask = NV30VPGetDestMask;
+
+ shader->GetSourceID = NV30VPGetSourceID;
+ shader->GetSourceAbs = NV30VPGetSourceAbs;
+
+ shader->GetRelAddressRegID = NV30VPGetRelAddressRegID;
+ shader->GetRelAddressSwizzle = NV30VPGetRelAddressSwizzle;
+
+ shader->SupportsConditional = NV30VPSupportsConditional;
+ shader->GetConditionUpdate = NV30VPGetConditionUpdate;
+ shader->GetConditionTest = NV30VPGetConditionTest;
+ shader->GetCondition = NV30VPGetCondition;
+ shader->GetCondRegSwizzle = NV30VPGetCondRegSwizzle;
+ shader->GetCondRegID = NV30VPGetCondRegID;
+
+ shader->GetBranch = NV30VPGetBranch;
+}
+
diff --git a/src/mesa/drivers/dri/nouveau/nv40_fragprog.c b/src/mesa/drivers/dri/nouveau/nv40_fragprog.c
new file mode 100644
index 0000000000..3d58d6b666
--- /dev/null
+++ b/src/mesa/drivers/dri/nouveau/nv40_fragprog.c
@@ -0,0 +1,152 @@
+#include "nouveau_shader.h"
+#include "nv40_shader.h"
+
+/* branching ops */
+unsigned int NVFP_TX_BOP_COUNT = 5;
+struct _op_xlat NVFP_TX_BOP[64];
+
+static struct _op_xlat *
+NV40FPGetOPTXRec(nvsFunc * shader, int merged)
+{
+ struct _op_xlat *opr;
+ int op;
+
+ op = shader->GetOpcodeHW(shader, 0);
+ if (shader->inst[2] & NV40_FP_OP_OPCODE_IS_BRANCH) {
+ opr = NVFP_TX_BOP;
+ op &= ~NV40_FP_OP_OPCODE_IS_BRANCH;
+ if (op > NVFP_TX_BOP_COUNT)
+ return NULL;
+ }
+ else {
+ opr = NVFP_TX_AOP;
+ if (op > NVFP_TX_AOP_COUNT)
+ return NULL;
+ }
+
+ if (opr[op].SOP == NVS_OP_UNKNOWN)
+ return NULL;
+ return &opr[op];
+}
+
+static int
+NV40FPGetSourceID(nvsFunc * shader, int merged, int pos)
+{
+ switch (shader->GetSourceFile(shader, merged, pos)) {
+ case NVS_FILE_ATTRIB:
+ switch ((shader->inst[0] & NV40_FP_OP_INPUT_SRC_MASK)
+ >> NV40_FP_OP_INPUT_SRC_SHIFT) {
+ case NV40_FP_OP_INPUT_SRC_POSITION: return NVS_FR_POSITION;
+ case NV40_FP_OP_INPUT_SRC_COL0 : return NVS_FR_COL0;
+ case NV40_FP_OP_INPUT_SRC_COL1 : return NVS_FR_COL1;
+ case NV40_FP_OP_INPUT_SRC_FOGC : return NVS_FR_FOGCOORD;
+ case NV40_FP_OP_INPUT_SRC_TC(0) : return NVS_FR_TEXCOORD0;
+ case NV40_FP_OP_INPUT_SRC_TC(1) : return NVS_FR_TEXCOORD1;
+ case NV40_FP_OP_INPUT_SRC_TC(2) : return NVS_FR_TEXCOORD2;
+ case NV40_FP_OP_INPUT_SRC_TC(3) : return NVS_FR_TEXCOORD3;
+ case NV40_FP_OP_INPUT_SRC_TC(4) : return NVS_FR_TEXCOORD4;
+ case NV40_FP_OP_INPUT_SRC_TC(5) : return NVS_FR_TEXCOORD5;
+ case NV40_FP_OP_INPUT_SRC_TC(6) : return NVS_FR_TEXCOORD6;
+ case NV40_FP_OP_INPUT_SRC_TC(7) : return NVS_FR_TEXCOORD7;
+ case NV40_FP_OP_INPUT_SRC_FACING : return NVS_FR_FACING;
+ default:
+ return -1;
+ }
+ break;
+ case NVS_FILE_TEMP:
+ {
+ unsigned int src;
+
+ src = shader->GetSourceHW(shader, merged, pos);
+ return ((src & NV40_FP_REG_SRC_MASK) >> NV40_FP_REG_SRC_SHIFT);
+ }
+ case NVS_FILE_CONST: /* inlined into fragprog */
+ default:
+ return -1;
+ }
+}
+
+static int
+NV40FPGetBranch(nvsFunc * shader)
+{
+ return ((shader->inst[2] & NV40_FP_OP_IADDR_MASK)
+ >> NV40_FP_OP_IADDR_SHIFT);;
+}
+
+static int
+NV40FPGetBranchElse(nvsFunc * shader)
+{
+ return ((shader->inst[2] & NV40_FP_OP_ELSE_ID_MASK)
+ >> NV40_FP_OP_ELSE_ID_SHIFT);
+}
+
+static int
+NV40FPGetBranchEnd(nvsFunc * shader)
+{
+ return ((shader->inst[3] & NV40_FP_OP_END_ID_MASK)
+ >> NV40_FP_OP_END_ID_SHIFT);
+}
+
+static int
+NV40FPGetLoopCount(nvsFunc * shader)
+{
+ return ((shader->inst[2] & NV40_FP_OP_LOOP_COUNT_MASK)
+ >> NV40_FP_OP_LOOP_COUNT_SHIFT);
+}
+
+static int
+NV40FPGetLoopInitial(nvsFunc * shader)
+{
+ return ((shader->inst[2] & NV40_FP_OP_LOOP_INDEX_MASK)
+ >> NV40_FP_OP_LOOP_INDEX_SHIFT);
+}
+
+static int
+NV40FPGetLoopIncrement(nvsFunc * shader)
+{
+ return ((shader->inst[2] & NV40_FP_OP_LOOP_INCR_MASK)
+ >> NV40_FP_OP_LOOP_INCR_SHIFT);
+}
+
+void
+NV40FPInitShaderFuncs(nvsFunc * shader)
+{
+ /* Inherit NV30 FP code, it's mostly the same */
+ NV30FPInitShaderFuncs(shader);
+
+ /* Kill off opcodes seen on NV30, but not seen on NV40 - need to find
+ * out if these actually work or not.
+ *
+ * update: either LIT/RSQ don't work on nv40, or I generate bad code for
+ * them. haven't tested the others yet
+ */
+ MOD_OPCODE(NVFP_TX_AOP, 0x1B, NVS_OP_UNKNOWN, -1, -1, -1); /* NV30 RSQ */
+ MOD_OPCODE(NVFP_TX_AOP, 0x1E, NVS_OP_UNKNOWN, -1, -1, -1); /* NV30 LIT */
+ MOD_OPCODE(NVFP_TX_AOP, 0x1F, NVS_OP_UNKNOWN, -1, -1, -1); /* NV30 LRP */
+ MOD_OPCODE(NVFP_TX_AOP, 0x26, NVS_OP_UNKNOWN, -1, -1, -1); /* NV30 POW */
+ MOD_OPCODE(NVFP_TX_AOP, 0x36, NVS_OP_UNKNOWN, -1, -1, -1); /* NV30 RFL */
+
+ /* Extra opcodes supported on NV40 */
+ MOD_OPCODE(NVFP_TX_AOP, NV40_FP_OP_OPCODE_DIV , NVS_OP_DIV , 0, 1, -1);
+ MOD_OPCODE(NVFP_TX_AOP, NV40_FP_OP_OPCODE_DP2A , NVS_OP_DP2A, 0, 1, 2);
+ MOD_OPCODE(NVFP_TX_AOP, NV40_FP_OP_OPCODE_TXL , NVS_OP_TXL , 0, -1, -1);
+
+ MOD_OPCODE(NVFP_TX_BOP, NV40_FP_OP_BRA_OPCODE_BRK , NVS_OP_BRK , -1, -1, -1);
+ MOD_OPCODE(NVFP_TX_BOP, NV40_FP_OP_BRA_OPCODE_CAL , NVS_OP_CAL , -1, -1, -1);
+ MOD_OPCODE(NVFP_TX_BOP, NV40_FP_OP_BRA_OPCODE_IF , NVS_OP_IF , -1, -1, -1);
+ MOD_OPCODE(NVFP_TX_BOP, NV40_FP_OP_BRA_OPCODE_LOOP, NVS_OP_LOOP, -1, -1, -1);
+ MOD_OPCODE(NVFP_TX_BOP, NV40_FP_OP_BRA_OPCODE_REP , NVS_OP_REP , -1, -1, -1);
+ MOD_OPCODE(NVFP_TX_BOP, NV40_FP_OP_BRA_OPCODE_RET , NVS_OP_RET , -1, -1, -1);
+
+ /* fragment.facing */
+ shader->GetSourceID = NV40FPGetSourceID;
+
+ /* branching */
+ shader->GetOPTXRec = NV40FPGetOPTXRec;
+ shader->GetBranch = NV40FPGetBranch;
+ shader->GetBranchElse = NV40FPGetBranchElse;
+ shader->GetBranchEnd = NV40FPGetBranchEnd;
+ shader->GetLoopCount = NV40FPGetLoopCount;
+ shader->GetLoopInitial = NV40FPGetLoopInitial;
+ shader->GetLoopIncrement = NV40FPGetLoopIncrement;
+}
diff --git a/src/mesa/drivers/dri/nouveau/nv40_shader.h b/src/mesa/drivers/dri/nouveau/nv40_shader.h
new file mode 100644
index 0000000000..2a2b5639b6
--- /dev/null
+++ b/src/mesa/drivers/dri/nouveau/nv40_shader.h
@@ -0,0 +1,467 @@
+#ifndef __NV40_SHADER_H__
+#define __NV40_SHADER_H__
+
+/* Vertex programs instruction set
+ *
+ * The NV40 instruction set is very similar to NV30. Most fields are in
+ * a slightly different position in the instruction however.
+ *
+ * Merged instructions
+ * In some cases it is possible to put two instructions into one opcode
+ * slot. The rules for when this is OK is not entirely clear to me yet.
+ *
+ * There are separate writemasks and dest temp register fields for each
+ * grouping of instructions. There is however only one field with the
+ * ID of a result register. Writing to temp/result regs is selected by
+ * setting VEC_RESULT/SCA_RESULT.
+ *
+ * Temporary registers
+ * The source/dest temp register fields have been extended by 1 bit, to
+ * give a total of 32 temporary registers.
+ *
+ * Relative Addressing
+ * NV40 can use an address register to index into vertex attribute regs.
+ * This is done by putting the offset value into INPUT_SRC and setting
+ * the INDEX_INPUT flag.
+ *
+ * Conditional execution (see NV_vertex_program{2,3} for details)
+ * There is a second condition code register on NV40, it's use is enabled
+ * by setting the COND_REG_SELECT_1 flag.
+ *
+ * Texture lookup
+ * TODO
+ */
+
+/* ---- OPCODE BITS 127:96 / data DWORD 0 --- */
+#define NV40_VP_INST_VEC_RESULT (1 << 30)
+/* uncertain.. */
+#define NV40_VP_INST_COND_UPDATE_ENABLE ((1 << 14)|1<<29)
+/* use address reg as index into attribs */
+#define NV40_VP_INST_INDEX_INPUT (1 << 27)
+#define NV40_VP_INST_COND_REG_SELECT_1 (1 << 25)
+#define NV40_VP_INST_ADDR_REG_SELECT_1 (1 << 24)
+#define NV40_VP_INST_SRC2_ABS (1 << 23)
+#define NV40_VP_INST_SRC1_ABS (1 << 22)
+#define NV40_VP_INST_SRC0_ABS (1 << 21)
+#define NV40_VP_INST_VEC_DEST_TEMP_SHIFT 15
+#define NV40_VP_INST_VEC_DEST_TEMP_MASK (0x1F << 15)
+#define NV40_VP_INST_COND_TEST_ENABLE (1 << 13)
+#define NV40_VP_INST_COND_SHIFT 10
+#define NV40_VP_INST_COND_MASK (0x7 << 10)
+# define NV40_VP_INST_COND_FL 0
+# define NV40_VP_INST_COND_LT 1
+# define NV40_VP_INST_COND_EQ 2
+# define NV40_VP_INST_COND_LE 3
+# define NV40_VP_INST_COND_GT 4
+# define NV40_VP_INST_COND_NE 5
+# define NV40_VP_INST_COND_GE 6
+# define NV40_VP_INST_COND_TR 7
+#define NV40_VP_INST_COND_SWZ_X_SHIFT 8
+#define NV40_VP_INST_COND_SWZ_X_MASK (3 << 8)
+#define NV40_VP_INST_COND_SWZ_Y_SHIFT 6
+#define NV40_VP_INST_COND_SWZ_Y_MASK (3 << 6)
+#define NV40_VP_INST_COND_SWZ_Z_SHIFT 4
+#define NV40_VP_INST_COND_SWZ_Z_MASK (3 << 4)
+#define NV40_VP_INST_COND_SWZ_W_SHIFT 2
+#define NV40_VP_INST_COND_SWZ_W_MASK (3 << 2)
+#define NV40_VP_INST_COND_SWZ_ALL_SHIFT 2
+#define NV40_VP_INST_COND_SWZ_ALL_MASK (0xFF << 2)
+#define NV40_VP_INST_ADDR_SWZ_SHIFT 0
+#define NV40_VP_INST_ADDR_SWZ_MASK (0x03 << 0)
+#define NV40_VP_INST0_KNOWN ( \
+ NV40_VP_INST_INDEX_INPUT | \
+ NV40_VP_INST_COND_REG_SELECT_1 | \
+ NV40_VP_INST_ADDR_REG_SELECT_1 | \
+ NV40_VP_INST_SRC2_ABS | \
+ NV40_VP_INST_SRC1_ABS | \
+ NV40_VP_INST_SRC0_ABS | \
+ NV40_VP_INST_VEC_DEST_TEMP_MASK | \
+ NV40_VP_INST_COND_TEST_ENABLE | \
+ NV40_VP_INST_COND_MASK | \
+ NV40_VP_INST_COND_SWZ_ALL_MASK | \
+ NV40_VP_INST_ADDR_SWZ_MASK)
+
+/* ---- OPCODE BITS 95:64 / data DWORD 1 --- */
+#define NV40_VP_INST_VEC_OPCODE_SHIFT 22
+#define NV40_VP_INST_VEC_OPCODE_MASK (0x1F << 22)
+# define NV40_VP_INST_OP_NOP 0x00
+# define NV40_VP_INST_OP_MOV 0x01
+# define NV40_VP_INST_OP_MUL 0x02
+# define NV40_VP_INST_OP_ADD 0x03
+# define NV40_VP_INST_OP_MAD 0x04
+# define NV40_VP_INST_OP_DP3 0x05
+# define NV40_VP_INST_OP_DP4 0x07
+# define NV40_VP_INST_OP_DPH 0x06
+# define NV40_VP_INST_OP_DST 0x08
+# define NV40_VP_INST_OP_MIN 0x09
+# define NV40_VP_INST_OP_MAX 0x0A
+# define NV40_VP_INST_OP_SLT 0x0B
+# define NV40_VP_INST_OP_SGE 0x0C
+# define NV40_VP_INST_OP_ARL 0x0D
+# define NV40_VP_INST_OP_FRC 0x0E
+# define NV40_VP_INST_OP_FLR 0x0F
+# define NV40_VP_INST_OP_SEQ 0x10
+# define NV40_VP_INST_OP_SFL 0x11
+# define NV40_VP_INST_OP_SGT 0x12
+# define NV40_VP_INST_OP_SLE 0x13
+# define NV40_VP_INST_OP_SNE 0x14
+# define NV40_VP_INST_OP_STR 0x15
+# define NV40_VP_INST_OP_SSG 0x16
+# define NV40_VP_INST_OP_ARR 0x17
+# define NV40_VP_INST_OP_ARA 0x18
+# define NV40_VP_INST_OP_TXWHAT 0x19
+#define NV40_VP_INST_SCA_OPCODE_SHIFT 27
+#define NV40_VP_INST_SCA_OPCODE_MASK (0x1F << 27)
+# define NV40_VP_INST_OP_RCP 0x02
+# define NV40_VP_INST_OP_RCC 0x03
+# define NV40_VP_INST_OP_RSQ 0x04
+# define NV40_VP_INST_OP_EXP 0x05
+# define NV40_VP_INST_OP_LOG 0x06
+# define NV40_VP_INST_OP_LIT 0x07
+# define NV40_VP_INST_OP_BRA 0x09
+# define NV40_VP_INST_OP_CAL 0x0B
+# define NV40_VP_INST_OP_RET 0x0C
+# define NV40_VP_INST_OP_LG2 0x0D
+# define NV40_VP_INST_OP_EX2 0x0E
+# define NV40_VP_INST_OP_SIN 0x0F
+# define NV40_VP_INST_OP_COS 0x10
+# define NV40_VP_INST_OP_PUSHA 0x13
+# define NV40_VP_INST_OP_POPA 0x14
+#define NV40_VP_INST_CONST_SRC_SHIFT 12
+#define NV40_VP_INST_CONST_SRC_MASK (0xFF << 12)
+#define NV40_VP_INST_INPUT_SRC_SHIFT 8
+#define NV40_VP_INST_INPUT_SRC_MASK (0x0F << 8)
+# define NV40_VP_INST_IN_POS 0
+# define NV40_VP_INST_IN_WEIGHT 1
+# define NV40_VP_INST_IN_NORMAL 2
+# define NV40_VP_INST_IN_COL0 3
+# define NV40_VP_INST_IN_COL1 4
+# define NV40_VP_INST_IN_FOGC 5
+# define NV40_VP_INST_IN_TC0 8
+# define NV40_VP_INST_IN_TC(n) (8+n)
+#define NV40_VP_INST_SRC0H_SHIFT 0
+#define NV40_VP_INST_SRC0H_MASK (0xFF << 0)
+#define NV40_VP_INST1_KNOWN ( \
+ NV40_VP_INST_VEC_OPCODE_MASK | \
+ NV40_VP_INST_SCA_OPCODE_MASK | \
+ NV40_VP_INST_CONST_SRC_MASK | \
+ NV40_VP_INST_INPUT_SRC_MASK | \
+ NV40_VP_INST_SRC0H_MASK \
+ )
+
+/* ---- OPCODE BITS 63:32 / data DWORD 2 --- */
+#define NV40_VP_INST_SRC0L_SHIFT 23
+#define NV40_VP_INST_SRC0L_MASK (0x1FF << 23)
+#define NV40_VP_INST_SRC1_SHIFT 6
+#define NV40_VP_INST_SRC1_MASK (0x1FFFF << 6)
+#define NV40_VP_INST_SRC2H_SHIFT 0
+#define NV40_VP_INST_SRC2H_MASK (0x3F << 0)
+#define NV40_VP_INST_IADDRH_SHIFT 0
+#define NV40_VP_INST_IADDRH_MASK (0x1F << 0)
+
+/* ---- OPCODE BITS 31:0 / data DWORD 3 --- */
+#define NV40_VP_INST_IADDRL_SHIFT 29
+#define NV40_VP_INST_IADDRL_MASK (7 << 29)
+#define NV40_VP_INST_SRC2L_SHIFT 21
+#define NV40_VP_INST_SRC2L_MASK (0x7FF << 21)
+#define NV40_VP_INST_SCA_WRITEMASK_SHIFT 17
+#define NV40_VP_INST_SCA_WRITEMASK_MASK (0xF << 17)
+# define NV40_VP_INST_SCA_WRITEMASK_X (1 << 20)
+# define NV40_VP_INST_SCA_WRITEMASK_Y (1 << 19)
+# define NV40_VP_INST_SCA_WRITEMASK_Z (1 << 18)
+# define NV40_VP_INST_SCA_WRITEMASK_W (1 << 17)
+#define NV40_VP_INST_VEC_WRITEMASK_SHIFT 13
+#define NV40_VP_INST_VEC_WRITEMASK_MASK (0xF << 13)
+# define NV40_VP_INST_VEC_WRITEMASK_X (1 << 16)
+# define NV40_VP_INST_VEC_WRITEMASK_Y (1 << 15)
+# define NV40_VP_INST_VEC_WRITEMASK_Z (1 << 14)
+# define NV40_VP_INST_VEC_WRITEMASK_W (1 << 13)
+#define NV40_VP_INST_SCA_RESULT (1 << 12)
+#define NV40_VP_INST_SCA_DEST_TEMP_SHIFT 7
+#define NV40_VP_INST_SCA_DEST_TEMP_MASK (0x1F << 7)
+#define NV40_VP_INST_DEST_SHIFT 2
+#define NV40_VP_INST_DEST_MASK (31 << 2)
+# define NV40_VP_INST_DEST_POS 0
+# define NV40_VP_INST_DEST_COL0 1
+# define NV40_VP_INST_DEST_COL1 2
+# define NV40_VP_INST_DEST_BFC0 3
+# define NV40_VP_INST_DEST_BFC1 4
+# define NV40_VP_INST_DEST_FOGC 5
+# define NV40_VP_INST_DEST_PSZ 6
+# define NV40_VP_INST_DEST_TC0 7
+# define NV40_VP_INST_DEST_TC(n) (7+n)
+# define NV40_VP_INST_DEST_TEMP 0x1F
+#define NV40_VP_INST_INDEX_CONST (1 << 1)
+#define NV40_VP_INST_LAST (1 << 0)
+#define NV40_VP_INST3_KNOWN ( \
+ NV40_VP_INST_SRC2L_MASK |\
+ NV40_VP_INST_SCA_WRITEMASK_MASK |\
+ NV40_VP_INST_VEC_WRITEMASK_MASK |\
+ NV40_VP_INST_SCA_DEST_TEMP_MASK |\
+ NV40_VP_INST_DEST_MASK |\
+ NV40_VP_INST_INDEX_CONST)
+
+/* Useful to split the source selection regs into their pieces */
+#define NV40_VP_SRC0_HIGH_SHIFT 9
+#define NV40_VP_SRC0_HIGH_MASK 0x0001FE00
+#define NV40_VP_SRC0_LOW_MASK 0x000001FF
+#define NV40_VP_SRC2_HIGH_SHIFT 11
+#define NV40_VP_SRC2_HIGH_MASK 0x0001F800
+#define NV40_VP_SRC2_LOW_MASK 0x000007FF
+
+/* Source selection - these are the bits you fill NV40_VP_INST_SRCn with */
+#define NV40_VP_SRC_NEGATE (1 << 16)
+#define NV40_VP_SRC_SWZ_X_SHIFT 14
+#define NV40_VP_SRC_SWZ_X_MASK (3 << 14)
+#define NV40_VP_SRC_SWZ_Y_SHIFT 12
+#define NV40_VP_SRC_SWZ_Y_MASK (3 << 12)
+#define NV40_VP_SRC_SWZ_Z_SHIFT 10
+#define NV40_VP_SRC_SWZ_Z_MASK (3 << 10)
+#define NV40_VP_SRC_SWZ_W_SHIFT 8
+#define NV40_VP_SRC_SWZ_W_MASK (3 << 8)
+#define NV40_VP_SRC_SWZ_ALL_SHIFT 8
+#define NV40_VP_SRC_SWZ_ALL_MASK (0xFF << 8)
+#define NV40_VP_SRC_TEMP_SRC_SHIFT 2
+#define NV40_VP_SRC_TEMP_SRC_MASK (0x1F << 2)
+#define NV40_VP_SRC_REG_TYPE_SHIFT 0
+#define NV40_VP_SRC_REG_TYPE_MASK (3 << 0)
+# define NV40_VP_SRC_REG_TYPE_UNK0 0
+# define NV40_VP_SRC_REG_TYPE_TEMP 1
+# define NV40_VP_SRC_REG_TYPE_INPUT 2
+# define NV40_VP_SRC_REG_TYPE_CONST 3
+
+
+/*
+ * Each fragment program opcode appears to be comprised of 4 32-bit values.
+ *
+ * 0 - Opcode, output reg/mask, ATTRIB source
+ * 1 - Source 0
+ * 2 - Source 1
+ * 3 - Source 2
+ *
+ * There appears to be no special difference between result regs and temp regs.
+ * result.color == R0.xyzw
+ * result.depth == R1.z
+ * When the fragprog contains instructions to write depth,
+ * NV30_TCL_PRIMITIVE_3D_UNK1D78=0 otherwise it is set to 1.
+ *
+ * Constants are inserted directly after the instruction that uses them.
+ *
+ * It appears that it's not possible to use two input registers in one
+ * instruction as the input sourcing is done in the instruction dword
+ * and not the source selection dwords. As such instructions such as:
+ *
+ * ADD result.color, fragment.color, fragment.texcoord[0];
+ *
+ * must be split into two MOV's and then an ADD (nvidia does this) but
+ * I'm not sure why it's not just one MOV and then source the second input
+ * in the ADD instruction..
+ *
+ * Negation of the full source is done with NV30_FP_REG_NEGATE, arbitrary
+ * negation requires multiplication with a const.
+ *
+ * Arbitrary swizzling is supported with the exception of SWIZZLE_ZERO and
+ * SWIZZLE_ONE.
+ *
+ * The temp/result regs appear to be initialised to (0.0, 0.0, 0.0, 0.0) as
+ * SWIZZLE_ZERO is implemented simply by not writing to the relevant components
+ * of the destination.
+ *
+ * Looping
+ * Loops appear to be fairly expensive on NV40 at least, the proprietary
+ * driver goes to a lot of effort to avoid using the native looping
+ * instructions. If the total number of *executed* instructions between
+ * REP/ENDREP or LOOP/ENDLOOP is <=500, the driver will unroll the loop.
+ * The maximum loop count is 255.
+ *
+ * Conditional execution
+ * TODO
+ *
+ * Non-native instructions:
+ * LIT
+ * LRP - MAD+MAD
+ * SUB - ADD, negate second source
+ * RSQ - LG2 + EX2
+ * POW - LG2 + MUL + EX2
+ * SCS - COS + SIN
+ * XPD
+ * DP2 - MUL + ADD
+ * NRM
+ */
+
+//== Opcode / Destination selection ==
+#define NV40_FP_OP_PROGRAM_END (1 << 0)
+#define NV40_FP_OP_OUT_REG_SHIFT 1
+#define NV40_FP_OP_OUT_REG_MASK (31 << 1)
+/* Needs to be set when writing outputs to get expected result.. */
+#define NV40_FP_OP_UNK0_7 (1 << 7)
+#define NV40_FP_OP_COND_WRITE_ENABLE (1 << 8)
+#define NV40_FP_OP_OUTMASK_SHIFT 9
+#define NV40_FP_OP_OUTMASK_MASK (0xF << 9)
+# define NV40_FP_OP_OUT_X (1 << 9)
+# define NV40_FP_OP_OUT_Y (1 <<10)
+# define NV40_FP_OP_OUT_Z (1 <<11)
+# define NV40_FP_OP_OUT_W (1 <<12)
+/* Uncertain about these, especially the input_src values.. it's possible that
+ * they can be dynamically changed.
+ */
+#define NV40_FP_OP_INPUT_SRC_SHIFT 13
+#define NV40_FP_OP_INPUT_SRC_MASK (15 << 13)
+# define NV40_FP_OP_INPUT_SRC_POSITION 0x0
+# define NV40_FP_OP_INPUT_SRC_COL0 0x1
+# define NV40_FP_OP_INPUT_SRC_COL1 0x2
+# define NV40_FP_OP_INPUT_SRC_FOGC 0x3
+# define NV40_FP_OP_INPUT_SRC_TC0 0x4
+# define NV40_FP_OP_INPUT_SRC_TC(n) (0x4 + n)
+# define NV40_FP_OP_INPUT_SRC_FACING 0xE
+#define NV40_FP_OP_TEX_UNIT_SHIFT 17
+#define NV40_FP_OP_TEX_UNIT_MASK (0xF << 17)
+#define NV40_FP_OP_PRECISION_SHIFT 22
+#define NV40_FP_OP_PRECISION_MASK (3 << 22)
+# define NV40_FP_PRECISION_FP32 0
+# define NV40_FP_PRECISION_FP16 1
+# define NV40_FP_PRECISION_FX12 2
+#define NV40_FP_OP_OPCODE_SHIFT 24
+#define NV40_FP_OP_OPCODE_MASK (0x3F << 24)
+# define NV40_FP_OP_OPCODE_NOP 0x00
+# define NV40_FP_OP_OPCODE_MOV 0x01
+# define NV40_FP_OP_OPCODE_MUL 0x02
+# define NV40_FP_OP_OPCODE_ADD 0x03
+# define NV40_FP_OP_OPCODE_MAD 0x04
+# define NV40_FP_OP_OPCODE_DP3 0x05
+# define NV40_FP_OP_OPCODE_DP4 0x06
+# define NV40_FP_OP_OPCODE_DST 0x07
+# define NV40_FP_OP_OPCODE_MIN 0x08
+# define NV40_FP_OP_OPCODE_MAX 0x09
+# define NV40_FP_OP_OPCODE_SLT 0x0A
+# define NV40_FP_OP_OPCODE_SGE 0x0B
+# define NV40_FP_OP_OPCODE_SLE 0x0C
+# define NV40_FP_OP_OPCODE_SGT 0x0D
+# define NV40_FP_OP_OPCODE_SNE 0x0E
+# define NV40_FP_OP_OPCODE_SEQ 0x0F
+# define NV40_FP_OP_OPCODE_FRC 0x10
+# define NV40_FP_OP_OPCODE_FLR 0x11
+# define NV40_FP_OP_OPCODE_KIL 0x12
+# define NV40_FP_OP_OPCODE_PK4B 0x13
+# define NV40_FP_OP_OPCODE_UP4B 0x14
+/* DDX/DDY can only write to XY */
+# define NV40_FP_OP_OPCODE_DDX 0x15
+# define NV40_FP_OP_OPCODE_DDY 0x16
+# define NV40_FP_OP_OPCODE_TEX 0x17
+# define NV40_FP_OP_OPCODE_TXP 0x18
+# define NV40_FP_OP_OPCODE_TXD 0x19
+# define NV40_FP_OP_OPCODE_RCP 0x1A
+# define NV40_FP_OP_OPCODE_EX2 0x1C
+# define NV40_FP_OP_OPCODE_LG2 0x1D
+# define NV40_FP_OP_OPCODE_COS 0x22
+# define NV40_FP_OP_OPCODE_SIN 0x23
+# define NV40_FP_OP_OPCODE_PK2H 0x24
+# define NV40_FP_OP_OPCODE_UP2H 0x25
+# define NV40_FP_OP_OPCODE_PK4UB 0x27
+# define NV40_FP_OP_OPCODE_UP4UB 0x28
+# define NV40_FP_OP_OPCODE_PK2US 0x29
+# define NV40_FP_OP_OPCODE_UP2US 0x2A
+# define NV40_FP_OP_OPCODE_DP2A 0x2E
+# define NV40_FP_OP_OPCODE_TXL 0x2F
+# define NV40_FP_OP_OPCODE_TXB 0x31
+# define NV40_FP_OP_OPCODE_DIV 0x3A
+/* The use of these instructions appears to be indicated by bit 31 of DWORD 2.*/
+# define NV40_FP_OP_BRA_OPCODE_BRK 0x0
+# define NV40_FP_OP_BRA_OPCODE_CAL 0x1
+# define NV40_FP_OP_BRA_OPCODE_IF 0x2
+# define NV40_FP_OP_BRA_OPCODE_LOOP 0x3
+# define NV40_FP_OP_BRA_OPCODE_REP 0x4
+# define NV40_FP_OP_BRA_OPCODE_RET 0x5
+#define NV40_FP_OP_OUT_SAT (1 << 31)
+
+/* high order bits of SRC0 */
+#define NV40_FP_OP_OUT_ABS (1 << 29)
+#define NV40_FP_OP_COND_SWZ_W_SHIFT 27
+#define NV40_FP_OP_COND_SWZ_W_MASK (3 << 27)
+#define NV40_FP_OP_COND_SWZ_Z_SHIFT 25
+#define NV40_FP_OP_COND_SWZ_Z_MASK (3 << 25)
+#define NV40_FP_OP_COND_SWZ_Y_SHIFT 23
+#define NV40_FP_OP_COND_SWZ_Y_MASK (3 << 23)
+#define NV40_FP_OP_COND_SWZ_X_SHIFT 21
+#define NV40_FP_OP_COND_SWZ_X_MASK (3 << 21)
+#define NV40_FP_OP_COND_SWZ_ALL_SHIFT 21
+#define NV40_FP_OP_COND_SWZ_ALL_MASK (0xFF << 21)
+#define NV40_FP_OP_COND_SHIFT 18
+#define NV40_FP_OP_COND_MASK (0x07 << 18)
+# define NV40_FP_OP_COND_FL 0
+# define NV40_FP_OP_COND_LT 1
+# define NV40_FP_OP_COND_EQ 2
+# define NV40_FP_OP_COND_LE 3
+# define NV40_FP_OP_COND_GT 4
+# define NV40_FP_OP_COND_NE 5
+# define NV40_FP_OP_COND_GE 6
+# define NV40_FP_OP_COND_TR 7
+
+/* high order bits of SRC1 */
+#define NV40_FP_OP_OPCODE_IS_BRANCH (1<<31)
+#define NV40_FP_OP_SRC_SCALE_SHIFT 28
+#define NV40_FP_OP_SRC_SCALE_MASK (3 << 28)
+
+/* SRC1 LOOP */
+#define NV40_FP_OP_LOOP_INCR_SHIFT 19
+#define NV40_FP_OP_LOOP_INCR_MASK (0xFF << 19)
+#define NV40_FP_OP_LOOP_INDEX_SHIFT 10
+#define NV40_FP_OP_LOOP_INDEX_MASK (0xFF << 10)
+#define NV40_FP_OP_LOOP_COUNT_SHIFT 2
+#define NV40_FP_OP_LOOP_COUNT_MASK (0xFF << 2)
+
+/* SRC1 IF */
+#define NV40_FP_OP_ELSE_ID_SHIFT 2
+#define NV40_FP_OP_ELSE_ID_MASK (0xFF << 2)
+
+/* SRC1 CAL */
+#define NV40_FP_OP_IADDR_SHIFT 2
+#define NV40_FP_OP_IADDR_MASK (0xFF << 2)
+
+/* SRC1 REP
+ * I have no idea why there are 3 count values here.. but they
+ * have always been filled with the same value in my tests so
+ * far..
+ */
+#define NV40_FP_OP_REP_COUNT1_SHIFT 2
+#define NV40_FP_OP_REP_COUNT1_MASK (0xFF << 2)
+#define NV40_FP_OP_REP_COUNT2_SHIFT 10
+#define NV40_FP_OP_REP_COUNT2_MASK (0xFF << 10)
+#define NV40_FP_OP_REP_COUNT3_SHIFT 19
+#define NV40_FP_OP_REP_COUNT3_MASK (0xFF << 19)
+
+/* SRC2 REP/IF */
+#define NV40_FP_OP_END_ID_SHIFT 2
+#define NV40_FP_OP_END_ID_MASK (0xFF << 2)
+
+// SRC2 high-order
+#define NV40_FP_OP_INDEX_INPUT (1 << 30)
+#define NV40_FP_OP_ADDR_INDEX_SHIFT 19
+#define NV40_FP_OP_ADDR_INDEX_MASK (0xF << 19)
+
+//== Register selection ==
+#define NV40_FP_REG_TYPE_SHIFT 0
+#define NV40_FP_REG_TYPE_MASK (3 << 0)
+# define NV40_FP_REG_TYPE_TEMP 0
+# define NV40_FP_REG_TYPE_INPUT 1
+# define NV40_FP_REG_TYPE_CONST 2
+#define NV40_FP_REG_SRC_SHIFT 2
+#define NV40_FP_REG_SRC_MASK (31 << 2)
+#define NV40_FP_REG_UNK_0 (1 << 8)
+#define NV40_FP_REG_SWZ_ALL_SHIFT 9
+#define NV40_FP_REG_SWZ_ALL_MASK (255 << 9)
+#define NV40_FP_REG_SWZ_X_SHIFT 9
+#define NV40_FP_REG_SWZ_X_MASK (3 << 9)
+#define NV40_FP_REG_SWZ_Y_SHIFT 11
+#define NV40_FP_REG_SWZ_Y_MASK (3 << 11)
+#define NV40_FP_REG_SWZ_Z_SHIFT 13
+#define NV40_FP_REG_SWZ_Z_MASK (3 << 13)
+#define NV40_FP_REG_SWZ_W_SHIFT 15
+#define NV40_FP_REG_SWZ_W_MASK (3 << 15)
+# define NV40_FP_SWIZZLE_X 0
+# define NV40_FP_SWIZZLE_Y 1
+# define NV40_FP_SWIZZLE_Z 2
+# define NV40_FP_SWIZZLE_W 3
+#define NV40_FP_REG_NEGATE (1 << 17)
+
+#endif
diff --git a/src/mesa/drivers/dri/nouveau/nv40_vertprog.c b/src/mesa/drivers/dri/nouveau/nv40_vertprog.c
new file mode 100644
index 0000000000..0493e18403
--- /dev/null
+++ b/src/mesa/drivers/dri/nouveau/nv40_vertprog.c
@@ -0,0 +1,685 @@
+#include "nouveau_shader.h"
+#include "nouveau_msg.h"
+#include "nv40_shader.h"
+
+/*****************************************************************************
+ * Assembly routines
+ */
+static int
+NV40VPSupportsOpcode(nvsFunc * shader, nvsOpcode op)
+{
+ if (shader->GetOPTXFromSOP(op, NULL))
+ return 1;
+ return 0;
+}
+
+static void
+NV40VPSetOpcode(nvsFunc *shader, unsigned int opcode, int slot)
+{
+ if (slot) {
+ shader->inst[1] &= ~NV40_VP_INST_SCA_OPCODE_MASK;
+ shader->inst[1] |= (opcode << NV40_VP_INST_SCA_OPCODE_SHIFT);
+ } else {
+ shader->inst[1] &= ~NV40_VP_INST_VEC_OPCODE_MASK;
+ shader->inst[1] |= (opcode << NV40_VP_INST_VEC_OPCODE_SHIFT);
+ }
+}
+
+static void
+NV40VPSetCCUpdate(nvsFunc *shader)
+{
+ shader->inst[0] |= NV40_VP_INST_COND_UPDATE_ENABLE;
+}
+
+static void
+NV40VPSetCondition(nvsFunc *shader, int on, nvsCond cond, int reg,
+ nvsSwzComp *swizzle)
+{
+ unsigned int hwcond;
+
+ if (on ) shader->inst[0] |= NV40_VP_INST_COND_TEST_ENABLE;
+ else shader->inst[0] &= ~NV40_VP_INST_COND_TEST_ENABLE;
+ if (reg) shader->inst[0] |= NV40_VP_INST_COND_REG_SELECT_1;
+ else shader->inst[0] &= ~NV40_VP_INST_COND_REG_SELECT_1;
+
+ switch (cond) {
+ case NVS_COND_TR: hwcond = NV40_VP_INST_COND_TR; break;
+ case NVS_COND_FL: hwcond = NV40_VP_INST_COND_FL; break;
+ case NVS_COND_LT: hwcond = NV40_VP_INST_COND_LT; break;
+ case NVS_COND_GT: hwcond = NV40_VP_INST_COND_GT; break;
+ case NVS_COND_NE: hwcond = NV40_VP_INST_COND_NE; break;
+ case NVS_COND_EQ: hwcond = NV40_VP_INST_COND_EQ; break;
+ case NVS_COND_GE: hwcond = NV40_VP_INST_COND_GE; break;
+ case NVS_COND_LE: hwcond = NV40_VP_INST_COND_LE; break;
+ default:
+ WARN_ONCE("unknown vp cond %d\n", cond);
+ hwcond = NV40_VP_INST_COND_TR;
+ break;
+ }
+ shader->inst[0] &= ~NV40_VP_INST_COND_MASK;
+ shader->inst[0] |= (hwcond << NV40_VP_INST_COND_SHIFT);
+
+ shader->inst[0] &= ~NV40_VP_INST_COND_SWZ_ALL_MASK;
+ shader->inst[0] |= (swizzle[NVS_SWZ_X] << NV40_VP_INST_COND_SWZ_X_SHIFT);
+ shader->inst[0] |= (swizzle[NVS_SWZ_Y] << NV40_VP_INST_COND_SWZ_Y_SHIFT);
+ shader->inst[0] |= (swizzle[NVS_SWZ_Z] << NV40_VP_INST_COND_SWZ_Z_SHIFT);
+ shader->inst[0] |= (swizzle[NVS_SWZ_W] << NV40_VP_INST_COND_SWZ_W_SHIFT);
+}
+
+static void
+NV40VPSetResult(nvsFunc *shader, nvsRegister * dest, unsigned int mask,
+ int slot)
+{
+ unsigned int hwmask = 0;
+
+ if (mask & SMASK_X) hwmask |= (1 << 3);
+ if (mask & SMASK_Y) hwmask |= (1 << 2);
+ if (mask & SMASK_Z) hwmask |= (1 << 1);
+ if (mask & SMASK_W) hwmask |= (1 << 0);
+
+ if (dest->file == NVS_FILE_RESULT) {
+ int hwidx;
+
+ switch (dest->index) {
+ case NVS_FR_POSITION : hwidx = NV40_VP_INST_DEST_POS; break;
+ case NVS_FR_COL0 : hwidx = NV40_VP_INST_DEST_COL0; break;
+ case NVS_FR_COL1 : hwidx = NV40_VP_INST_DEST_COL1; break;
+ case NVS_FR_BFC0 : hwidx = NV40_VP_INST_DEST_BFC0; break;
+ case NVS_FR_BFC1 : hwidx = NV40_VP_INST_DEST_BFC1; break;
+ case NVS_FR_FOGCOORD : hwidx = NV40_VP_INST_DEST_FOGC; break;
+ case NVS_FR_POINTSZ : hwidx = NV40_VP_INST_DEST_PSZ; break;
+ case NVS_FR_TEXCOORD0: hwidx = NV40_VP_INST_DEST_TC(0); break;
+ case NVS_FR_TEXCOORD1: hwidx = NV40_VP_INST_DEST_TC(1); break;
+ case NVS_FR_TEXCOORD2: hwidx = NV40_VP_INST_DEST_TC(2); break;
+ case NVS_FR_TEXCOORD3: hwidx = NV40_VP_INST_DEST_TC(3); break;
+ case NVS_FR_TEXCOORD4: hwidx = NV40_VP_INST_DEST_TC(4); break;
+ case NVS_FR_TEXCOORD5: hwidx = NV40_VP_INST_DEST_TC(5); break;
+ case NVS_FR_TEXCOORD6: hwidx = NV40_VP_INST_DEST_TC(6); break;
+ case NVS_FR_TEXCOORD7: hwidx = NV40_VP_INST_DEST_TC(7); break;
+ default:
+ WARN_ONCE("unknown vtxprog output %d\n", dest->index);
+ hwidx = 0;
+ break;
+ }
+ shader->inst[3] &= ~NV40_VP_INST_DEST_MASK;
+ shader->inst[3] |= (hwidx << NV40_VP_INST_DEST_SHIFT);
+
+ if (slot) shader->inst[3] |= NV40_VP_INST_SCA_RESULT;
+ else shader->inst[0] |= NV40_VP_INST_VEC_RESULT;
+ } else {
+ /* NVS_FILE_TEMP || NVS_FILE_ADDRESS */
+ if (slot) {
+ shader->inst[3] &= ~NV40_VP_INST_SCA_RESULT;
+ shader->inst[3] &= ~NV40_VP_INST_SCA_DEST_TEMP_MASK;
+ shader->inst[3] |= (dest->index << NV40_VP_INST_SCA_DEST_TEMP_SHIFT);
+ } else {
+ shader->inst[0] &= ~NV40_VP_INST_VEC_RESULT;
+ shader->inst[0] &= ~(NV40_VP_INST_VEC_DEST_TEMP_MASK | (1<<20));
+ shader->inst[0] |= (dest->index << NV40_VP_INST_VEC_DEST_TEMP_SHIFT);
+ }
+ }
+
+ if (slot) {
+ shader->inst[3] &= ~NV40_VP_INST_SCA_WRITEMASK_MASK;
+ shader->inst[3] |= (hwmask << NV40_VP_INST_SCA_WRITEMASK_SHIFT);
+ } else {
+ shader->inst[3] &= ~NV40_VP_INST_VEC_WRITEMASK_MASK;
+ shader->inst[3] |= (hwmask << NV40_VP_INST_VEC_WRITEMASK_SHIFT);
+ }
+}
+
+static void
+NV40VPInsertSource(nvsFunc *shader, unsigned int hw, int pos)
+{
+ switch (pos) {
+ case 0:
+ shader->inst[1] &= ~NV40_VP_INST_SRC0H_MASK;
+ shader->inst[2] &= ~NV40_VP_INST_SRC0L_MASK;
+ shader->inst[1] |= ((hw & NV40_VP_SRC0_HIGH_MASK) >>
+ NV40_VP_SRC0_HIGH_SHIFT)
+ << NV40_VP_INST_SRC0H_SHIFT;
+ shader->inst[2] |= (hw & NV40_VP_SRC0_LOW_MASK)
+ << NV40_VP_INST_SRC0L_SHIFT;
+ break;
+ case 1:
+ shader->inst[2] &= ~NV40_VP_INST_SRC1_MASK;
+ shader->inst[2] |= hw
+ << NV40_VP_INST_SRC1_SHIFT;
+ break;
+ case 2:
+ shader->inst[2] &= ~NV40_VP_INST_SRC2H_MASK;
+ shader->inst[3] &= ~NV40_VP_INST_SRC2L_MASK;
+ shader->inst[2] |= ((hw & NV40_VP_SRC2_HIGH_MASK) >>
+ NV40_VP_SRC2_HIGH_SHIFT)
+ << NV40_VP_INST_SRC2H_SHIFT;
+ shader->inst[3] |= (hw & NV40_VP_SRC2_LOW_MASK)
+ << NV40_VP_INST_SRC2L_SHIFT;
+ break;
+ default:
+ assert(0);
+ break;
+ }
+}
+
+static void
+NV40VPSetSource(nvsFunc *shader, nvsRegister * src, int pos)
+{
+ unsigned int hw = 0;
+
+ switch (src->file) {
+ case NVS_FILE_ADDRESS:
+ break;
+ case NVS_FILE_ATTRIB:
+ hw |= (NV40_VP_SRC_REG_TYPE_INPUT << NV40_VP_SRC_REG_TYPE_SHIFT);
+
+ shader->inst[1] &= ~NV40_VP_INST_INPUT_SRC_MASK;
+ shader->inst[1] |= (src->index << NV40_VP_INST_INPUT_SRC_SHIFT);
+ if (src->indexed) {
+ shader->inst[0] |= NV40_VP_INST_INDEX_INPUT;
+ if (src->addr_reg)
+ shader->inst[0] |= NV40_VP_INST_ADDR_REG_SELECT_1;
+ else
+ shader->inst[0] &= ~NV40_VP_INST_ADDR_REG_SELECT_1;
+ shader->inst[0] &= ~NV40_VP_INST_ADDR_SWZ_SHIFT;
+ shader->inst[0] |= (src->addr_comp << NV40_VP_INST_ADDR_SWZ_SHIFT);
+ } else
+ shader->inst[0] &= ~NV40_VP_INST_INDEX_INPUT;
+ break;
+ case NVS_FILE_CONST:
+ hw |= (NV40_VP_SRC_REG_TYPE_CONST << NV40_VP_SRC_REG_TYPE_SHIFT);
+
+ shader->inst[1] &= ~NV40_VP_INST_CONST_SRC_MASK;
+ shader->inst[1] |= (src->index << NV40_VP_INST_CONST_SRC_SHIFT);
+ if (src->indexed) {
+ shader->inst[3] |= NV40_VP_INST_INDEX_CONST;
+ if (src->addr_reg)
+ shader->inst[0] |= NV40_VP_INST_ADDR_REG_SELECT_1;
+ else
+ shader->inst[0] &= ~NV40_VP_INST_ADDR_REG_SELECT_1;
+ shader->inst[0] &= ~NV40_VP_INST_ADDR_SWZ_MASK;
+ shader->inst[0] |= (src->addr_comp << NV40_VP_INST_ADDR_SWZ_SHIFT);
+ } else
+ shader->inst[3] &= ~NV40_VP_INST_INDEX_CONST;
+ break;
+ case NVS_FILE_TEMP:
+ hw |= (NV40_VP_SRC_REG_TYPE_TEMP << NV40_VP_SRC_REG_TYPE_SHIFT);
+ hw |= (src->index << NV40_VP_SRC_TEMP_SRC_SHIFT);
+ break;
+ default:
+ fprintf(stderr, "unknown source file %d\n", src->file);
+ assert(0);
+ break;
+ }
+
+ if (src->file != NVS_FILE_ADDRESS) {
+ if (src->negate)
+ hw |= NV40_VP_SRC_NEGATE;
+ if (src->abs)
+ shader->inst[0] |= (1 << (21 + pos));
+ else
+ shader->inst[0] &= ~(1 << (21 + pos));
+ hw |= (src->swizzle[0] << NV40_VP_SRC_SWZ_X_SHIFT);
+ hw |= (src->swizzle[1] << NV40_VP_SRC_SWZ_Y_SHIFT);
+ hw |= (src->swizzle[2] << NV40_VP_SRC_SWZ_Z_SHIFT);
+ hw |= (src->swizzle[3] << NV40_VP_SRC_SWZ_W_SHIFT);
+
+ NV40VPInsertSource(shader, hw, pos);
+ }
+}
+
+static void
+NV40VPInitInstruction(nvsFunc *shader)
+{
+ unsigned int hwsrc = 0;
+
+ shader->inst[0] = /*NV40_VP_INST_VEC_RESULT | */
+ NV40_VP_INST_VEC_DEST_TEMP_MASK | (1<<20);
+ shader->inst[1] = 0;
+ shader->inst[2] = 0;
+ shader->inst[3] = NV40_VP_INST_SCA_RESULT |
+ NV40_VP_INST_SCA_DEST_TEMP_MASK |
+ NV40_VP_INST_DEST_MASK;
+
+ hwsrc = (NV40_VP_SRC_REG_TYPE_INPUT << NV40_VP_SRC_REG_TYPE_SHIFT) |
+ (NVS_SWZ_X << NV40_VP_SRC_SWZ_X_SHIFT) |
+ (NVS_SWZ_Y << NV40_VP_SRC_SWZ_Y_SHIFT) |
+ (NVS_SWZ_Z << NV40_VP_SRC_SWZ_Z_SHIFT) |
+ (NVS_SWZ_W << NV40_VP_SRC_SWZ_W_SHIFT);
+ NV40VPInsertSource(shader, hwsrc, 0);
+ NV40VPInsertSource(shader, hwsrc, 1);
+ NV40VPInsertSource(shader, hwsrc, 2);
+}
+
+static void
+NV40VPSetLastInst(nvsFunc *shader)
+{
+ shader->inst[3] |= 1;
+}
+
+/*****************************************************************************
+ * Disassembly routines
+ */
+static int
+NV40VPHasMergedInst(nvsFunc * shader)
+{
+ if (shader->GetOpcodeHW(shader, 0) != NV40_VP_INST_OP_NOP &&
+ shader->GetOpcodeHW(shader, 1) != NV40_VP_INST_OP_NOP)
+ return 1;
+ return 0;
+}
+
+static unsigned int
+NV40VPGetOpcodeHW(nvsFunc * shader, int slot)
+{
+ int op;
+
+ if (slot)
+ op = (shader->inst[1] & NV40_VP_INST_SCA_OPCODE_MASK)
+ >> NV40_VP_INST_SCA_OPCODE_SHIFT;
+ else
+ op = (shader->inst[1] & NV40_VP_INST_VEC_OPCODE_MASK)
+ >> NV40_VP_INST_VEC_OPCODE_SHIFT;
+
+ return op;
+}
+
+static nvsRegFile
+NV40VPGetDestFile(nvsFunc * shader, int merged)
+{
+ nvsOpcode op;
+
+ op = shader->GetOpcode(shader, merged);
+ switch (op) {
+ case NVS_OP_ARL:
+ case NVS_OP_ARR:
+ case NVS_OP_ARA:
+ case NVS_OP_POPA:
+ return NVS_FILE_ADDRESS;
+ default:
+ if (shader->GetOpcodeSlot(shader, merged)) {
+ if (shader->inst[3] & NV40_VP_INST_SCA_RESULT)
+ return NVS_FILE_RESULT;
+ }
+ else {
+ if (shader->inst[0] & NV40_VP_INST_VEC_RESULT)
+ return NVS_FILE_RESULT;
+ }
+ return NVS_FILE_TEMP;
+ }
+
+}
+
+static unsigned int
+NV40VPGetDestID(nvsFunc * shader, int merged)
+{
+ int id;
+
+ switch (shader->GetDestFile(shader, merged)) {
+ case NVS_FILE_RESULT:
+ id = ((shader->inst[3] & NV40_VP_INST_DEST_MASK)
+ >> NV40_VP_INST_DEST_SHIFT);
+ switch (id) {
+ case NV40_VP_INST_DEST_POS : return NVS_FR_POSITION;
+ case NV40_VP_INST_DEST_COL0: return NVS_FR_COL0;
+ case NV40_VP_INST_DEST_COL1: return NVS_FR_COL1;
+ case NV40_VP_INST_DEST_BFC0: return NVS_FR_BFC0;
+ case NV40_VP_INST_DEST_BFC1: return NVS_FR_BFC1;
+ case NV40_VP_INST_DEST_FOGC: {
+ int mask = shader->GetDestMask(shader, merged);
+ switch (mask) {
+ case SMASK_X: return NVS_FR_FOGCOORD;
+ case SMASK_Y: return NVS_FR_CLIP0;
+ case SMASK_Z: return NVS_FR_CLIP1;
+ case SMASK_W: return NVS_FR_CLIP2;
+ default:
+ printf("more than 1 mask component set in FOGC writemask!\n");
+ return NVS_FR_UNKNOWN;
+ }
+ }
+ case NV40_VP_INST_DEST_PSZ:
+ {
+ int mask = shader->GetDestMask(shader, merged);
+ switch (mask) {
+ case SMASK_X: return NVS_FR_POINTSZ;
+ case SMASK_Y: return NVS_FR_CLIP3;
+ case SMASK_Z: return NVS_FR_CLIP4;
+ case SMASK_W: return NVS_FR_CLIP5;
+ default:
+ printf("more than 1 mask component set in PSZ writemask!\n");
+ return NVS_FR_UNKNOWN;
+ }
+ }
+ case NV40_VP_INST_DEST_TC(0): return NVS_FR_TEXCOORD0;
+ case NV40_VP_INST_DEST_TC(1): return NVS_FR_TEXCOORD1;
+ case NV40_VP_INST_DEST_TC(2): return NVS_FR_TEXCOORD2;
+ case NV40_VP_INST_DEST_TC(3): return NVS_FR_TEXCOORD3;
+ case NV40_VP_INST_DEST_TC(4): return NVS_FR_TEXCOORD4;
+ case NV40_VP_INST_DEST_TC(5): return NVS_FR_TEXCOORD5;
+ case NV40_VP_INST_DEST_TC(6): return NVS_FR_TEXCOORD6;
+ case NV40_VP_INST_DEST_TC(7): return NVS_FR_TEXCOORD7;
+ default:
+ return -1;
+ }
+ case NVS_FILE_ADDRESS:
+ /* Instructions that write address regs are encoded as if
+ * they would write temps.
+ */
+ case NVS_FILE_TEMP:
+ if (shader->GetOpcodeSlot(shader, merged))
+ id = ((shader->inst[3] & NV40_VP_INST_SCA_DEST_TEMP_MASK)
+ >> NV40_VP_INST_SCA_DEST_TEMP_SHIFT);
+ else
+ id = ((shader->inst[0] & NV40_VP_INST_VEC_DEST_TEMP_MASK)
+ >> NV40_VP_INST_VEC_DEST_TEMP_SHIFT);
+ return id;
+ default:
+ return -1;
+ }
+}
+
+static unsigned int
+NV40VPGetDestMask(nvsFunc * shader, int merged)
+{
+ unsigned int mask = 0;
+
+ if (shader->GetOpcodeSlot(shader, merged)) {
+ if (shader->inst[3] & NV40_VP_INST_SCA_WRITEMASK_X) mask |= SMASK_X;
+ if (shader->inst[3] & NV40_VP_INST_SCA_WRITEMASK_Y) mask |= SMASK_Y;
+ if (shader->inst[3] & NV40_VP_INST_SCA_WRITEMASK_Z) mask |= SMASK_Z;
+ if (shader->inst[3] & NV40_VP_INST_SCA_WRITEMASK_W) mask |= SMASK_W;
+ } else {
+ if (shader->inst[3] & NV40_VP_INST_VEC_WRITEMASK_X) mask |= SMASK_X;
+ if (shader->inst[3] & NV40_VP_INST_VEC_WRITEMASK_Y) mask |= SMASK_Y;
+ if (shader->inst[3] & NV40_VP_INST_VEC_WRITEMASK_Z) mask |= SMASK_Z;
+ if (shader->inst[3] & NV40_VP_INST_VEC_WRITEMASK_W) mask |= SMASK_W;
+ }
+
+ return mask;
+}
+
+static unsigned int
+NV40VPGetSourceHW(nvsFunc * shader, int merged, int pos)
+{
+ struct _op_xlat *opr;
+ unsigned int src;
+
+ opr = shader->GetOPTXRec(shader, merged);
+ if (!opr)
+ return -1;
+
+ switch (opr->srcpos[pos]) {
+ case 0:
+ src = ((shader->inst[1] & NV40_VP_INST_SRC0H_MASK)
+ >> NV40_VP_INST_SRC0H_SHIFT)
+ << NV40_VP_SRC0_HIGH_SHIFT;
+ src |= ((shader->inst[2] & NV40_VP_INST_SRC0L_MASK)
+ >> NV40_VP_INST_SRC0L_SHIFT);
+ break;
+ case 1:
+ src = ((shader->inst[2] & NV40_VP_INST_SRC1_MASK)
+ >> NV40_VP_INST_SRC1_SHIFT);
+ break;
+ case 2:
+ src = ((shader->inst[2] & NV40_VP_INST_SRC2H_MASK)
+ >> NV40_VP_INST_SRC2H_SHIFT)
+ << NV40_VP_SRC2_HIGH_SHIFT;
+ src |= ((shader->inst[3] & NV40_VP_INST_SRC2L_MASK)
+ >> NV40_VP_INST_SRC2L_SHIFT);
+ break;
+ default:
+ src = -1;
+ }
+
+ return src;
+}
+
+static nvsRegFile
+NV40VPGetSourceFile(nvsFunc * shader, int merged, int pos)
+{
+ unsigned int src;
+ struct _op_xlat *opr;
+ int file;
+
+ opr = shader->GetOPTXRec(shader, merged);
+ if (!opr || opr->srcpos[pos] == -1)
+ return -1;
+
+ switch (opr->srcpos[pos]) {
+ case SPOS_ADDRESS: return NVS_FILE_ADDRESS;
+ default:
+ src = shader->GetSourceHW(shader, merged, pos);
+ file = (src & NV40_VP_SRC_REG_TYPE_MASK) >> NV40_VP_SRC_REG_TYPE_SHIFT;
+
+ switch (file) {
+ case NV40_VP_SRC_REG_TYPE_TEMP : return NVS_FILE_TEMP;
+ case NV40_VP_SRC_REG_TYPE_INPUT: return NVS_FILE_ATTRIB;
+ case NV40_VP_SRC_REG_TYPE_CONST: return NVS_FILE_CONST;
+ default:
+ return NVS_FILE_UNKNOWN;
+ }
+ }
+}
+
+static int
+NV40VPGetSourceID(nvsFunc * shader, int merged, int pos)
+{
+ switch (shader->GetSourceFile(shader, merged, pos)) {
+ case NVS_FILE_ATTRIB:
+ switch ((shader->inst[1] & NV40_VP_INST_INPUT_SRC_MASK)
+ >> NV40_VP_INST_INPUT_SRC_SHIFT) {
+ case NV40_VP_INST_IN_POS: return NVS_FR_POSITION;
+ case NV40_VP_INST_IN_WEIGHT: return NVS_FR_WEIGHT;
+ case NV40_VP_INST_IN_NORMAL: return NVS_FR_NORMAL;
+ case NV40_VP_INST_IN_COL0: return NVS_FR_COL0;
+ case NV40_VP_INST_IN_COL1: return NVS_FR_COL1;
+ case NV40_VP_INST_IN_FOGC: return NVS_FR_FOGCOORD;
+ case NV40_VP_INST_IN_TC(0): return NVS_FR_TEXCOORD0;
+ case NV40_VP_INST_IN_TC(1): return NVS_FR_TEXCOORD1;
+ case NV40_VP_INST_IN_TC(2): return NVS_FR_TEXCOORD2;
+ case NV40_VP_INST_IN_TC(3): return NVS_FR_TEXCOORD3;
+ case NV40_VP_INST_IN_TC(4): return NVS_FR_TEXCOORD4;
+ case NV40_VP_INST_IN_TC(5): return NVS_FR_TEXCOORD5;
+ case NV40_VP_INST_IN_TC(6): return NVS_FR_TEXCOORD6;
+ case NV40_VP_INST_IN_TC(7): return NVS_FR_TEXCOORD7;
+ default:
+ return -1;
+ }
+ break;
+ case NVS_FILE_CONST:
+ return ((shader->inst[1] & NV40_VP_INST_CONST_SRC_MASK)
+ >> NV40_VP_INST_CONST_SRC_SHIFT);
+ case NVS_FILE_TEMP:
+ {
+ unsigned int src;
+
+ src = shader->GetSourceHW(shader, merged, pos);
+ return ((src & NV40_VP_SRC_TEMP_SRC_MASK) >>
+ NV40_VP_SRC_TEMP_SRC_SHIFT);
+ }
+ default:
+ return -1;
+ }
+}
+
+static int
+NV40VPGetSourceNegate(nvsFunc * shader, int merged, int pos)
+{
+ unsigned int src;
+
+ src = shader->GetSourceHW(shader, merged, pos);
+
+ if (src == -1)
+ return -1;
+ return ((src & NV40_VP_SRC_NEGATE) ? 1 : 0);
+}
+
+static void
+NV40VPGetSourceSwizzle(nvsFunc * shader, int merged, int pos, nvsSwzComp *swz)
+{
+ unsigned int src;
+ int swzbits;
+
+ src = shader->GetSourceHW(shader, merged, pos);
+ swzbits = (src & NV40_VP_SRC_SWZ_ALL_MASK) >> NV40_VP_SRC_SWZ_ALL_SHIFT;
+ NV20VPTXSwizzle(swzbits, swz);
+}
+
+static int
+NV40VPGetSourceIndexed(nvsFunc * shader, int merged, int pos)
+{
+ switch (shader->GetSourceFile(shader, merged, pos)) {
+ case NVS_FILE_ATTRIB:
+ return ((shader->inst[0] & NV40_VP_INST_INDEX_INPUT) ? 1 : 0);
+ case NVS_FILE_CONST:
+ return ((shader->inst[3] & NV40_VP_INST_INDEX_CONST) ? 1 : 0);
+ default:
+ return 0;
+ }
+}
+
+static nvsSwzComp
+NV40VPGetAddressRegSwizzle(nvsFunc * shader)
+{
+ nvsSwzComp swz;
+
+ swz = NV20VP_TX_SWIZZLE[(shader->inst[0] & NV40_VP_INST_ADDR_SWZ_MASK)
+ >> NV40_VP_INST_ADDR_SWZ_SHIFT];
+ return swz;
+}
+
+static int
+NV40VPSupportsConditional(nvsFunc * shader)
+{
+ /*FIXME: Is this true of all ops? */
+ return 1;
+}
+
+static int
+NV40VPGetConditionUpdate(nvsFunc * shader)
+{
+ return ((shader->inst[0] & NV40_VP_INST_COND_UPDATE_ENABLE) ? 1 : 0);
+}
+
+static int
+NV40VPGetConditionTest(nvsFunc * shader)
+{
+ int op;
+
+ /* The condition test is unconditionally enabled on some
+ * instructions. ie: the condition test bit does *NOT* have
+ * to be set.
+ *
+ * FIXME: check other relevant ops for this situation.
+ */
+ op = shader->GetOpcodeHW(shader, 1);
+ switch (op) {
+ case NV40_VP_INST_OP_BRA:
+ return 1;
+ default:
+ return ((shader->inst[0] & NV40_VP_INST_COND_TEST_ENABLE) ? 1 : 0);
+ }
+}
+
+static nvsCond
+NV40VPGetCondition(nvsFunc * shader)
+{
+ int cond;
+
+ cond = ((shader->inst[0] & NV40_VP_INST_COND_MASK)
+ >> NV40_VP_INST_COND_SHIFT);
+
+ switch (cond) {
+ case NV40_VP_INST_COND_FL: return NVS_COND_FL;
+ case NV40_VP_INST_COND_LT: return NVS_COND_LT;
+ case NV40_VP_INST_COND_EQ: return NVS_COND_EQ;
+ case NV40_VP_INST_COND_LE: return NVS_COND_LE;
+ case NV40_VP_INST_COND_GT: return NVS_COND_GT;
+ case NV40_VP_INST_COND_NE: return NVS_COND_NE;
+ case NV40_VP_INST_COND_GE: return NVS_COND_GE;
+ case NV40_VP_INST_COND_TR: return NVS_COND_TR;
+ default:
+ return NVS_COND_UNKNOWN;
+ }
+}
+
+static void
+NV40VPGetCondRegSwizzle(nvsFunc * shader, nvsSwzComp *swz)
+{
+ int swzbits;
+
+ swzbits = (shader->inst[0] & NV40_VP_INST_COND_SWZ_ALL_MASK)
+ >> NV40_VP_INST_COND_SWZ_ALL_SHIFT;
+ NV20VPTXSwizzle(swzbits, swz);
+}
+
+static int
+NV40VPGetCondRegID(nvsFunc * shader)
+{
+ return ((shader->inst[0] & NV40_VP_INST_COND_REG_SELECT_1) ? 1 : 0);
+}
+
+static int
+NV40VPGetBranch(nvsFunc * shader)
+{
+ int addr;
+
+ addr = ((shader->inst[2] & NV40_VP_INST_IADDRH_MASK)
+ >> NV40_VP_INST_IADDRH_SHIFT) << 3;
+ addr |= ((shader->inst[3] & NV40_VP_INST_IADDRL_MASK)
+ >> NV40_VP_INST_IADDRL_SHIFT);
+ return addr;
+}
+
+void
+NV40VPInitShaderFuncs(nvsFunc * shader)
+{
+ /* Inherit NV30 VP code, we share some of it */
+ NV30VPInitShaderFuncs(shader);
+
+ /* Limits */
+ shader->MaxInst = 4096;
+ shader->MaxAttrib = 16;
+ shader->MaxTemp = 32;
+ shader->MaxAddress = 2;
+ shader->MaxConst = 256;
+ shader->caps = SCAP_SRC_ABS;
+
+ /* Add extra opcodes for NV40+ */
+// MOD_OPCODE(NVVP_TX_VOP, NV40_VP_INST_OP_TXWHAT, NVS_OP_TEX , 0, 4, -1);
+ MOD_OPCODE(NVVP_TX_SOP, NV40_VP_INST_OP_PUSHA, NVS_OP_PUSHA, 3, -1, -1);
+ MOD_OPCODE(NVVP_TX_SOP, NV40_VP_INST_OP_POPA , NVS_OP_POPA , -1, -1, -1);
+
+ shader->InitInstruction = NV40VPInitInstruction;
+ shader->SupportsOpcode = NV40VPSupportsOpcode;
+ shader->SetOpcode = NV40VPSetOpcode;
+ shader->SetCCUpdate = NV40VPSetCCUpdate;
+ shader->SetCondition = NV40VPSetCondition;
+ shader->SetResult = NV40VPSetResult;
+ shader->SetSource = NV40VPSetSource;
+ shader->SetLastInst = NV40VPSetLastInst;
+
+ shader->HasMergedInst = NV40VPHasMergedInst;
+ shader->GetOpcodeHW = NV40VPGetOpcodeHW;
+
+ shader->GetDestFile = NV40VPGetDestFile;
+ shader->GetDestID = NV40VPGetDestID;
+ shader->GetDestMask = NV40VPGetDestMask;
+
+ shader->GetSourceHW = NV40VPGetSourceHW;
+ shader->GetSourceFile = NV40VPGetSourceFile;
+ shader->GetSourceID = NV40VPGetSourceID;
+ shader->GetSourceNegate = NV40VPGetSourceNegate;
+ shader->GetSourceSwizzle = NV40VPGetSourceSwizzle;
+ shader->GetSourceIndexed = NV40VPGetSourceIndexed;
+
+ shader->GetRelAddressSwizzle = NV40VPGetAddressRegSwizzle;
+
+ shader->SupportsConditional = NV40VPSupportsConditional;
+ shader->GetConditionUpdate = NV40VPGetConditionUpdate;
+ shader->GetConditionTest = NV40VPGetConditionTest;
+ shader->GetCondition = NV40VPGetCondition;
+ shader->GetCondRegSwizzle = NV40VPGetCondRegSwizzle;
+ shader->GetCondRegID = NV40VPGetCondRegID;
+
+ shader->GetBranch = NV40VPGetBranch;
+}