Import a classic DRI driver for nv0x-nv2x.
authorFrancisco Jerez <currojerez@riseup.net>
Mon, 1 Feb 2010 00:19:10 +0000 (01:19 +0100)
committerFrancisco Jerez <currojerez@riseup.net>
Thu, 4 Feb 2010 21:14:39 +0000 (22:14 +0100)
55 files changed:
src/mesa/drivers/dri/nouveau/Makefile [new file with mode: 0644]
src/mesa/drivers/dri/nouveau/nouveau_bo_state.c [new file with mode: 0644]
src/mesa/drivers/dri/nouveau/nouveau_bo_state.h [new file with mode: 0644]
src/mesa/drivers/dri/nouveau/nouveau_bufferobj.c [new file with mode: 0644]
src/mesa/drivers/dri/nouveau/nouveau_bufferobj.h [new file with mode: 0644]
src/mesa/drivers/dri/nouveau/nouveau_context.c [new file with mode: 0644]
src/mesa/drivers/dri/nouveau/nouveau_context.h [new file with mode: 0644]
src/mesa/drivers/dri/nouveau/nouveau_driver.c [new file with mode: 0644]
src/mesa/drivers/dri/nouveau/nouveau_driver.h [new file with mode: 0644]
src/mesa/drivers/dri/nouveau/nouveau_fbo.c [new file with mode: 0644]
src/mesa/drivers/dri/nouveau/nouveau_fbo.h [new file with mode: 0644]
src/mesa/drivers/dri/nouveau/nouveau_gldefs.h [new file with mode: 0644]
src/mesa/drivers/dri/nouveau/nouveau_render.h [new file with mode: 0644]
src/mesa/drivers/dri/nouveau/nouveau_render_t.c [new file with mode: 0644]
src/mesa/drivers/dri/nouveau/nouveau_screen.c [new file with mode: 0644]
src/mesa/drivers/dri/nouveau/nouveau_screen.h [new file with mode: 0644]
src/mesa/drivers/dri/nouveau/nouveau_span.c [new file with mode: 0644]
src/mesa/drivers/dri/nouveau/nouveau_state.c [new file with mode: 0644]
src/mesa/drivers/dri/nouveau/nouveau_state.h [new file with mode: 0644]
src/mesa/drivers/dri/nouveau/nouveau_surface.c [new file with mode: 0644]
src/mesa/drivers/dri/nouveau/nouveau_surface.h [new file with mode: 0644]
src/mesa/drivers/dri/nouveau/nouveau_swtnl_t.c [new file with mode: 0644]
src/mesa/drivers/dri/nouveau/nouveau_texture.c [new file with mode: 0644]
src/mesa/drivers/dri/nouveau/nouveau_texture.h [new file with mode: 0644]
src/mesa/drivers/dri/nouveau/nouveau_util.h [new file with mode: 0644]
src/mesa/drivers/dri/nouveau/nouveau_vbo_t.c [new file with mode: 0644]
src/mesa/drivers/dri/nouveau/nv04_context.c [new file with mode: 0644]
src/mesa/drivers/dri/nouveau/nv04_context.h [new file with mode: 0644]
src/mesa/drivers/dri/nouveau/nv04_driver.h [new file with mode: 0644]
src/mesa/drivers/dri/nouveau/nv04_render.c [new file with mode: 0644]
src/mesa/drivers/dri/nouveau/nv04_screen.c [new file with mode: 0644]
src/mesa/drivers/dri/nouveau/nv04_state_fb.c [new file with mode: 0644]
src/mesa/drivers/dri/nouveau/nv04_state_frag.c [new file with mode: 0644]
src/mesa/drivers/dri/nouveau/nv04_state_raster.c [new file with mode: 0644]
src/mesa/drivers/dri/nouveau/nv04_state_tex.c [new file with mode: 0644]
src/mesa/drivers/dri/nouveau/nv04_surface.c [new file with mode: 0644]
src/mesa/drivers/dri/nouveau/nv10_context.c [new file with mode: 0644]
src/mesa/drivers/dri/nouveau/nv10_driver.h [new file with mode: 0644]
src/mesa/drivers/dri/nouveau/nv10_render.c [new file with mode: 0644]
src/mesa/drivers/dri/nouveau/nv10_screen.c [new file with mode: 0644]
src/mesa/drivers/dri/nouveau/nv10_state_fb.c [new file with mode: 0644]
src/mesa/drivers/dri/nouveau/nv10_state_frag.c [new file with mode: 0644]
src/mesa/drivers/dri/nouveau/nv10_state_polygon.c [new file with mode: 0644]
src/mesa/drivers/dri/nouveau/nv10_state_raster.c [new file with mode: 0644]
src/mesa/drivers/dri/nouveau/nv10_state_tex.c [new file with mode: 0644]
src/mesa/drivers/dri/nouveau/nv10_state_tnl.c [new file with mode: 0644]
src/mesa/drivers/dri/nouveau/nv20_context.c [new file with mode: 0644]
src/mesa/drivers/dri/nouveau/nv20_driver.h [new file with mode: 0644]
src/mesa/drivers/dri/nouveau/nv20_render.c [new file with mode: 0644]
src/mesa/drivers/dri/nouveau/nv20_screen.c [new file with mode: 0644]
src/mesa/drivers/dri/nouveau/nv20_state_fb.c [new file with mode: 0644]
src/mesa/drivers/dri/nouveau/nv20_state_polygon.c [new file with mode: 0644]
src/mesa/drivers/dri/nouveau/nv20_state_raster.c [new file with mode: 0644]
src/mesa/drivers/dri/nouveau/nv20_state_tex.c [new file with mode: 0644]
src/mesa/drivers/dri/nouveau/nv20_state_tnl.c [new file with mode: 0644]

diff --git a/src/mesa/drivers/dri/nouveau/Makefile b/src/mesa/drivers/dri/nouveau/Makefile
new file mode 100644 (file)
index 0000000..7c895a2
--- /dev/null
@@ -0,0 +1,59 @@
+# src/mesa/drivers/dri/nouveau/Makefile
+
+TOP = ../../../../..
+include $(TOP)/configs/current
+
+CFLAGS += $(shell pkg-config libdrm libdrm_nouveau --cflags)
+DRI_LIB_DEPS += $(shell pkg-config libdrm_nouveau --libs)
+
+LIBNAME = nouveau_vieux_dri.so
+
+MINIGLX_SOURCES =
+
+DRIVER_SOURCES = \
+       nouveau_screen.c \
+       nouveau_context.c \
+       nouveau_fbo.c \
+       nouveau_driver.c \
+       nouveau_state.c \
+       nouveau_bufferobj.c \
+       nouveau_span.c \
+       nouveau_bo_state.c \
+       nouveau_texture.c \
+       nouveau_surface.c \
+       nv04_context.c \
+       nv04_screen.c \
+       nv04_render.c \
+       nv04_state_fb.c \
+       nv04_state_raster.c \
+       nv04_state_tex.c \
+       nv04_state_frag.c \
+       nv04_surface.c \
+       nv10_context.c \
+       nv10_screen.c \
+       nv10_render.c \
+       nv10_state_fb.c \
+       nv10_state_polygon.c \
+       nv10_state_raster.c \
+       nv10_state_tex.c \
+       nv10_state_frag.c \
+       nv10_state_tnl.c \
+       nv20_context.c \
+       nv20_screen.c \
+       nv20_render.c \
+       nv20_state_fb.c \
+       nv20_state_polygon.c \
+       nv20_state_raster.c \
+       nv20_state_tex.c \
+       nv20_state_tnl.c
+
+C_SOURCES = \
+       $(COMMON_SOURCES) \
+       $(DRIVER_SOURCES)
+
+ASM_SOURCES =
+
+
+include ../Makefile.template
+
+symlinks:
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_bo_state.c b/src/mesa/drivers/dri/nouveau/nouveau_bo_state.c
new file mode 100644 (file)
index 0000000..664632f
--- /dev/null
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2009 Francisco Jerez.
+ * 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.
+ *
+ */
+
+#include "nouveau_driver.h"
+#include "nouveau_context.h"
+
+static GLboolean
+nouveau_bo_marker_emit(GLcontext *ctx, struct nouveau_bo_marker *m,
+                      uint32_t flags)
+{
+       struct nouveau_channel *chan = context_chan(ctx);
+       struct nouveau_pushbuf *push = chan->pushbuf;
+       uint32_t packet;
+
+       if (m->gr->bound == NOUVEAU_GROBJ_UNBOUND)
+               nouveau_grobj_autobind(m->gr);
+
+       if (MARK_RING(chan, 2, 2))
+               return GL_FALSE;
+
+       push->remaining -= 2;
+       packet = (m->gr->subc << 13) | (1 << 18) | m->mthd;
+
+       if (flags) {
+               if (nouveau_pushbuf_emit_reloc(chan, push->cur++, m->bo,
+                                              packet, 0, flags |
+                                              (m->flags & (NOUVEAU_BO_VRAM |
+                                                           NOUVEAU_BO_GART |
+                                                           NOUVEAU_BO_RDWR)),
+                                              0, 0))
+                       goto fail;
+       } else {
+               *(push->cur++) = packet;
+       }
+
+       if (nouveau_pushbuf_emit_reloc(chan, push->cur++, m->bo, m->data,
+                                      m->data2, flags | m->flags,
+                                      m->vor, m->tor))
+               goto fail;
+
+       return GL_TRUE;
+
+fail:
+       MARK_UNDO(chan);
+       return GL_FALSE;
+}
+
+static GLboolean
+nouveau_bo_context_grow(struct nouveau_bo_context *bctx)
+{
+       struct nouveau_bo_marker *marker = bctx->marker;
+       int allocated = bctx->allocated + 1;
+
+       marker = realloc(marker, allocated * sizeof(struct nouveau_bo_marker));
+       if (!marker)
+               return GL_FALSE;
+
+       bctx->marker = marker;
+       bctx->allocated = allocated;
+
+       return GL_TRUE;
+}
+
+GLboolean
+nouveau_bo_mark(struct nouveau_bo_context *bctx, struct nouveau_grobj *gr,
+               uint32_t mthd, struct nouveau_bo *bo,
+               uint32_t data, uint32_t data2, uint32_t vor, uint32_t tor,
+               uint32_t flags)
+{
+       struct nouveau_bo_state *s = &to_nouveau_context(bctx->ctx)->bo;
+       struct nouveau_bo_marker *m;
+
+       if (bctx->count == bctx->allocated) {
+               if (!nouveau_bo_context_grow(bctx))
+                       goto fail;
+       }
+
+       m = &bctx->marker[bctx->count];
+
+       *m = (struct nouveau_bo_marker) {
+               .gr = gr,
+               .mthd = mthd,
+               .data = data,
+               .data2 = data2,
+               .vor = vor,
+               .tor = tor,
+               .flags = flags,
+       };
+       nouveau_bo_ref(bo, &m->bo);
+
+       s->count++;
+       bctx->count++;
+
+       if (!nouveau_bo_marker_emit(bctx->ctx, m, 0))
+               goto fail;
+
+       return GL_TRUE;
+
+fail:
+       nouveau_bo_context_reset(bctx);
+       return GL_FALSE;
+}
+
+void
+nouveau_bo_context_reset(struct nouveau_bo_context *bctx)
+{
+       struct nouveau_bo_state *s = &to_nouveau_context(bctx->ctx)->bo;
+       int i;
+
+       for (i = 0; i < bctx->count; i++)
+               nouveau_bo_ref(NULL, &bctx->marker[i].bo);
+
+       s->count -= bctx->count;
+       bctx->count = 0;
+}
+
+GLboolean
+nouveau_bo_state_emit(GLcontext *ctx)
+{
+       struct nouveau_bo_state *s = &to_nouveau_context(ctx)->bo;
+       int i, j;
+
+       for (i = 0; i < NUM_NOUVEAU_BO_CONTEXT; i++) {
+               struct nouveau_bo_context *bctx = &s->context[i];
+
+               for (j = 0; j < bctx->count; j++) {
+                       if (!nouveau_bo_marker_emit(ctx, &bctx->marker[j],
+                                                   NOUVEAU_BO_DUMMY))
+                               return GL_FALSE;
+               }
+       }
+
+       return GL_TRUE;
+}
+
+void
+nouveau_bo_state_init(GLcontext *ctx)
+{
+       struct nouveau_bo_state *s = &to_nouveau_context(ctx)->bo;
+       int i;
+
+       for (i = 0; i < NUM_NOUVEAU_BO_CONTEXT; i++)
+               s->context[i].ctx = ctx;
+}
+
+void
+nouveau_bo_state_destroy(GLcontext *ctx)
+{
+       struct nouveau_bo_state *s = &to_nouveau_context(ctx)->bo;
+       int i, j;
+
+       for (i = 0; i < NUM_NOUVEAU_BO_CONTEXT; i++) {
+               struct nouveau_bo_context *bctx = &s->context[i];
+
+               for (j = 0; j < bctx->count; j++)
+                       nouveau_bo_ref(NULL, &bctx->marker[j].bo);
+
+               if (bctx->marker)
+                       free(bctx->marker);
+       }
+}
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_bo_state.h b/src/mesa/drivers/dri/nouveau/nouveau_bo_state.h
new file mode 100644 (file)
index 0000000..da0a3a5
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2009 Francisco Jerez.
+ * 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.
+ *
+ */
+
+#ifndef __NOUVEAU_BO_STATE_H__
+#define __NOUVEAU_BO_STATE_H__
+
+enum {
+       NOUVEAU_BO_CONTEXT_FRAMEBUFFER = 0,
+       NOUVEAU_BO_CONTEXT_LMA_DEPTH,
+       NOUVEAU_BO_CONTEXT_SURFACE,
+       NOUVEAU_BO_CONTEXT_TEXTURE0,
+       NOUVEAU_BO_CONTEXT_TEXTURE1,
+       NOUVEAU_BO_CONTEXT_TEXTURE2,
+       NOUVEAU_BO_CONTEXT_TEXTURE3,
+       NOUVEAU_BO_CONTEXT_VERTEX,
+       NUM_NOUVEAU_BO_CONTEXT
+};
+
+struct nouveau_bo_marker {
+       struct nouveau_grobj *gr;
+       uint32_t mthd;
+
+       struct nouveau_bo *bo;
+       uint32_t data;
+       uint32_t data2;
+       uint32_t vor;
+       uint32_t tor;
+       uint32_t flags;
+};
+
+struct nouveau_bo_context {
+       GLcontext *ctx;
+
+       struct nouveau_bo_marker *marker;
+       int allocated;
+       int count;
+};
+
+struct nouveau_bo_state {
+       struct nouveau_bo_context context[NUM_NOUVEAU_BO_CONTEXT];
+       int count;
+};
+
+GLboolean
+nouveau_bo_mark(struct nouveau_bo_context *bctx, struct nouveau_grobj *gr,
+               uint32_t mthd, struct nouveau_bo *bo,
+               uint32_t data, uint32_t data2, uint32_t vor, uint32_t tor,
+               uint32_t flags);
+
+#define nouveau_bo_markl(bctx, gr, mthd, bo, data, flags)              \
+       nouveau_bo_mark(bctx, gr, mthd, bo, data, 0, 0, 0,              \
+                       flags | NOUVEAU_BO_LOW);
+
+#define nouveau_bo_marko(bctx, gr, mthd, bo, flags)                    \
+       nouveau_bo_mark(bctx, gr, mthd, bo, 0, 0,                       \
+                       context_chan(ctx)->vram->handle,                \
+                       context_chan(ctx)->gart->handle,                \
+                       flags | NOUVEAU_BO_OR);
+
+void
+nouveau_bo_context_reset(struct nouveau_bo_context *bctx);
+
+GLboolean
+nouveau_bo_state_emit(GLcontext *ctx);
+
+void
+nouveau_bo_state_init(GLcontext *ctx);
+
+void
+nouveau_bo_state_destroy(GLcontext *ctx);
+
+#define __context_bctx(ctx, i)                                         \
+       ({                                                              \
+               struct nouveau_context *nctx = to_nouveau_context(ctx); \
+               struct nouveau_bo_context *bctx = &nctx->bo.context[i]; \
+               nouveau_bo_context_reset(bctx);                         \
+               bctx;                                                   \
+       })
+#define context_bctx(ctx, s) \
+       __context_bctx(ctx, NOUVEAU_BO_CONTEXT_##s)
+#define context_bctx_i(ctx, s, i) \
+       __context_bctx(ctx, NOUVEAU_BO_CONTEXT_##s##0 + (i))
+
+#endif
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_bufferobj.c b/src/mesa/drivers/dri/nouveau/nouveau_bufferobj.c
new file mode 100644 (file)
index 0000000..1118b96
--- /dev/null
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2009 Francisco Jerez.
+ * 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.
+ *
+ */
+
+#include "nouveau_driver.h"
+#include "nouveau_bufferobj.h"
+#include "nouveau_context.h"
+
+#include "main/bufferobj.h"
+
+static struct gl_buffer_object *
+nouveau_bufferobj_new(GLcontext *ctx, GLuint buffer, GLenum target)
+{
+       struct nouveau_bufferobj *nbo;
+
+       nbo = CALLOC_STRUCT(nouveau_bufferobj);
+       if (!nbo)
+               return NULL;
+
+       _mesa_initialize_buffer_object(&nbo->base, buffer, target);
+
+       return &nbo->base;
+}
+
+static void
+nouveau_bufferobj_del(GLcontext *ctx, struct gl_buffer_object *obj)
+{
+       struct nouveau_bufferobj *nbo = to_nouveau_bufferobj(obj);
+
+       nouveau_bo_ref(NULL, &nbo->bo);
+       FREE(nbo);
+}
+
+static GLboolean
+nouveau_bufferobj_data(GLcontext *ctx, GLenum target, GLsizeiptrARB size,
+                      const GLvoid *data, GLenum usage,
+                      struct gl_buffer_object *obj)
+{
+       struct nouveau_bufferobj *nbo = to_nouveau_bufferobj(obj);
+       int ret;
+
+       obj->Size = size;
+       obj->Usage = usage;
+
+       nouveau_bo_ref(NULL, &nbo->bo);
+       ret = nouveau_bo_new(context_dev(ctx),
+                            NOUVEAU_BO_GART | NOUVEAU_BO_MAP, 0,
+                            size, &nbo->bo);
+       assert(!ret);
+
+       if (data) {
+               nouveau_bo_map(nbo->bo, NOUVEAU_BO_WR);
+               _mesa_memcpy(nbo->bo->map, data, size);
+               nouveau_bo_unmap(nbo->bo);
+       }
+
+       return GL_TRUE;
+}
+
+static void
+nouveau_bufferobj_subdata(GLcontext *ctx, GLenum target, GLintptrARB offset,
+                         GLsizeiptrARB size, const GLvoid *data,
+                         struct gl_buffer_object *obj)
+{
+       struct nouveau_bufferobj *nbo = to_nouveau_bufferobj(obj);
+
+       nouveau_bo_map(nbo->bo, NOUVEAU_BO_WR);
+       _mesa_memcpy(nbo->bo->map + offset, data, size);
+       nouveau_bo_unmap(nbo->bo);
+}
+
+static void
+nouveau_bufferobj_get_subdata(GLcontext *ctx, GLenum target, GLintptrARB offset,
+                          GLsizeiptrARB size, GLvoid *data,
+                          struct gl_buffer_object *obj)
+{
+       struct nouveau_bufferobj *nbo = to_nouveau_bufferobj(obj);
+
+       nouveau_bo_map(nbo->bo, NOUVEAU_BO_RD);
+       _mesa_memcpy(data, nbo->bo->map + offset, size);
+       nouveau_bo_unmap(nbo->bo);
+}
+
+static void *
+nouveau_bufferobj_map(GLcontext *ctx, GLenum target, GLenum access,
+                  struct gl_buffer_object *obj)
+{
+       return ctx->Driver.MapBufferRange(ctx, target, 0, obj->Size, access,
+                                         obj);
+}
+
+static void *
+nouveau_bufferobj_map_range(GLcontext *ctx, GLenum target, GLintptr offset,
+                           GLsizeiptr length, GLenum access,
+                           struct gl_buffer_object *obj)
+{
+       struct nouveau_bufferobj *nbo = to_nouveau_bufferobj(obj);
+       uint32_t flags = 0;
+
+       assert(!obj->Pointer);
+
+       if (!nbo->bo)
+               return NULL;
+
+       if (access == GL_READ_ONLY_ARB ||
+           access == GL_READ_WRITE_ARB)
+               flags |= NOUVEAU_BO_RD;
+       if (access == GL_WRITE_ONLY_ARB ||
+           access == GL_READ_WRITE_ARB)
+               flags |= NOUVEAU_BO_WR;
+
+       nouveau_bo_map_range(nbo->bo, offset, length, flags);
+
+       obj->Pointer = nbo->bo->map;
+       obj->Offset = offset;
+       obj->Length = length;
+       obj->AccessFlags = access;
+
+       return obj->Pointer;
+}
+
+static GLboolean
+nouveau_bufferobj_unmap(GLcontext *ctx, GLenum target, struct gl_buffer_object *obj)
+{
+       struct nouveau_bufferobj *nbo = to_nouveau_bufferobj(obj);
+
+       assert(obj->Pointer);
+
+       nouveau_bo_unmap(nbo->bo);
+
+       obj->Pointer = NULL;
+       obj->Offset = 0;
+       obj->Length = 0;
+       obj->AccessFlags = 0;
+
+       return GL_TRUE;
+}
+
+void
+nouveau_bufferobj_functions_init(struct dd_function_table *functions)
+{
+       functions->NewBufferObject = nouveau_bufferobj_new;
+       functions->DeleteBuffer = nouveau_bufferobj_del;
+       functions->BufferData = nouveau_bufferobj_data;
+       functions->BufferSubData = nouveau_bufferobj_subdata;
+       functions->GetBufferSubData = nouveau_bufferobj_get_subdata;
+       functions->MapBuffer = nouveau_bufferobj_map;
+       functions->MapBufferRange = nouveau_bufferobj_map_range;
+       functions->UnmapBuffer = nouveau_bufferobj_unmap;
+}
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_bufferobj.h b/src/mesa/drivers/dri/nouveau/nouveau_bufferobj.h
new file mode 100644 (file)
index 0000000..acfc4cb
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2009 Francisco Jerez.
+ * 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.
+ *
+ */
+
+#ifndef __NOUVEAU_BUFFEROBJ_H__
+#define __NOUVEAU_BUFFEROBJ_H__
+
+struct nouveau_bufferobj {
+       struct gl_buffer_object base;
+       struct nouveau_bo *bo;
+};
+#define to_nouveau_bufferobj(x) ((struct nouveau_bufferobj *)(x))
+
+void
+nouveau_bufferobj_functions_init(struct dd_function_table *functions);
+
+#endif
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_context.c b/src/mesa/drivers/dri/nouveau/nouveau_context.c
new file mode 100644 (file)
index 0000000..b87b8db
--- /dev/null
@@ -0,0 +1,273 @@
+/*
+ * Copyright (C) 2009 Francisco Jerez.
+ * 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.
+ *
+ */
+
+#include "nouveau_driver.h"
+#include "nouveau_context.h"
+#include "nouveau_bufferobj.h"
+#include "nouveau_fbo.h"
+
+#include "main/dd.h"
+#include "main/framebuffer.h"
+#include "main/light.h"
+#include "main/state.h"
+#include "drivers/common/meta.h"
+#include "drivers/common/driverfuncs.h"
+#include "swrast/swrast.h"
+#include "vbo/vbo.h"
+#include "tnl/tnl.h"
+
+#define need_GL_EXT_framebuffer_object
+#define need_GL_EXT_fog_coord
+
+#include "main/remap_helper.h"
+
+static const struct dri_extension nouveau_extensions[] = {
+       { "GL_EXT_framebuffer_object",  GL_EXT_framebuffer_object_functions },
+       { "GL_ARB_multitexture",        NULL },
+       { "GL_EXT_texture_lod_bias",    NULL },
+       { "GL_SGIS_generate_mipmap",    NULL },
+       { "GL_ARB_texture_env_combine", NULL },
+       { "GL_ARB_texture_env_dot3",    NULL },
+       { "GL_ARB_texture_env_add",     NULL },
+       { "GL_EXT_fog_coord",           GL_EXT_fog_coord_functions },
+       { NULL,                         NULL }
+};
+
+GLboolean
+nouveau_context_create(const __GLcontextModes *visual, __DRIcontext *dri_ctx,
+                      void *share_ctx)
+{
+       __DRIscreen *dri_screen = dri_ctx->driScreenPriv;
+       struct nouveau_screen *screen = dri_screen->private;
+       struct nouveau_context *nctx;
+       GLcontext *ctx;
+
+       ctx = screen->driver->context_create(screen, visual, share_ctx);
+       if (!ctx)
+               return GL_FALSE;
+
+       nctx = to_nouveau_context(ctx);
+       nctx->dri_context = dri_ctx;
+       dri_ctx->driverPrivate = ctx;
+
+       return GL_TRUE;
+}
+
+GLboolean
+nouveau_context_init(GLcontext *ctx, struct nouveau_screen *screen,
+                    const GLvisual *visual, GLcontext *share_ctx)
+{
+       struct nouveau_context *nctx = to_nouveau_context(ctx);
+       struct dd_function_table functions;
+
+       nctx->screen = screen;
+       nctx->fallback = HWTNL;
+
+       /* Initialize the function pointers */
+       _mesa_init_driver_functions(&functions);
+       nouveau_driver_functions_init(&functions);
+       nouveau_bufferobj_functions_init(&functions);
+       nouveau_texture_functions_init(&functions);
+       nouveau_fbo_functions_init(&functions);
+
+       /* Initialize the mesa context */
+       _mesa_initialize_context(ctx, visual, share_ctx, &functions, NULL);
+
+       nouveau_state_init(ctx);
+       nouveau_bo_state_init(ctx);
+       _mesa_meta_init(ctx);
+       _swrast_CreateContext(ctx);
+       _vbo_CreateContext(ctx);
+       _tnl_CreateContext(ctx);
+       nouveau_span_functions_init(ctx);
+       _mesa_allow_light_in_model(ctx, GL_FALSE);
+
+       /* Enable any supported extensions */
+       driInitExtensions(ctx, nouveau_extensions, GL_TRUE);
+
+       return GL_TRUE;
+}
+
+void
+nouveau_context_destroy(__DRIcontext *dri_ctx)
+{
+       struct nouveau_context *nctx = dri_ctx->driverPrivate;
+       GLcontext *ctx = &nctx->base;
+
+       if (nctx->screen->context == nctx)
+               nctx->screen->context = NULL;
+
+       _tnl_DestroyContext(ctx);
+       _vbo_DestroyContext(ctx);
+       _swrast_DestroyContext(ctx);
+       _mesa_meta_free(ctx);
+       nouveau_bo_state_destroy(ctx);
+       context_drv(ctx)->context_destroy(ctx);
+}
+
+static void
+nouveau_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable,
+                            unsigned int *stamp)
+{
+       struct nouveau_context *nctx = context->driverPrivate;
+       GLcontext *ctx = &nctx->base;
+       __DRIscreen *screen = context->driScreenPriv;
+       struct gl_framebuffer *fb = drawable->driverPrivate;
+       unsigned int attachments[10];
+       __DRIbuffer *buffers = NULL;
+       int i = 0, count, ret;
+
+       attachments[i++] = __DRI_BUFFER_FRONT_LEFT;
+       if (fb->Visual.doubleBufferMode)
+               attachments[i++] = __DRI_BUFFER_BACK_LEFT;
+       if (fb->Visual.haveDepthBuffer && fb->Visual.haveStencilBuffer)
+               attachments[i++] = __DRI_BUFFER_DEPTH_STENCIL;
+       else if (fb->Visual.haveDepthBuffer)
+               attachments[i++] = __DRI_BUFFER_DEPTH;
+       else if (fb->Visual.haveStencilBuffer)
+               attachments[i++] = __DRI_BUFFER_STENCIL;
+
+       buffers = (*screen->dri2.loader->getBuffers)(drawable,
+                                                    &drawable->w, &drawable->h,
+                                                    attachments, i, &count,
+                                                    drawable->loaderPrivate);
+       if (buffers == NULL)
+               return;
+
+       for (i = 0; i < count; i++) {
+               struct gl_renderbuffer *rb;
+               struct nouveau_surface *s;
+               uint32_t old_handle;
+               int index;
+
+               switch (buffers[i].attachment) {
+               case __DRI_BUFFER_FRONT_LEFT:
+               case __DRI_BUFFER_FAKE_FRONT_LEFT:
+                       index = BUFFER_FRONT_LEFT;
+                       break;
+               case __DRI_BUFFER_BACK_LEFT:
+                       index = BUFFER_BACK_LEFT;
+                       break;
+               case __DRI_BUFFER_DEPTH:
+               case __DRI_BUFFER_DEPTH_STENCIL:
+                       index = BUFFER_DEPTH;
+                       break;
+               case __DRI_BUFFER_STENCIL:
+                       index = BUFFER_STENCIL;
+                       break;
+               default:
+                       assert(0);
+               }
+
+               rb = fb->Attachment[index].Renderbuffer;
+               s = &to_nouveau_renderbuffer(rb)->surface;
+
+               s->width = drawable->w;
+               s->height = drawable->h;
+               s->pitch = buffers[i].pitch;
+               s->cpp = buffers[i].cpp;
+
+               /* Don't bother to reopen the bo if it happens to be
+                * the same. */
+               if (s->bo) {
+                       ret = nouveau_bo_handle_get(s->bo, &old_handle);
+                       assert(!ret);
+               }
+
+               if (!s->bo || old_handle != buffers[i].name) {
+                       nouveau_bo_ref(NULL, &s->bo);
+                       ret = nouveau_bo_handle_ref(context_dev(ctx),
+                                                   buffers[i].name, &s->bo);
+                       assert(!ret);
+
+                       context_dirty(ctx, FRAMEBUFFER);
+               }
+       }
+
+       _mesa_resize_framebuffer(ctx, fb, drawable->w, drawable->h);
+}
+
+GLboolean
+nouveau_context_make_current(__DRIcontext *dri_ctx, __DRIdrawable *dri_draw,
+                            __DRIdrawable *dri_read)
+{
+       if (dri_ctx) {
+               struct nouveau_context *nctx = dri_ctx->driverPrivate;
+               GLcontext *ctx = &nctx->base;
+
+               if (nctx->screen->context != nctx) {
+                       nctx->screen->context = nctx;
+                       BITSET_ONES(nctx->dirty);
+               }
+
+               /* Ask the X server for new renderbuffers. */
+               nouveau_update_renderbuffers(dri_ctx, dri_draw,
+                                            &nctx->drawable.d_stamp);
+               if (dri_draw != dri_read)
+                       nouveau_update_renderbuffers(dri_ctx, dri_read,
+                                                    &nctx->drawable.r_stamp);
+
+               /* Pass it down to mesa. */
+               _mesa_make_current(ctx, dri_draw->driverPrivate,
+                                  dri_read->driverPrivate);
+               _mesa_update_state(ctx);
+
+               FIRE_RING(context_chan(ctx));
+
+       } else {
+               _mesa_make_current(NULL, NULL, NULL);
+       }
+
+       return GL_TRUE;
+}
+
+GLboolean
+nouveau_context_unbind(__DRIcontext *dri_ctx)
+{
+       return GL_TRUE;
+}
+
+void
+nouveau_fallback(GLcontext *ctx, enum nouveau_fallback mode)
+{
+       struct nouveau_context *nctx = to_nouveau_context(ctx);
+
+       nctx->fallback = MAX2(HWTNL, mode);
+
+       if (mode < SWRAST)
+               nouveau_state_emit(ctx);
+       else
+               FIRE_RING(context_chan(ctx));
+}
+
+void
+nouveau_validate_framebuffer(GLcontext *ctx)
+{
+       struct nouveau_context *nctx = to_nouveau_context(ctx);
+
+       /* Someone's planning to draw something really soon. */
+       nctx->drawable.dirty = GL_TRUE;
+}
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_context.h b/src/mesa/drivers/dri/nouveau/nouveau_context.h
new file mode 100644 (file)
index 0000000..9812963
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2009 Francisco Jerez.
+ * 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.
+ *
+ */
+
+#ifndef __NOUVEAU_CONTEXT_H__
+#define __NOUVEAU_CONTEXT_H__
+
+#include "nouveau_screen.h"
+#include "nouveau_state.h"
+#include "nouveau_bo_state.h"
+#include "nouveau_render.h"
+
+#include "main/bitset.h"
+
+enum nouveau_fallback {
+       HWTNL = 0,
+       SWTNL,
+       SWRAST,
+};
+
+struct nouveau_drawable_state {
+       GLboolean dirty;
+       unsigned int d_stamp;
+       unsigned int r_stamp;
+};
+
+struct nouveau_context {
+       GLcontext base;
+       __DRIcontext *dri_context;
+       struct nouveau_screen *screen;
+
+       BITSET_DECLARE(dirty, MAX_NOUVEAU_STATE);
+       enum nouveau_fallback fallback;
+
+       struct nouveau_bo_state bo;
+       struct nouveau_render_state render;
+       struct nouveau_drawable_state drawable;
+};
+
+#define to_nouveau_context(ctx)        ((struct nouveau_context *)(ctx))
+
+#define context_dev(ctx) \
+       (to_nouveau_context(ctx)->screen->device)
+#define context_chipset(ctx) \
+       (context_dev(ctx)->chipset)
+#define context_chan(ctx) \
+       (to_nouveau_context(ctx)->screen->chan)
+#define context_eng3d(ctx) \
+       (to_nouveau_context(ctx)->screen->eng3d)
+#define context_drv(ctx) \
+       (to_nouveau_context(ctx)->screen->driver)
+#define context_dirty(ctx, s) \
+       BITSET_SET(to_nouveau_context(ctx)->dirty, NOUVEAU_STATE_##s)
+#define context_dirty_i(ctx, s, i) \
+       BITSET_SET(to_nouveau_context(ctx)->dirty, NOUVEAU_STATE_##s##0 + i)
+
+GLboolean
+nouveau_context_create(const __GLcontextModes *visual, __DRIcontext *dri_ctx,
+                      void *share_ctx);
+
+GLboolean
+nouveau_context_init(GLcontext *ctx, struct nouveau_screen *screen,
+                    const GLvisual *visual, GLcontext *share_ctx);
+
+void
+nouveau_context_destroy(__DRIcontext *dri_ctx);
+
+GLboolean
+nouveau_context_make_current(__DRIcontext *dri_ctx,
+                            __DRIdrawable *ddraw,
+                            __DRIdrawable *rdraw);
+
+GLboolean
+nouveau_context_unbind(__DRIcontext *dri_ctx);
+
+void
+nouveau_fallback(GLcontext *ctx, enum nouveau_fallback mode);
+
+void
+nouveau_validate_framebuffer(GLcontext *ctx);
+
+#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 (file)
index 0000000..bf0e20c
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2009 Francisco Jerez.
+ * 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.
+ *
+ */
+
+#include "nouveau_driver.h"
+#include "nouveau_context.h"
+#include "nouveau_fbo.h"
+#include "nouveau_util.h"
+
+#include "drivers/common/meta.h"
+
+static const GLubyte *
+nouveau_get_string(GLcontext *ctx, GLenum name)
+{
+       static char buffer[128];
+       char hardware_name[32];
+
+       switch (name) {
+               case GL_VENDOR:
+                       return (GLubyte *)"Nouveau";
+
+               case GL_RENDERER:
+                       sprintf(hardware_name, "nv%02X", context_chipset(ctx));
+                       driGetRendererString(buffer, hardware_name, DRIVER_DATE, 0);
+
+                       return (GLubyte *)buffer;
+               default:
+                       return NULL;
+       }
+}
+
+static void
+nouveau_flush(GLcontext *ctx)
+{
+       struct nouveau_context *nctx = to_nouveau_context(ctx);
+       struct nouveau_channel *chan = context_chan(ctx);
+
+       FIRE_RING(chan);
+
+       if (ctx->DrawBuffer->Name == 0 &&
+           ctx->DrawBuffer->_ColorDrawBufferIndexes[0] == BUFFER_FRONT_LEFT) {
+               __DRIscreen *screen = nctx->screen->dri_screen;
+               __DRIdri2LoaderExtension *dri2 = screen->dri2.loader;
+               __DRIdrawable *drawable = nctx->dri_context->driDrawablePriv;
+
+               dri2->flushFrontBuffer(drawable, drawable->loaderPrivate);
+       }
+
+       nctx->drawable.dirty = GL_FALSE;
+}
+
+static void
+nouveau_finish(GLcontext *ctx)
+{
+       nouveau_flush(ctx);
+}
+
+void
+nouveau_clear(GLcontext *ctx, GLbitfield buffers)
+{
+       struct gl_framebuffer *fb = ctx->DrawBuffer;
+       int x, y, w, h;
+       int i, buf;
+
+       nouveau_validate_framebuffer(ctx);
+       get_scissors(fb, &x, &y, &w, &h);
+
+       for (i = 0; i < BUFFER_COUNT; i++) {
+               struct nouveau_surface *s;
+               unsigned mask, value;
+
+               buf = buffers & (1 << i);
+               if (!buf)
+                       continue;
+
+               s = &to_nouveau_renderbuffer(
+                       fb->Attachment[i].Renderbuffer->Wrapped)->surface;
+
+               if (buf & BUFFER_BITS_COLOR) {
+                       mask = pack_rgba_i(s->format, ctx->Color.ColorMask[0]);
+                       value = pack_rgba_f(s->format, ctx->Color.ClearColor);
+
+                       if (mask)
+                               context_drv(ctx)->surface_fill(
+                                       ctx, s, mask, value, x, y, w, h);
+
+                       buffers &= ~buf;
+
+               } else if (buf & (BUFFER_BIT_DEPTH | BUFFER_BIT_STENCIL)) {
+                       mask = pack_zs_i(s->format,
+                                        (buffers & BUFFER_BIT_DEPTH &&
+                                         ctx->Depth.Mask) ? ~0 : 0,
+                                        (buffers & BUFFER_BIT_STENCIL &&
+                                         ctx->Stencil.WriteMask[0]) ? ~0 : 0);
+                       value = pack_zs_f(s->format,
+                                         ctx->Depth.Clear,
+                                         ctx->Stencil.Clear);
+
+                       if (mask)
+                               context_drv(ctx)->surface_fill(
+                                       ctx, s, mask, value, x, y, w, h);
+
+                       buffers &= ~(BUFFER_BIT_DEPTH | BUFFER_BIT_STENCIL);
+               }
+       }
+
+       if (buffers)
+               _mesa_meta_Clear(ctx, buffers);
+}
+
+void
+nouveau_driver_functions_init(struct dd_function_table *functions)
+{
+       functions->GetString = nouveau_get_string;
+       functions->Flush = nouveau_flush;
+       functions->Finish = nouveau_finish;
+       functions->Clear = nouveau_clear;
+}
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_driver.h b/src/mesa/drivers/dri/nouveau/nouveau_driver.h
new file mode 100644 (file)
index 0000000..3b4d332
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2009 Francisco Jerez.
+ * 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.
+ *
+ */
+
+#ifndef __NOUVEAU_DRIVER_H__
+#define __NOUVEAU_DRIVER_H__
+
+#include "main/imports.h"
+#include "main/mtypes.h"
+#include "main/macros.h"
+#include "main/formats.h"
+#include "utils.h"
+#include "dri_util.h"
+
+#undef NDEBUG
+#include <assert.h>
+
+#include "nouveau_device.h"
+#include "nouveau_pushbuf.h"
+#include "nouveau_grobj.h"
+#include "nouveau_channel.h"
+#include "nouveau_bo.h"
+#include "nouveau_notifier.h"
+#include "nouveau_screen.h"
+#include "nouveau_state.h"
+#include "nouveau_surface.h"
+
+#define DRIVER_DATE    "20091015"
+#define DRIVER_AUTHOR  "Nouveau"
+
+struct nouveau_driver {
+       void (*screen_destroy)(struct nouveau_screen *screen);
+
+       GLcontext *(*context_create)(struct nouveau_screen *screen,
+                                    const GLvisual *visual,
+                                    GLcontext *share_ctx);
+       void (*context_destroy)(GLcontext *ctx);
+
+       void (*surface_copy)(GLcontext *ctx,
+                            struct nouveau_surface *dst,
+                            struct nouveau_surface *src,
+                            int dx, int dy, int sx, int sy, int w, int h);
+       void (*surface_fill)(GLcontext *ctx,
+                            struct nouveau_surface *dst,
+                            unsigned mask, unsigned value,
+                            int dx, int dy, int w, int h);
+
+       nouveau_state_func *emit;
+       int num_emit;
+};
+
+#define nouveau_error(format, ...) \
+       _mesa_fprintf(stderr, "%s: " format, __func__, ## __VA_ARGS__)
+
+void
+nouveau_clear(GLcontext *ctx, GLbitfield buffers);
+
+void
+nouveau_span_functions_init(GLcontext *ctx);
+
+void
+nouveau_driver_functions_init(struct dd_function_table *functions);
+
+void
+nouveau_texture_functions_init(struct dd_function_table *functions);
+
+#endif
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_fbo.c b/src/mesa/drivers/dri/nouveau/nouveau_fbo.c
new file mode 100644 (file)
index 0000000..91eade8
--- /dev/null
@@ -0,0 +1,277 @@
+/*
+ * Copyright (C) 2009 Francisco Jerez.
+ * 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.
+ *
+ */
+
+#include "nouveau_driver.h"
+#include "nouveau_fbo.h"
+#include "nouveau_context.h"
+#include "nouveau_texture.h"
+
+#include "main/framebuffer.h"
+#include "main/renderbuffer.h"
+#include "main/fbobject.h"
+
+static GLboolean
+set_renderbuffer_format(struct gl_renderbuffer *rb, GLenum internalFormat)
+{
+       struct nouveau_surface *s = &to_nouveau_renderbuffer(rb)->surface;
+
+       rb->InternalFormat  = internalFormat;
+
+       switch (internalFormat) {
+       case GL_RGB:
+       case GL_RGB8:
+               rb->_BaseFormat  = GL_RGB;
+               rb->Format = MESA_FORMAT_XRGB8888;
+               rb->DataType = GL_UNSIGNED_BYTE;
+               s->cpp = 4;
+               break;
+       case GL_RGBA:
+       case GL_RGBA8:
+               rb->_BaseFormat  = GL_RGBA;
+               rb->Format = MESA_FORMAT_ARGB8888;
+               rb->DataType = GL_UNSIGNED_BYTE;
+               s->cpp = 4;
+               break;
+       case GL_RGB5:
+               rb->_BaseFormat  = GL_RGB;
+               rb->Format = MESA_FORMAT_RGB565;
+               rb->DataType = GL_UNSIGNED_BYTE;
+               s->cpp = 2;
+               break;
+       case GL_DEPTH_COMPONENT16:
+               rb->_BaseFormat  = GL_DEPTH_COMPONENT;
+               rb->Format = MESA_FORMAT_Z16;
+               rb->DataType = GL_UNSIGNED_SHORT;
+               s->cpp = 2;
+               break;
+       case GL_DEPTH_COMPONENT24:
+       case GL_STENCIL_INDEX8_EXT:
+       case GL_DEPTH24_STENCIL8_EXT:
+               rb->_BaseFormat  = GL_DEPTH_COMPONENT;
+               rb->Format = MESA_FORMAT_Z24_S8;
+               rb->DataType = GL_UNSIGNED_INT;
+               s->cpp = 4;
+               break;
+       default:
+               return GL_FALSE;
+       }
+
+       s->format = rb->Format;
+
+       return GL_TRUE;
+}
+
+static GLboolean
+nouveau_renderbuffer_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
+                            GLenum internalFormat,
+                            GLuint width, GLuint height)
+{
+       struct nouveau_surface *s = &to_nouveau_renderbuffer(rb)->surface;
+
+       if (!set_renderbuffer_format(rb, internalFormat))
+               return GL_FALSE;
+
+       rb->Width = width;
+       rb->Height = height;
+
+       nouveau_surface_alloc(ctx, s, TILED, NOUVEAU_BO_VRAM | NOUVEAU_BO_MAP,
+                             rb->Format, width, height);
+
+       context_dirty(ctx, FRAMEBUFFER);
+       return GL_TRUE;
+}
+
+static void
+nouveau_renderbuffer_del(struct gl_renderbuffer *rb)
+{
+       struct nouveau_surface *s = &to_nouveau_renderbuffer(rb)->surface;
+
+       nouveau_surface_ref(NULL, s);
+       FREE(rb);
+}
+
+static struct gl_renderbuffer *
+nouveau_renderbuffer_new(GLcontext *ctx, GLuint name)
+{
+       struct gl_renderbuffer *rb;
+
+       rb = (struct gl_renderbuffer *)
+               CALLOC_STRUCT(nouveau_renderbuffer);
+       if (!rb)
+               return NULL;
+
+       _mesa_init_renderbuffer(rb, name);
+
+       rb->AllocStorage = nouveau_renderbuffer_storage;
+       rb->Delete = nouveau_renderbuffer_del;
+
+       return rb;
+}
+
+static GLboolean
+nouveau_renderbuffer_dri_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
+                                GLenum internalFormat,
+                                GLuint width, GLuint height)
+{
+       if (!set_renderbuffer_format(rb, internalFormat))
+               return GL_FALSE;
+
+       rb->Width = width;
+       rb->Height = height;
+
+       context_dirty(ctx, FRAMEBUFFER);
+       return GL_TRUE;
+}
+
+struct gl_renderbuffer *
+nouveau_renderbuffer_dri_new(GLenum format, __DRIdrawable *drawable)
+{
+       struct gl_renderbuffer *rb;
+
+       rb = nouveau_renderbuffer_new(NULL, 0);
+       if (!rb)
+               return NULL;
+
+       rb->AllocStorage = nouveau_renderbuffer_dri_storage;
+
+       if (!set_renderbuffer_format(rb, format)) {
+               nouveau_renderbuffer_del(rb);
+               return NULL;
+       }
+
+       return rb;
+}
+
+static struct gl_framebuffer *
+nouveau_framebuffer_new(GLcontext *ctx, GLuint name)
+{
+       struct nouveau_framebuffer *nfb;
+
+       nfb = CALLOC_STRUCT(nouveau_framebuffer);
+       if (!nfb)
+               return NULL;
+
+       _mesa_initialize_user_framebuffer(&nfb->base, name);
+
+       return &nfb->base;
+}
+
+struct gl_framebuffer *
+nouveau_framebuffer_dri_new(const GLvisual *visual)
+{
+       struct nouveau_framebuffer *nfb;
+
+       nfb = CALLOC_STRUCT(nouveau_framebuffer);
+       if (!nfb)
+               return NULL;
+
+       _mesa_initialize_window_framebuffer(&nfb->base, visual);
+
+       return &nfb->base;
+}
+
+static void
+nouveau_bind_framebuffer(GLcontext *ctx, GLenum target,
+                        struct gl_framebuffer *dfb,
+                        struct gl_framebuffer *rfb)
+{
+       context_dirty(ctx, FRAMEBUFFER);
+}
+
+static void
+nouveau_framebuffer_renderbuffer(GLcontext *ctx, struct gl_framebuffer *fb,
+                                GLenum attachment, struct gl_renderbuffer *rb)
+{
+       _mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb);
+
+       context_dirty(ctx, FRAMEBUFFER);
+}
+
+static GLenum
+get_tex_format(struct gl_texture_image *ti)
+{
+       switch (ti->TexFormat) {
+       case MESA_FORMAT_ARGB8888:
+               return GL_RGBA8;
+       case MESA_FORMAT_RGB565:
+               return GL_RGB5;
+       default:
+               assert(0);
+       }
+}
+
+static void
+nouveau_render_texture(GLcontext *ctx, struct gl_framebuffer *fb,
+                      struct gl_renderbuffer_attachment *att)
+{
+       struct gl_renderbuffer *rb = att->Renderbuffer;
+       struct gl_texture_image *ti =
+               att->Texture->Image[att->CubeMapFace][att->TextureLevel];
+       int ret;
+
+       /* Allocate a renderbuffer object for the texture if we
+        * haven't already done so. */
+       if (!rb) {
+               rb = nouveau_renderbuffer_new(ctx, 0);
+               assert(rb);
+
+               rb->AllocStorage = NULL;
+               _mesa_reference_renderbuffer(&att->Renderbuffer, rb);
+       }
+
+       /* Update the renderbuffer fields from the texture. */
+       ret = set_renderbuffer_format(rb, get_tex_format(ti));
+       assert(ret);
+
+       rb->Width = ti->Width;
+       rb->Height = ti->Height;
+       nouveau_surface_ref(&to_nouveau_teximage(ti)->surface,
+                           &to_nouveau_renderbuffer(rb)->surface);
+
+       context_dirty(ctx, FRAMEBUFFER);
+}
+
+static void
+nouveau_finish_render_texture(GLcontext *ctx,
+                             struct gl_renderbuffer_attachment *att)
+{
+       struct nouveau_renderbuffer *nrb
+               = to_nouveau_renderbuffer(att->Renderbuffer);
+
+       texture_dirty(att->Texture);
+       nouveau_surface_ref(NULL, &nrb->surface);
+}
+
+void
+nouveau_fbo_functions_init(struct dd_function_table *functions)
+{
+       functions->NewFramebuffer = nouveau_framebuffer_new;
+       functions->NewRenderbuffer = nouveau_renderbuffer_new;
+       functions->BindFramebuffer = nouveau_bind_framebuffer;
+       functions->FramebufferRenderbuffer = nouveau_framebuffer_renderbuffer;
+       functions->RenderTexture = nouveau_render_texture;
+       functions->FinishRenderTexture = nouveau_finish_render_texture;
+}
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_fbo.h b/src/mesa/drivers/dri/nouveau/nouveau_fbo.h
new file mode 100644 (file)
index 0000000..5ae984b
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2009 Francisco Jerez.
+ * 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.
+ *
+ */
+
+#ifndef __NOUVEAU_FBO_H__
+#define __NOUVEAU_FBO_H__
+
+struct nouveau_framebuffer {
+       struct gl_framebuffer base;
+       struct nouveau_bo *lma_bo;
+};
+#define to_nouveau_framebuffer(x) ((struct nouveau_framebuffer *)(x))
+
+struct nouveau_renderbuffer {
+       struct gl_renderbuffer base;
+       struct nouveau_surface surface;
+};
+#define to_nouveau_renderbuffer(x) ((struct nouveau_renderbuffer *)(x))
+
+struct gl_framebuffer *
+nouveau_framebuffer_dri_new(const GLvisual *visual);
+
+struct gl_renderbuffer *
+nouveau_renderbuffer_dri_new(GLenum format, __DRIdrawable *drawable);
+
+void
+nouveau_fbo_functions_init(struct dd_function_table *functions);
+
+#endif
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_gldefs.h b/src/mesa/drivers/dri/nouveau/nouveau_gldefs.h
new file mode 100644 (file)
index 0000000..00007a9
--- /dev/null
@@ -0,0 +1,263 @@
+/*
+ * Copyright (C) 2007-2010 The Nouveau Project.
+ * 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.
+ *
+ */
+
+#ifndef __NOUVEAU_GLDEFS_H__
+#define __NOUVEAU_GLDEFS_H__
+
+static inline unsigned
+nvgl_blend_func(unsigned func)
+{
+       switch (func) {
+       case GL_ZERO:
+               return 0x0000;
+       case GL_ONE:
+               return 0x0001;
+       case GL_SRC_COLOR:
+               return 0x0300;
+       case GL_ONE_MINUS_SRC_COLOR:
+               return 0x0301;
+       case GL_SRC_ALPHA:
+               return 0x0302;
+       case GL_ONE_MINUS_SRC_ALPHA:
+               return 0x0303;
+       case GL_DST_ALPHA:
+               return 0x0304;
+       case GL_ONE_MINUS_DST_ALPHA:
+               return 0x0305;
+       case GL_DST_COLOR:
+               return 0x0306;
+       case GL_ONE_MINUS_DST_COLOR:
+               return 0x0307;
+       case GL_SRC_ALPHA_SATURATE:
+               return 0x0308;
+       case GL_CONSTANT_COLOR:
+               return 0x8001;
+       case GL_ONE_MINUS_CONSTANT_COLOR:
+               return 0x8002;
+       case GL_CONSTANT_ALPHA:
+               return 0x8003;
+       case GL_ONE_MINUS_CONSTANT_ALPHA:
+               return 0x8004;
+       default:
+               assert(0);
+       }
+}
+
+static inline unsigned
+nvgl_blend_eqn(unsigned eqn)
+{
+       switch (eqn) {
+       case GL_FUNC_ADD:
+               return 0x8006;
+       case GL_MIN:
+               return 0x8007;
+       case GL_MAX:
+               return 0x8008;
+       case GL_FUNC_SUBTRACT:
+               return 0x800a;
+       case GL_FUNC_REVERSE_SUBTRACT:
+               return 0x800b;
+       default:
+               assert(0);
+       }
+}
+
+static inline unsigned
+nvgl_logicop_func(unsigned func)
+{
+       switch (func) {
+       case GL_CLEAR:
+               return 0x1500;
+       case GL_NOR:
+               return 0x1508;
+       case GL_AND_INVERTED:
+               return 0x1504;
+       case GL_COPY_INVERTED:
+               return 0x150c;
+       case GL_AND_REVERSE:
+               return 0x1502;
+       case GL_INVERT:
+               return 0x150a;
+       case GL_XOR:
+               return 0x1506;
+       case GL_NAND:
+               return 0x150e;
+       case GL_AND:
+               return 0x1501;
+       case GL_EQUIV:
+               return 0x1509;
+       case GL_NOOP:
+               return 0x1505;
+       case GL_OR_INVERTED:
+               return 0x150d;
+       case GL_COPY:
+               return 0x1503;
+       case GL_OR_REVERSE:
+               return 0x150b;
+       case GL_OR:
+               return 0x1507;
+       case GL_SET:
+               return 0x150f;
+       default:
+               assert(0);
+       }
+}
+
+static inline unsigned
+nvgl_comparison_op(unsigned op)
+{
+       switch (op) {
+       case GL_NEVER:
+               return 0x0200;
+       case GL_LESS:
+               return 0x0201;
+       case GL_EQUAL:
+               return 0x0202;
+       case GL_LEQUAL:
+               return 0x0203;
+       case GL_GREATER:
+               return 0x0204;
+       case GL_NOTEQUAL:
+               return 0x0205;
+       case GL_GEQUAL:
+               return 0x0206;
+       case GL_ALWAYS:
+               return 0x0207;
+       default:
+               assert(0);
+       }
+}
+
+static inline unsigned
+nvgl_polygon_mode(unsigned mode)
+{
+       switch (mode) {
+       case GL_POINT:
+               return 0x1b00;
+       case GL_LINE:
+               return 0x1b01;
+       case GL_FILL:
+               return 0x1b02;
+       default:
+               assert(0);
+       }
+}
+
+static inline unsigned
+nvgl_stencil_op(unsigned op)
+{
+       switch (op) {
+       case GL_ZERO:
+               return 0x0000;
+       case GL_INVERT:
+               return 0x150a;
+       case GL_KEEP:
+               return 0x1e00;
+       case GL_REPLACE:
+               return 0x1e01;
+       case GL_INCR:
+               return 0x1e02;
+       case GL_DECR:
+               return 0x1e03;
+       case GL_INCR_WRAP_EXT:
+               return 0x8507;
+       case GL_DECR_WRAP_EXT:
+               return 0x8508;
+       default:
+               assert(0);
+       }
+}
+
+static inline unsigned
+nvgl_primitive(unsigned prim)
+{
+       switch (prim) {
+       case GL_POINTS:
+               return 0x0001;
+       case GL_LINES:
+               return 0x0002;
+       case GL_LINE_LOOP:
+               return 0x0003;
+       case GL_LINE_STRIP:
+               return 0x0004;
+       case GL_TRIANGLES:
+               return 0x0005;
+       case GL_TRIANGLE_STRIP:
+               return 0x0006;
+       case GL_TRIANGLE_FAN:
+               return 0x0007;
+       case GL_QUADS:
+               return 0x0008;
+       case GL_QUAD_STRIP:
+               return 0x0009;
+       case GL_POLYGON:
+               return 0x000a;
+       default:
+               assert(0);
+       }
+}
+
+static inline unsigned
+nvgl_wrap_mode(unsigned wrap)
+{
+       switch (wrap) {
+       case GL_REPEAT:
+               return 0x1;
+       case GL_MIRRORED_REPEAT:
+               return 0x2;
+       case GL_CLAMP_TO_EDGE:
+               return 0x3;
+       case GL_CLAMP_TO_BORDER:
+               return 0x4;
+       case GL_CLAMP:
+               return 0x5;
+       default:
+               assert(0);
+       }
+}
+
+static inline unsigned
+nvgl_filter_mode(unsigned filter)
+{
+       switch (filter) {
+       case GL_NEAREST:
+               return 0x1;
+       case GL_LINEAR:
+               return 0x2;
+       case GL_NEAREST_MIPMAP_NEAREST:
+               return 0x3;
+       case GL_LINEAR_MIPMAP_NEAREST:
+               return 0x4;
+       case GL_NEAREST_MIPMAP_LINEAR:
+               return 0x5;
+       case GL_LINEAR_MIPMAP_LINEAR:
+               return 0x6;
+       default:
+               assert(0);
+       }
+}
+
+#endif
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_render.h b/src/mesa/drivers/dri/nouveau/nouveau_render.h
new file mode 100644 (file)
index 0000000..bff0ccf
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2009-2010 Francisco Jerez.
+ * 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.
+ *
+ */
+
+#ifndef __NOUVEAU_RENDER_H__
+#define __NOUVEAU_RENDER_H__
+
+#include "vbo/vbo_context.h"
+
+struct nouveau_array_state;
+
+typedef void (*dispatch_t)(GLcontext *, unsigned int, int, unsigned int);
+typedef unsigned (*extract_u_t)(struct nouveau_array_state *a, int i, int j);
+typedef float (*extract_f_t)(struct nouveau_array_state *a, int i, int j);
+
+struct nouveau_attr_info {
+       int vbo_index;
+       int imm_method;
+       int imm_fields;
+
+       void (*emit)(GLcontext *, struct nouveau_array_state *, const void *);
+};
+
+struct nouveau_array_state {
+       int attr;
+       int stride, fields, type;
+
+       struct nouveau_bo *bo;
+       unsigned offset;
+       const void *buf;
+
+       extract_u_t extract_u;
+       extract_f_t extract_f;
+};
+
+#define RENDER_SCRATCH_COUNT 32
+#define RENDER_SCRATCH_SIZE 64*1024
+
+struct nouveau_scratch_state {
+       struct nouveau_bo *bo[RENDER_SCRATCH_COUNT];
+
+       int index;
+       int offset;
+       void *buf;
+};
+
+struct nouveau_swtnl_state {
+       struct nouveau_bo *vbo;
+       void *buf;
+       unsigned vertex_count;
+       GLenum primitive;
+};
+
+struct nouveau_render_state {
+       enum {
+               VBO,
+               IMM
+       } mode;
+
+       struct nouveau_array_state ib;
+       struct nouveau_array_state attrs[VERT_ATTRIB_MAX];
+
+       /* Maps a HW VBO index or IMM emission order to an index in
+        * the attrs array above (or -1 if unused). */
+       int map[VERT_ATTRIB_MAX];
+
+       int attr_count;
+       int vertex_size;
+
+       struct nouveau_scratch_state scratch;
+       struct nouveau_swtnl_state swtnl;
+};
+
+#define to_render_state(ctx) (&to_nouveau_context(ctx)->render)
+
+#endif
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_render_t.c b/src/mesa/drivers/dri/nouveau/nouveau_render_t.c
new file mode 100644 (file)
index 0000000..c050578
--- /dev/null
@@ -0,0 +1,361 @@
+/*
+ * Copyright (C) 2009-2010 Francisco Jerez.
+ * 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.
+ *
+ */
+
+/*
+ * Vertex submission helper definitions shared among the software and
+ * hardware TnL paths.
+ */
+
+#include "nouveau_gldefs.h"
+
+#include "main/light.h"
+#include "vbo/vbo.h"
+#include "tnl/tnl.h"
+
+#define OUT_INDICES_L(r, i, d, n)              \
+       BATCH_OUT_L(i + d, n);                  \
+       (void)r
+#define OUT_INDICES_I16(r, i, d, n)                            \
+       BATCH_OUT_I16(r->ib.extract_u(&r->ib, 0, i) + d,        \
+                     r->ib.extract_u(&r->ib, 0, i + 1) + d)
+#define OUT_INDICES_I32(r, i, d, n)                    \
+       BATCH_OUT_I32(r->ib.extract_u(&r->ib, 0, i) + d)
+
+/*
+ * Emit <n> vertices using BATCH_OUT_<out>, MAX_OUT_<out> at a time,
+ * grouping them in packets of length MAX_PACKET.
+ *
+ * out:   hardware index data type.
+ * ctx:   GL context.
+ * start: element within the index buffer to begin with.
+ * delta: integer correction that will be added to each index found in
+ *        the index buffer.
+ */
+#define EMIT_VBO(out, ctx, start, delta, n) do {                       \
+               struct nouveau_render_state *render = to_render_state(ctx); \
+               int npush = n;                                          \
+                                                                       \
+               while (npush) {                                         \
+                       int npack = MIN2(npush, MAX_PACKET * MAX_OUT_##out); \
+                       npush -= npack;                                 \
+                                                                       \
+                       BATCH_PACKET_##out((npack + MAX_OUT_##out - 1)  \
+                                          / MAX_OUT_##out);            \
+                       while (npack) {                                 \
+                               int nout = MIN2(npack, MAX_OUT_##out);  \
+                               npack -= nout;                          \
+                                                                       \
+                               OUT_INDICES_##out(render, start, delta, \
+                                                 nout);                \
+                               start += nout;                          \
+                       }                                               \
+               }                                                       \
+       } while (0)
+
+/*
+ * Emit the <n>-th element of the array <a>, using IMM_OUT.
+ */
+#define EMIT_IMM(ctx, a, n) do {                                       \
+               struct nouveau_attr_info *info =                        \
+                       &TAG(vertex_attrs)[(a)->attr];                  \
+               int m;                                                  \
+                                                                       \
+               if (!info->emit) {                                      \
+                       IMM_PACKET(info->imm_method, info->imm_fields); \
+                                                                       \
+                       for (m = 0; m < (a)->fields; m++)               \
+                               IMM_OUT((a)->extract_f(a, n, m));       \
+                                                                       \
+                       for (m = (a)->fields; m < info->imm_fields; m++) \
+                               IMM_OUT(((float []){0, 0, 0, 1})[m]);   \
+                                                                       \
+               } else {                                                \
+                       info->emit(ctx, a, (a)->buf + n * (a)->stride); \
+               }                                                       \
+       } while (0)
+
+/*
+ * Select an appropriate dispatch function for the given index buffer.
+ */
+static void
+get_array_dispatch(struct nouveau_array_state *a, dispatch_t *dispatch)
+{
+       if (!a->fields) {
+               auto void f(GLcontext *, unsigned int, int, unsigned int);
+
+               void f(GLcontext *ctx, unsigned int start, int delta,
+                      unsigned int n) {
+                       struct nouveau_channel *chan = context_chan(ctx);
+                       RENDER_LOCALS(ctx);
+
+                       EMIT_VBO(L, ctx, start, delta, n);
+               };
+
+               *dispatch = f;
+
+       } else if (a->type == GL_UNSIGNED_INT) {
+               auto void f(GLcontext *, unsigned int, int, unsigned int);
+
+               void f(GLcontext *ctx, unsigned int start, int delta,
+                      unsigned int n) {
+                       struct nouveau_channel *chan = context_chan(ctx);
+                       RENDER_LOCALS(ctx);
+
+                       EMIT_VBO(I32, ctx, start, delta, n);
+               };
+
+               *dispatch = f;
+
+       } else {
+               auto void f(GLcontext *, unsigned int, int, unsigned int);
+
+               void f(GLcontext *ctx, unsigned int start, int delta,
+                      unsigned int n) {
+                       struct nouveau_channel *chan = context_chan(ctx);
+                       RENDER_LOCALS(ctx);
+
+                       EMIT_VBO(I32, ctx, start, delta, n & 1);
+                       EMIT_VBO(I16, ctx, start, delta, n & ~1);
+               };
+
+               *dispatch = f;
+       }
+}
+
+/*
+ * Select appropriate element extraction functions for the given
+ * array.
+ */
+static void
+get_array_extract(struct nouveau_array_state *a,
+                 extract_u_t *extract_u, extract_f_t *extract_f)
+{
+#define EXTRACT(in_t, out_t, k)                                                \
+       ({                                                              \
+               auto out_t f(struct nouveau_array_state *, int, int);   \
+               out_t f(struct nouveau_array_state *a, int i, int j) {  \
+                       in_t x = ((in_t *)(a->buf + i * a->stride))[j]; \
+                                                                       \
+                       return (out_t)x / (k);                          \
+               };                                                      \
+               f;                                                      \
+       });
+
+       switch (a->type) {
+       case GL_BYTE:
+               *extract_u = EXTRACT(char, unsigned, 1);
+               *extract_f = EXTRACT(char, float, SCHAR_MAX);
+               break;
+       case GL_UNSIGNED_BYTE:
+               *extract_u = EXTRACT(unsigned char, unsigned, 1);
+               *extract_f = EXTRACT(unsigned char, float, UCHAR_MAX);
+               break;
+       case GL_SHORT:
+               *extract_u = EXTRACT(short, unsigned, 1);
+               *extract_f = EXTRACT(short, float, SHRT_MAX);
+               break;
+       case GL_UNSIGNED_SHORT:
+               *extract_u = EXTRACT(unsigned short, unsigned, 1);
+               *extract_f = EXTRACT(unsigned short, float, USHRT_MAX);
+               break;
+       case GL_INT:
+               *extract_u = EXTRACT(int, unsigned, 1);
+               *extract_f = EXTRACT(int, float, INT_MAX);
+               break;
+       case GL_UNSIGNED_INT:
+               *extract_u = EXTRACT(unsigned int, unsigned, 1);
+               *extract_f = EXTRACT(unsigned int, float, UINT_MAX);
+               break;
+       case GL_FLOAT:
+               *extract_u = EXTRACT(float, unsigned, 1.0 / UINT_MAX);
+               *extract_f = EXTRACT(float, float, 1);
+               break;
+
+       default:
+               assert(0);
+       }
+}
+
+/*
+ * Returns a pointer to a chunk of <size> bytes long GART memory. <bo>
+ * will be updated with the buffer object the memory is located in.
+ *
+ * If <offset> is provided, it will be updated with the offset within
+ * <bo> of the allocated memory. Otherwise the returned memory will
+ * always be located right at the beginning of <bo>.
+ */
+static inline void *
+get_scratch_vbo(GLcontext *ctx, unsigned size, struct nouveau_bo **bo,
+               unsigned *offset)
+{
+       struct nouveau_scratch_state *scratch = &to_render_state(ctx)->scratch;
+       void *buf;
+
+       if (scratch->buf && offset &&
+           size <= RENDER_SCRATCH_SIZE - scratch->offset) {
+               nouveau_bo_ref(scratch->bo[scratch->index], bo);
+
+               buf = scratch->buf + scratch->offset;
+               *offset = scratch->offset;
+               scratch->offset += size;
+
+       } else if (size <= RENDER_SCRATCH_SIZE) {
+               scratch->index = (scratch->index + 1) % RENDER_SCRATCH_COUNT;
+               nouveau_bo_ref(scratch->bo[scratch->index], bo);
+
+               nouveau_bo_map(*bo, NOUVEAU_BO_WR);
+               buf = scratch->buf = (*bo)->map;
+               nouveau_bo_unmap(*bo);
+
+               if (offset)
+                       *offset = 0;
+               scratch->offset = size;
+
+       } else {
+               nouveau_bo_new(context_dev(ctx),
+                              NOUVEAU_BO_MAP | NOUVEAU_BO_GART, 0, size, bo);
+
+               nouveau_bo_map(*bo, NOUVEAU_BO_WR);
+               buf = (*bo)->map;
+               nouveau_bo_unmap(*bo);
+
+               if (offset)
+                       *offset = 0;
+       }
+
+       return buf;
+}
+
+/*
+ * Returns how many vertices you can draw using <n> pushbuf dwords.
+ */
+static inline unsigned
+get_max_vertices(GLcontext *ctx, const struct _mesa_index_buffer *ib,
+                unsigned n)
+{
+       struct nouveau_render_state *render = to_render_state(ctx);
+
+       if (render->mode == IMM) {
+               return MAX2(0, n - 4) / (render->vertex_size / 4 +
+                                        render->attr_count);
+       } else {
+               unsigned max_out;
+
+               if (ib) {
+                       switch (ib->type) {
+                       case GL_UNSIGNED_INT:
+                               max_out = MAX_OUT_I32;
+                               break;
+
+                       case GL_UNSIGNED_SHORT:
+                               max_out = MAX_OUT_I16;
+                               break;
+
+                       case GL_UNSIGNED_BYTE:
+                               max_out = MAX_OUT_I16;
+                               break;
+                       }
+               } else {
+                       max_out = MAX_OUT_L;
+               }
+
+               return MAX2(0, n - 7) * max_out * MAX_PACKET / (1 + MAX_PACKET);
+       }
+}
+
+#include "nouveau_vbo_t.c"
+#include "nouveau_swtnl_t.c"
+
+static void
+TAG(emit_material)(GLcontext *ctx, struct nouveau_array_state *a,
+                  const void *v)
+{
+       const int attr = a->attr - VERT_ATTRIB_GENERIC0;
+       const int state = ((int []) {
+                               NOUVEAU_STATE_MATERIAL_FRONT_AMBIENT,
+                               NOUVEAU_STATE_MATERIAL_BACK_AMBIENT,
+                               NOUVEAU_STATE_MATERIAL_FRONT_DIFFUSE,
+                               NOUVEAU_STATE_MATERIAL_BACK_DIFFUSE,
+                               NOUVEAU_STATE_MATERIAL_FRONT_SPECULAR,
+                               NOUVEAU_STATE_MATERIAL_BACK_SPECULAR,
+                               NOUVEAU_STATE_MATERIAL_FRONT_AMBIENT,
+                               NOUVEAU_STATE_MATERIAL_BACK_AMBIENT,
+                               NOUVEAU_STATE_MATERIAL_FRONT_SHININESS,
+                               NOUVEAU_STATE_MATERIAL_BACK_SHININESS
+                       }) [attr];
+
+       COPY_4V(ctx->Light.Material.Attrib[attr], (float *)v);
+       _mesa_update_material(ctx, 1 << attr);
+
+       context_drv(ctx)->emit[state](ctx, state);
+}
+
+static void
+TAG(render_prims)(GLcontext *ctx, const struct gl_client_array **arrays,
+                 const struct _mesa_prim *prims, GLuint nr_prims,
+                 const struct _mesa_index_buffer *ib,
+                 GLboolean index_bounds_valid,
+                 GLuint min_index, GLuint max_index)
+{
+       struct nouveau_context *nctx = to_nouveau_context(ctx);
+
+       nouveau_validate_framebuffer(ctx);
+
+       if (nctx->fallback == HWTNL)
+               TAG(vbo_render_prims)(ctx, arrays, prims, nr_prims, ib,
+                                     index_bounds_valid, min_index, max_index);
+
+       if (nctx->fallback == SWTNL)
+               _tnl_vbo_draw_prims(ctx, arrays, prims, nr_prims, ib,
+                                   index_bounds_valid, min_index, max_index);
+}
+
+void
+TAG(render_init)(GLcontext *ctx)
+{
+       struct nouveau_render_state *render = to_render_state(ctx);
+       struct nouveau_scratch_state *scratch = &render->scratch;
+       int ret, i;
+
+       for (i = 0; i < RENDER_SCRATCH_COUNT; i++) {
+               ret = nouveau_bo_new(context_dev(ctx),
+                                    NOUVEAU_BO_MAP | NOUVEAU_BO_GART,
+                                    0, RENDER_SCRATCH_SIZE, &scratch->bo[i]);
+               assert(!ret);
+       }
+
+       for (i = 0; i < VERT_ATTRIB_MAX; i++)
+               render->map[i] = -1;
+
+       TAG(swtnl_init)(ctx);
+       vbo_set_draw_func(ctx, TAG(render_prims));
+}
+
+void
+TAG(render_destroy)(GLcontext *ctx)
+{
+       TAG(swtnl_destroy)(ctx);
+}
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_screen.c b/src/mesa/drivers/dri/nouveau/nouveau_screen.c
new file mode 100644 (file)
index 0000000..de63282
--- /dev/null
@@ -0,0 +1,269 @@
+/*
+ * Copyright (C) 2009 Francisco Jerez.
+ * 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.
+ *
+ */
+
+#include "nouveau_driver.h"
+#include "nouveau_context.h"
+#include "nouveau_fbo.h"
+#include "nouveau_drmif.h"
+#include "nv04_driver.h"
+#include "nv10_driver.h"
+#include "nv20_driver.h"
+
+#include "main/framebuffer.h"
+#include "main/renderbuffer.h"
+
+static const __DRIextension *nouveau_screen_extensions[];
+
+static void
+nouveau_destroy_screen(__DRIscreen *dri_screen);
+
+static void
+nouveau_channel_flush_notify(struct nouveau_channel *chan)
+{
+       struct nouveau_screen *screen = chan->user_private;
+       struct nouveau_context *nctx = screen->context;
+
+       if (nctx && nctx->fallback < SWRAST)
+               nouveau_state_emit(&nctx->base);
+}
+
+static const __DRIconfig **
+nouveau_get_configs(void)
+{
+       __DRIconfig **configs = NULL;
+       int i;
+
+       const uint8_t depth_bits[]   = { 0, 16, 24, 24 };
+       const uint8_t stencil_bits[] = { 0,  0,  0,  8 };
+       const uint8_t msaa_samples[] = { 0 };
+
+       const struct {
+               GLenum format;
+               GLenum type;
+       } fb_formats[] = {
+               { 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 },
+       };
+
+       const GLenum back_buffer_modes[] = {
+               GLX_NONE, GLX_SWAP_UNDEFINED_OML
+       };
+
+       for (i = 0; i < Elements(fb_formats); i++) {
+               __DRIconfig **config;
+
+               config = driCreateConfigs(fb_formats[i].format,
+                                         fb_formats[i].type,
+                                         depth_bits, stencil_bits,
+                                         Elements(depth_bits),
+                                         back_buffer_modes,
+                                         Elements(back_buffer_modes),
+                                         msaa_samples,
+                                         Elements(msaa_samples));
+               assert(config);
+
+               configs = configs ? driConcatConfigs(configs, config)
+                       : config;
+       }
+
+       return (const __DRIconfig **)configs;
+}
+
+static const __DRIconfig **
+nouveau_init_screen2(__DRIscreen *dri_screen)
+{
+       const __DRIconfig **configs;
+       struct nouveau_screen *screen;
+       int ret;
+
+       /* Allocate the screen. */
+       screen = CALLOC_STRUCT(nouveau_screen);
+       if (!screen)
+               return NULL;
+
+       dri_screen->private = screen;
+       dri_screen->extensions = nouveau_screen_extensions;
+       screen->dri_screen = dri_screen;
+
+       /* Open the DRM device. */
+       ret = nouveau_device_open_existing(&screen->device, 0, dri_screen->fd,
+                                          0);
+       if (ret) {
+               nouveau_error("Error opening the DRM device.\n");
+               goto fail;
+       }
+
+       ret = nouveau_channel_alloc(screen->device, 0xbeef0201, 0xbeef0202,
+                                   &screen->chan);
+       if (ret) {
+               nouveau_error("Error initializing the FIFO.\n");
+               goto fail;
+       }
+       screen->chan->flush_notify = nouveau_channel_flush_notify;
+       screen->chan->user_private = screen;
+
+       /* Do the card specific initialization */
+       switch (screen->device->chipset & 0xf0) {
+       case 0x00:
+               ret = nv04_screen_init(screen);
+               break;
+       case 0x10:
+               ret = nv10_screen_init(screen);
+               break;
+       case 0x20:
+               ret = nv20_screen_init(screen);
+               break;
+       default:
+               assert(0);
+       }
+       if (!ret) {
+               nouveau_error("Error initializing the hardware.\n");
+               goto fail;
+       }
+
+       configs = nouveau_get_configs();
+       if (!configs) {
+               nouveau_error("Error creating the framebuffer configs.\n");
+               goto fail;
+       }
+
+       return configs;
+fail:
+       nouveau_destroy_screen(dri_screen);
+       return NULL;
+
+}
+
+static void
+nouveau_destroy_screen(__DRIscreen *dri_screen)
+{
+       struct nouveau_screen *screen = dri_screen->private;
+
+       if (!screen)
+               return;
+
+       screen->driver->screen_destroy(screen);
+
+       if (screen->chan) {
+               screen->chan->flush_notify = NULL;
+               nouveau_channel_free(&screen->chan);
+       }
+
+       if (screen->device)
+               nouveau_device_close(&screen->device);
+
+       FREE(screen);
+       dri_screen->private = NULL;
+}
+
+static GLboolean
+nouveau_create_buffer(__DRIscreen *dri_screen,
+                     __DRIdrawable *drawable,
+                     const __GLcontextModes *visual,
+                     GLboolean is_pixmap)
+{
+       struct gl_renderbuffer  *rb;
+       struct gl_framebuffer *fb;
+       GLenum color_format;
+
+       if (is_pixmap)
+               return GL_FALSE; /* not implemented */
+
+       if (visual->redBits == 5)
+               color_format = GL_RGB5;
+       else if (visual->alphaBits == 0)
+               color_format = GL_RGB8;
+       else
+               color_format = GL_RGBA8;
+
+       fb = nouveau_framebuffer_dri_new(visual);
+       if (!fb)
+               return GL_FALSE;
+
+       /* Front buffer. */
+       rb = nouveau_renderbuffer_dri_new(color_format, drawable);
+       _mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, rb);
+
+       /* Back buffer */
+       if (visual->doubleBufferMode) {
+               rb = nouveau_renderbuffer_dri_new(color_format, drawable);
+               _mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, rb);
+       }
+
+       /* Depth/stencil buffer. */
+       if (visual->depthBits == 24 && visual->stencilBits == 8) {
+               rb = nouveau_renderbuffer_dri_new(GL_DEPTH24_STENCIL8_EXT, drawable);
+               _mesa_add_renderbuffer(fb, BUFFER_DEPTH, rb);
+               _mesa_add_renderbuffer(fb, BUFFER_STENCIL, rb);
+
+       } else if (visual->depthBits == 24) {
+               rb = nouveau_renderbuffer_dri_new(GL_DEPTH_COMPONENT24, drawable);
+               _mesa_add_renderbuffer(fb, BUFFER_DEPTH, rb);
+
+       } else if (visual->depthBits == 16) {
+               rb = nouveau_renderbuffer_dri_new(GL_DEPTH_COMPONENT16, drawable);
+               _mesa_add_renderbuffer(fb, BUFFER_DEPTH, rb);
+       }
+
+       /* Software renderbuffers. */
+       _mesa_add_soft_renderbuffers(fb, GL_FALSE, GL_FALSE, GL_FALSE,
+                                    visual->accumRedBits > 0,
+                                    GL_FALSE, GL_FALSE);
+
+       drawable->driverPrivate = fb;
+
+       return GL_TRUE;
+}
+
+static void
+nouveau_destroy_buffer(__DRIdrawable *drawable)
+{
+       _mesa_reference_framebuffer(
+               (struct gl_framebuffer **)&drawable->driverPrivate, NULL);
+}
+
+static const __DRIextension *nouveau_screen_extensions[] = {
+    NULL
+};
+
+const struct __DriverAPIRec driDriverAPI = {
+       .InitScreen2     = nouveau_init_screen2,
+       .DestroyScreen   = nouveau_destroy_screen,
+       .CreateBuffer    = nouveau_create_buffer,
+       .DestroyBuffer   = nouveau_destroy_buffer,
+       .CreateContext   = nouveau_context_create,
+       .DestroyContext  = nouveau_context_destroy,
+       .MakeCurrent     = nouveau_context_make_current,
+       .UnbindContext   = nouveau_context_unbind,
+};
+
+/* This is the table of extensions that the loader will dlsym() for. */
+PUBLIC const __DRIextension *__driDriverExtensions[] = {
+       &driCoreExtension.base,
+       &driDRI2Extension.base,
+       NULL
+};
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_screen.h b/src/mesa/drivers/dri/nouveau/nouveau_screen.h
new file mode 100644 (file)
index 0000000..5d45039
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2009 Francisco Jerez.
+ * 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.
+ *
+ */
+
+#ifndef __NOUVEAU_SCREEN_H__
+#define __NOUVEAU_SCREEN_H__
+
+struct nouveau_context;
+
+struct nouveau_screen {
+       __DRIscreen *dri_screen;
+
+       struct nouveau_device *device;
+       struct nouveau_channel *chan;
+
+       struct nouveau_notifier *ntfy;
+       struct nouveau_grobj *eng3d;
+       struct nouveau_grobj *eng3dm;
+       struct nouveau_grobj *surf3d;
+       struct nouveau_grobj *m2mf;
+       struct nouveau_grobj *surf2d;
+       struct nouveau_grobj *rop;
+       struct nouveau_grobj *patt;
+       struct nouveau_grobj *rect;
+       struct nouveau_grobj *swzsurf;
+       struct nouveau_grobj *sifm;
+
+       const struct nouveau_driver *driver;
+       struct nouveau_context *context;
+};
+
+#endif
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_span.c b/src/mesa/drivers/dri/nouveau/nouveau_span.c
new file mode 100644 (file)
index 0000000..dbbbf15
--- /dev/null
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) 2009 Francisco Jerez.
+ * 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.
+ *
+ */
+
+#include "nouveau_driver.h"
+#include "nouveau_fbo.h"
+#include "nouveau_context.h"
+#include "nouveau_bo.h"
+
+#include "swrast/swrast.h"
+
+#define LOCAL_VARS                                                     \
+       struct gl_framebuffer *fb = ctx->DrawBuffer;                    \
+       struct nouveau_surface *s = &to_nouveau_renderbuffer(rb)->surface; \
+       GLuint p;                                                       \
+       (void)p;
+
+#define LOCAL_DEPTH_VARS LOCAL_VARS
+
+#define HW_LOCK()
+#define HW_UNLOCK()
+
+#define HW_CLIPLOOP() {                                                        \
+       int minx = 0;                                                   \
+       int miny = 0;                                                   \
+       int maxx = fb->Width;                                           \
+       int maxy = fb->Height;
+
+#define HW_ENDCLIPLOOP() }
+
+#define Y_FLIP(y) (fb->Name ? (y) : rb->Height - 1 - (y))
+
+/* RGB565 span functions */
+#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) (s->bo->map + (y)*s->pitch + (x)*s->cpp)
+
+#include "spantmp2.h"
+
+/* ARGB8888 span functions */
+#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) (s->bo->map + (y)*s->pitch + (x)*s->cpp)
+
+#include "spantmp2.h"
+
+/* Z16 span functions */
+#define VALUE_TYPE uint16_t
+#define READ_DEPTH(v, x, y)                                            \
+       v = *(uint16_t *)(s->bo->map + (y)*s->pitch + (x)*s->cpp);
+#define WRITE_DEPTH(x, y, v)                                           \
+       *(uint16_t *)(s->bo->map + (y)*s->pitch + (x)*s->cpp) = v
+#define TAG(x) nouveau_##x##_z16
+
+#include "depthtmp.h"
+
+/* Z24S8 span functions */
+#define VALUE_TYPE uint32_t
+#define READ_DEPTH(v, x, y)                                            \
+       v = *(uint32_t *)(s->bo->map + (y)*s->pitch + (x)*s->cpp);
+#define WRITE_DEPTH(x, y, v)                                           \
+       *(uint32_t *)(s->bo->map + (y)*s->pitch + (x)*s->cpp) = v
+#define TAG(x) nouveau_##x##_z24s8
+
+#include "depthtmp.h"
+
+static void
+renderbuffer_map_unmap(struct gl_renderbuffer *rb, GLboolean map)
+{
+       struct nouveau_surface *s = &to_nouveau_renderbuffer(rb)->surface;
+
+       if (map) {
+               switch (rb->Format) {
+               case MESA_FORMAT_RGB565:
+                       nouveau_InitPointers_rgb565(rb);
+                       break;
+               case MESA_FORMAT_XRGB8888:
+               case MESA_FORMAT_ARGB8888:
+                       nouveau_InitPointers_argb8888(rb);
+                       break;
+               case MESA_FORMAT_Z16:
+                       nouveau_InitDepthPointers_z16(rb);
+                       break;
+               case MESA_FORMAT_Z24_S8:
+                       nouveau_InitDepthPointers_z24s8(rb);
+                       break;
+               default:
+                       assert(0);
+               }
+
+               nouveau_bo_map(s->bo, NOUVEAU_BO_RDWR);
+       } else {
+               nouveau_bo_unmap(s->bo);
+       }
+}
+
+static void
+texture_unit_map_unmap(GLcontext *ctx, struct gl_texture_unit *u, GLboolean map)
+{
+       if (!u->_ReallyEnabled)
+               return;
+
+       if (map)
+               ctx->Driver.MapTexture(ctx, u->_Current);
+       else
+               ctx->Driver.UnmapTexture(ctx, u->_Current);
+}
+
+static void
+span_map_unmap(GLcontext *ctx, GLboolean map)
+{
+       int i;
+
+       for (i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++)
+               renderbuffer_map_unmap(ctx->DrawBuffer->_ColorDrawBuffers[i], map);
+
+       renderbuffer_map_unmap(ctx->DrawBuffer->_ColorReadBuffer, map);
+
+       if (ctx->DrawBuffer->_DepthBuffer)
+               renderbuffer_map_unmap(ctx->DrawBuffer->_DepthBuffer->Wrapped, map);
+
+       for (i = 0; i < ctx->Const.MaxTextureUnits; i++)
+               texture_unit_map_unmap(ctx, &ctx->Texture.Unit[i], map);
+}
+
+static void
+nouveau_span_start(GLcontext *ctx)
+{
+       nouveau_fallback(ctx, SWRAST);
+       span_map_unmap(ctx, GL_TRUE);
+}
+
+static void
+nouveau_span_finish(GLcontext *ctx)
+{
+       span_map_unmap(ctx, GL_FALSE);
+       nouveau_fallback(ctx, HWTNL);
+}
+
+void
+nouveau_span_functions_init(GLcontext *ctx)
+{
+       struct swrast_device_driver *swdd =
+               _swrast_GetDeviceDriverReference(ctx);
+
+       swdd->SpanRenderStart = nouveau_span_start;
+       swdd->SpanRenderFinish = nouveau_span_finish;
+}
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_state.c b/src/mesa/drivers/dri/nouveau/nouveau_state.c
new file mode 100644 (file)
index 0000000..d727822
--- /dev/null
@@ -0,0 +1,532 @@
+/*
+ * Copyright (C) 2009 Francisco Jerez.
+ * 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.
+ *
+ */
+
+#include "nouveau_driver.h"
+#include "nouveau_context.h"
+#include "nouveau_texture.h"
+#include "nouveau_util.h"
+
+#include "swrast/swrast.h"
+#include "tnl/tnl.h"
+
+static void
+nouveau_alpha_func(GLcontext *ctx, GLenum func, GLfloat ref)
+{
+       context_dirty(ctx, ALPHA_FUNC);
+}
+
+static void
+nouveau_blend_color(GLcontext *ctx, const GLfloat color[4])
+{
+       context_dirty(ctx, BLEND_COLOR);
+}
+
+static void
+nouveau_blend_equation_separate(GLcontext *ctx, GLenum modeRGB, GLenum modeA)
+{
+       context_dirty(ctx, BLEND_EQUATION);
+}
+
+static void
+nouveau_blend_func_separate(GLcontext *ctx, GLenum sfactorRGB,
+                           GLenum dfactorRGB, GLenum sfactorA, GLenum dfactorA)
+{
+       context_dirty(ctx, BLEND_FUNC);
+}
+
+static void
+nouveau_clip_plane(GLcontext *ctx, GLenum plane, const GLfloat *equation)
+{
+       context_dirty_i(ctx, CLIP_PLANE, plane - GL_CLIP_PLANE0);
+}
+
+static void
+nouveau_color_mask(GLcontext *ctx, GLboolean rmask, GLboolean gmask,
+                  GLboolean bmask, GLboolean amask)
+{
+       context_dirty(ctx, COLOR_MASK);
+}
+
+static void
+nouveau_color_material(GLcontext *ctx, GLenum face, GLenum mode)
+{
+       context_dirty(ctx, COLOR_MATERIAL);
+       context_dirty(ctx, MATERIAL_FRONT_AMBIENT);
+       context_dirty(ctx, MATERIAL_BACK_AMBIENT);
+       context_dirty(ctx, MATERIAL_FRONT_DIFFUSE);
+       context_dirty(ctx, MATERIAL_BACK_DIFFUSE);
+       context_dirty(ctx, MATERIAL_FRONT_SPECULAR);
+       context_dirty(ctx, MATERIAL_BACK_SPECULAR);
+}
+
+static void
+nouveau_cull_face(GLcontext *ctx, GLenum mode)
+{
+       context_dirty(ctx, CULL_FACE);
+}
+
+static void
+nouveau_front_face(GLcontext *ctx, GLenum mode)
+{
+       context_dirty(ctx, FRONT_FACE);
+}
+
+static void
+nouveau_depth_func(GLcontext *ctx, GLenum func)
+{
+       context_dirty(ctx, DEPTH);
+}
+
+static void
+nouveau_depth_mask(GLcontext *ctx, GLboolean flag)
+{
+       context_dirty(ctx, DEPTH);
+}
+
+static void
+nouveau_depth_range(GLcontext *ctx, GLclampd nearval, GLclampd farval)
+{
+       context_dirty(ctx, VIEWPORT);
+}
+
+static void
+nouveau_draw_buffer(GLcontext *ctx, GLenum buffer)
+{
+       context_dirty(ctx, FRAMEBUFFER);
+}
+
+static void
+nouveau_draw_buffers(GLcontext *ctx, GLsizei n, const GLenum *buffers)
+{
+       context_dirty(ctx, FRAMEBUFFER);
+}
+
+static void
+nouveau_enable(GLcontext *ctx, GLenum cap, GLboolean state)
+{
+       int i;
+
+       switch (cap) {
+       case GL_ALPHA_TEST:
+               context_dirty(ctx, ALPHA_FUNC);
+               break;
+       case GL_BLEND:
+               context_dirty(ctx, BLEND_EQUATION);
+               break;
+       case GL_COLOR_LOGIC_OP:
+               context_dirty(ctx, LOGIC_OPCODE);
+               break;
+       case GL_COLOR_MATERIAL:
+               context_dirty(ctx, COLOR_MATERIAL);
+               context_dirty(ctx, MATERIAL_FRONT_AMBIENT);
+               context_dirty(ctx, MATERIAL_BACK_AMBIENT);
+               context_dirty(ctx, MATERIAL_FRONT_DIFFUSE);
+               context_dirty(ctx, MATERIAL_BACK_DIFFUSE);
+               context_dirty(ctx, MATERIAL_FRONT_SPECULAR);
+               context_dirty(ctx, MATERIAL_BACK_SPECULAR);
+               break;
+       case GL_COLOR_SUM_EXT:
+               context_dirty(ctx, FRAG);
+               break;
+       case GL_CULL_FACE:
+               context_dirty(ctx, CULL_FACE);
+               break;
+       case GL_DEPTH_TEST:
+               context_dirty(ctx, DEPTH);
+               break;
+       case GL_DITHER:
+               context_dirty(ctx, DITHER);
+               break;
+       case GL_FOG:
+               context_dirty(ctx, FOG);
+               context_dirty(ctx, FRAG);
+               context_dirty(ctx, MODELVIEW);
+               break;
+       case GL_LIGHT0:
+       case GL_LIGHT1:
+       case GL_LIGHT2:
+       case GL_LIGHT3:
+       case GL_LIGHT4:
+       case GL_LIGHT5:
+       case GL_LIGHT6:
+       case GL_LIGHT7:
+               context_dirty(ctx, MODELVIEW);
+               context_dirty(ctx, LIGHT_ENABLE);
+               context_dirty_i(ctx, LIGHT_SOURCE, cap - GL_LIGHT0);
+               context_dirty(ctx, MATERIAL_FRONT_AMBIENT);
+               context_dirty(ctx, MATERIAL_BACK_AMBIENT);
+               context_dirty(ctx, MATERIAL_FRONT_DIFFUSE);
+               context_dirty(ctx, MATERIAL_BACK_DIFFUSE);
+               context_dirty(ctx, MATERIAL_FRONT_SPECULAR);
+               context_dirty(ctx, MATERIAL_BACK_SPECULAR);
+               context_dirty(ctx, MATERIAL_FRONT_SHININESS);
+               context_dirty(ctx, MATERIAL_BACK_SHININESS);
+               break;
+       case GL_LIGHTING:
+               context_dirty(ctx, FRAG);
+               context_dirty(ctx, MODELVIEW);
+               context_dirty(ctx, LIGHT_ENABLE);
+
+               for (i = 0; i < MAX_LIGHTS; i++) {
+                       if (ctx->Light.Light[i].Enabled)
+                               context_dirty_i(ctx, LIGHT_SOURCE, i);
+               }
+
+               context_dirty(ctx, MATERIAL_FRONT_AMBIENT);
+               context_dirty(ctx, MATERIAL_BACK_AMBIENT);
+               context_dirty(ctx, MATERIAL_FRONT_DIFFUSE);
+               context_dirty(ctx, MATERIAL_BACK_DIFFUSE);
+               context_dirty(ctx, MATERIAL_FRONT_SPECULAR);
+               context_dirty(ctx, MATERIAL_BACK_SPECULAR);
+               context_dirty(ctx, MATERIAL_FRONT_SHININESS);
+               context_dirty(ctx, MATERIAL_BACK_SHININESS);
+               break;
+       case GL_LINE_SMOOTH:
+               context_dirty(ctx, LINE_MODE);
+               break;
+       case GL_NORMALIZE:
+               context_dirty(ctx, LIGHT_ENABLE);
+               break;
+       case GL_POINT_SMOOTH:
+               context_dirty(ctx, POINT_MODE);
+               break;
+       case GL_POLYGON_OFFSET_POINT:
+       case GL_POLYGON_OFFSET_LINE:
+       case GL_POLYGON_OFFSET_FILL:
+               context_dirty(ctx, POLYGON_OFFSET);
+               break;
+       case GL_POLYGON_SMOOTH:
+               context_dirty(ctx, POLYGON_MODE);
+               break;
+       case GL_SCISSOR_TEST:
+               context_dirty(ctx, SCISSOR);
+               break;
+       case GL_STENCIL_TEST:
+               context_dirty(ctx, STENCIL_FUNC);
+               break;
+       case GL_TEXTURE_1D:
+       case GL_TEXTURE_2D:
+       case GL_TEXTURE_3D:
+               context_dirty_i(ctx, TEX_ENV, ctx->Texture.CurrentUnit);
+               context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit);
+               break;
+       }
+}
+
+static void
+nouveau_fog(GLcontext *ctx, GLenum pname, const GLfloat *params)
+{
+       context_dirty(ctx, FOG);
+}
+
+static void
+nouveau_index_mask(GLcontext *ctx, GLuint mask)
+{
+       context_dirty(ctx, INDEX_MASK);
+}
+
+static void
+nouveau_light(GLcontext *ctx, GLenum light, GLenum pname, const GLfloat *params)
+{
+       switch (pname) {
+       case GL_AMBIENT:
+               context_dirty(ctx, MATERIAL_FRONT_AMBIENT);
+               context_dirty(ctx, MATERIAL_BACK_AMBIENT);
+               break;
+       case GL_DIFFUSE:
+               context_dirty(ctx, MATERIAL_FRONT_DIFFUSE);
+               context_dirty(ctx, MATERIAL_BACK_DIFFUSE);
+               break;
+       case GL_SPECULAR:
+               context_dirty(ctx, MATERIAL_FRONT_SPECULAR);
+               context_dirty(ctx, MATERIAL_BACK_SPECULAR);
+               break;
+       case GL_SPOT_CUTOFF:
+       case GL_POSITION:
+               context_dirty(ctx, MODELVIEW);
+               context_dirty(ctx, LIGHT_ENABLE);
+               context_dirty_i(ctx, LIGHT_SOURCE, light - GL_LIGHT0);
+               break;
+       default:
+               context_dirty_i(ctx, LIGHT_SOURCE, light - GL_LIGHT0);
+               break;
+       }
+}
+
+static void
+nouveau_light_model(GLcontext *ctx, GLenum pname, const GLfloat *params)
+{
+       context_dirty(ctx, LIGHT_MODEL);
+       context_dirty(ctx, MODELVIEW);
+}
+
+static void
+nouveau_line_stipple(GLcontext *ctx, GLint factor, GLushort pattern )
+{
+       context_dirty(ctx, LINE_STIPPLE);
+}
+
+static void
+nouveau_line_width(GLcontext *ctx, GLfloat width)
+{
+       context_dirty(ctx, LINE_MODE);
+}
+
+static void
+nouveau_logic_opcode(GLcontext *ctx, GLenum opcode)
+{
+       context_dirty(ctx, LOGIC_OPCODE);
+}
+
+static void
+nouveau_point_parameter(GLcontext *ctx, GLenum pname, const GLfloat *params)
+{
+       context_dirty(ctx, POINT_PARAMETER);
+}
+
+static void
+nouveau_point_size(GLcontext *ctx, GLfloat size)
+{
+       context_dirty(ctx, POINT_MODE);
+}
+
+static void
+nouveau_polygon_mode(GLcontext *ctx, GLenum face, GLenum mode)
+{
+       context_dirty(ctx, POLYGON_MODE);
+}
+
+static void
+nouveau_polygon_offset(GLcontext *ctx, GLfloat factor, GLfloat units)
+{
+       context_dirty(ctx, POLYGON_OFFSET);
+}
+
+static void
+nouveau_polygon_stipple(GLcontext *ctx, const GLubyte *mask)
+{
+       context_dirty(ctx, POLYGON_STIPPLE);
+}
+
+static void
+nouveau_render_mode(GLcontext *ctx, GLenum mode)
+{
+       context_dirty(ctx, RENDER_MODE);
+}
+
+static void
+nouveau_scissor(GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h)
+{
+       context_dirty(ctx, SCISSOR);
+}
+
+static void
+nouveau_shade_model(GLcontext *ctx, GLenum mode)
+{
+       context_dirty(ctx, SHADE_MODEL);
+}
+
+static void
+nouveau_stencil_func_separate(GLcontext *ctx, GLenum face, GLenum func,
+                             GLint ref, GLuint mask)
+{
+       context_dirty(ctx, STENCIL_FUNC);
+}
+
+static void
+nouveau_stencil_mask_separate(GLcontext *ctx, GLenum face, GLuint mask)
+{
+       context_dirty(ctx, STENCIL_MASK);
+}
+
+static void
+nouveau_stencil_op_separate(GLcontext *ctx, GLenum face, GLenum fail,
+                           GLenum zfail, GLenum zpass)
+{
+       context_dirty(ctx, STENCIL_OP);
+}
+
+static void
+nouveau_tex_gen(GLcontext *ctx, GLenum coord, GLenum pname,
+               const GLfloat *params)
+{
+       context_dirty_i(ctx, TEX_GEN, ctx->Texture.CurrentUnit);
+}
+
+static void
+nouveau_tex_env(GLcontext *ctx, GLenum target, GLenum pname,
+               const GLfloat *param)
+{
+       switch (target) {
+       case GL_TEXTURE_FILTER_CONTROL_EXT:
+               context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit);
+               break;
+       default:
+               context_dirty_i(ctx, TEX_ENV, ctx->Texture.CurrentUnit);
+               break;
+       }
+}
+
+static void
+nouveau_tex_parameter(GLcontext *ctx, GLenum target,
+                     struct gl_texture_object *t, GLenum pname,
+                     const GLfloat *params)
+{
+       switch (pname) {
+       case GL_TEXTURE_MIN_FILTER:
+       case GL_TEXTURE_MAG_FILTER:
+       case GL_TEXTURE_WRAP_S:
+       case GL_TEXTURE_WRAP_T:
+       case GL_TEXTURE_WRAP_R:
+       case GL_TEXTURE_MIN_LOD:
+       case GL_TEXTURE_MAX_LOD:
+       case GL_TEXTURE_MAX_ANISOTROPY_EXT:
+       case GL_TEXTURE_LOD_BIAS:
+               context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit);
+               break;
+
+       case GL_TEXTURE_BASE_LEVEL:
+       case GL_TEXTURE_MAX_LEVEL:
+               texture_dirty(t);
+               context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit);
+               break;
+       }
+}
+
+static void
+nouveau_viewport(GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h)
+{
+       context_dirty(ctx, VIEWPORT);
+}
+
+void
+nouveau_emit_nothing(GLcontext *ctx, int emit)
+{
+}
+
+int
+nouveau_next_dirty_state(GLcontext *ctx)
+{
+       struct nouveau_context *nctx = to_nouveau_context(ctx);
+       int i = BITSET_FFS(nctx->dirty) - 1;
+
+       if (i < 0 || i >= context_drv(ctx)->num_emit)
+               return -1;
+
+       return i;
+}
+
+void
+nouveau_state_emit(GLcontext *ctx)
+{
+       struct nouveau_context *nctx = to_nouveau_context(ctx);
+       const struct nouveau_driver *drv = context_drv(ctx);
+       int i;
+
+       while ((i = nouveau_next_dirty_state(ctx)) >= 0) {
+               BITSET_CLEAR(nctx->dirty, i);
+               drv->emit[i](ctx, i);
+       }
+
+       BITSET_ZERO(nctx->dirty);
+
+       nouveau_bo_state_emit(ctx);
+}
+
+static void
+nouveau_update_state(GLcontext *ctx, GLbitfield new_state)
+{
+       if (new_state & (_NEW_PROJECTION | _NEW_MODELVIEW))
+               context_dirty(ctx, PROJECTION);
+
+       if (new_state & _NEW_MODELVIEW)
+               context_dirty(ctx, MODELVIEW);
+
+       if (new_state & _NEW_CURRENT_ATTRIB &&
+           new_state & _NEW_LIGHT) {
+               context_dirty(ctx, MATERIAL_FRONT_AMBIENT);
+               context_dirty(ctx, MATERIAL_BACK_AMBIENT);
+               context_dirty(ctx, MATERIAL_FRONT_DIFFUSE);
+               context_dirty(ctx, MATERIAL_BACK_DIFFUSE);
+               context_dirty(ctx, MATERIAL_FRONT_SPECULAR);
+               context_dirty(ctx, MATERIAL_BACK_SPECULAR);
+               context_dirty(ctx, MATERIAL_FRONT_SHININESS);
+               context_dirty(ctx, MATERIAL_BACK_SHININESS);
+       }
+
+       _swrast_InvalidateState(ctx, new_state);
+       _tnl_InvalidateState(ctx, new_state);
+
+       nouveau_state_emit(ctx);
+}
+
+void
+nouveau_state_init(GLcontext *ctx)
+{
+       struct nouveau_context *nctx = to_nouveau_context(ctx);
+
+       ctx->Driver.AlphaFunc = nouveau_alpha_func;
+       ctx->Driver.BlendColor = nouveau_blend_color;
+       ctx->Driver.BlendEquationSeparate = nouveau_blend_equation_separate;
+       ctx->Driver.BlendFuncSeparate = nouveau_blend_func_separate;
+       ctx->Driver.ClipPlane = nouveau_clip_plane;
+       ctx->Driver.ColorMask = nouveau_color_mask;
+       ctx->Driver.ColorMaterial = nouveau_color_material;
+       ctx->Driver.CullFace = nouveau_cull_face;
+       ctx->Driver.FrontFace = nouveau_front_face;
+       ctx->Driver.DepthFunc = nouveau_depth_func;
+       ctx->Driver.DepthMask = nouveau_depth_mask;
+       ctx->Driver.DepthRange = nouveau_depth_range;
+       ctx->Driver.DrawBuffer = nouveau_draw_buffer;
+       ctx->Driver.DrawBuffers = nouveau_draw_buffers;
+       ctx->Driver.Enable = nouveau_enable;
+       ctx->Driver.Fogfv = nouveau_fog;
+       ctx->Driver.IndexMask = nouveau_index_mask;
+       ctx->Driver.Lightfv = nouveau_light;
+       ctx->Driver.LightModelfv = nouveau_light_model;
+       ctx->Driver.LineStipple = nouveau_line_stipple;
+       ctx->Driver.LineWidth = nouveau_line_width;
+       ctx->Driver.LogicOpcode = nouveau_logic_opcode;
+       ctx->Driver.PointParameterfv = nouveau_point_parameter;
+       ctx->Driver.PointSize = nouveau_point_size;
+       ctx->Driver.PolygonMode = nouveau_polygon_mode;
+       ctx->Driver.PolygonOffset = nouveau_polygon_offset;
+       ctx->Driver.PolygonStipple = nouveau_polygon_stipple;
+       ctx->Driver.RenderMode = nouveau_render_mode;
+       ctx->Driver.Scissor = nouveau_scissor;
+       ctx->Driver.ShadeModel = nouveau_shade_model;
+       ctx->Driver.StencilFuncSeparate = nouveau_stencil_func_separate;
+       ctx->Driver.StencilMaskSeparate = nouveau_stencil_mask_separate;
+       ctx->Driver.StencilOpSeparate = nouveau_stencil_op_separate;
+       ctx->Driver.TexGen = nouveau_tex_gen;
+       ctx->Driver.TexEnv = nouveau_tex_env;
+       ctx->Driver.TexParameter = nouveau_tex_parameter;
+       ctx->Driver.Viewport = nouveau_viewport;
+
+       ctx->Driver.UpdateState = nouveau_update_state;
+
+       BITSET_ONES(nctx->dirty);
+}
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_state.h b/src/mesa/drivers/dri/nouveau/nouveau_state.h
new file mode 100644 (file)
index 0000000..d001fa2
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2009 Francisco Jerez.
+ * 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.
+ *
+ */
+
+#ifndef __NOUVEAU_STATE_H__
+#define __NOUVEAU_STATE_H__
+
+enum {
+       NOUVEAU_STATE_ALPHA_FUNC,
+       NOUVEAU_STATE_BLEND_COLOR,
+       NOUVEAU_STATE_BLEND_EQUATION,
+       NOUVEAU_STATE_BLEND_FUNC,
+       NOUVEAU_STATE_CLIP_PLANE0,
+       NOUVEAU_STATE_CLIP_PLANE1,
+       NOUVEAU_STATE_CLIP_PLANE2,
+       NOUVEAU_STATE_CLIP_PLANE3,
+       NOUVEAU_STATE_CLIP_PLANE4,
+       NOUVEAU_STATE_CLIP_PLANE5,
+       NOUVEAU_STATE_COLOR_MASK,
+       NOUVEAU_STATE_COLOR_MATERIAL,
+       NOUVEAU_STATE_CULL_FACE,
+       NOUVEAU_STATE_FRONT_FACE,
+       NOUVEAU_STATE_DEPTH,
+       NOUVEAU_STATE_DITHER,
+       NOUVEAU_STATE_FRAG,
+       NOUVEAU_STATE_FRAMEBUFFER,
+       NOUVEAU_STATE_FOG,
+       NOUVEAU_STATE_INDEX_MASK,
+       NOUVEAU_STATE_LIGHT_ENABLE,
+       NOUVEAU_STATE_LIGHT_MODEL,
+       NOUVEAU_STATE_LIGHT_SOURCE0,
+       NOUVEAU_STATE_LIGHT_SOURCE1,
+       NOUVEAU_STATE_LIGHT_SOURCE2,
+       NOUVEAU_STATE_LIGHT_SOURCE3,
+       NOUVEAU_STATE_LIGHT_SOURCE4,
+       NOUVEAU_STATE_LIGHT_SOURCE5,
+       NOUVEAU_STATE_LIGHT_SOURCE6,
+       NOUVEAU_STATE_LIGHT_SOURCE7,
+       NOUVEAU_STATE_LINE_STIPPLE,
+       NOUVEAU_STATE_LINE_MODE,
+       NOUVEAU_STATE_LOGIC_OPCODE,
+       NOUVEAU_STATE_MATERIAL_FRONT_AMBIENT,
+       NOUVEAU_STATE_MATERIAL_BACK_AMBIENT,
+       NOUVEAU_STATE_MATERIAL_FRONT_DIFFUSE,
+       NOUVEAU_STATE_MATERIAL_BACK_DIFFUSE,
+       NOUVEAU_STATE_MATERIAL_FRONT_SPECULAR,
+       NOUVEAU_STATE_MATERIAL_BACK_SPECULAR,
+       NOUVEAU_STATE_MATERIAL_FRONT_SHININESS,
+       NOUVEAU_STATE_MATERIAL_BACK_SHININESS,
+       NOUVEAU_STATE_MODELVIEW,
+       NOUVEAU_STATE_POINT_MODE,
+       NOUVEAU_STATE_POINT_PARAMETER,
+       NOUVEAU_STATE_POLYGON_MODE,
+       NOUVEAU_STATE_POLYGON_OFFSET,
+       NOUVEAU_STATE_POLYGON_STIPPLE,
+       NOUVEAU_STATE_PROJECTION,
+       NOUVEAU_STATE_RENDER_MODE,
+       NOUVEAU_STATE_SCISSOR,
+       NOUVEAU_STATE_SHADE_MODEL,
+       NOUVEAU_STATE_STENCIL_FUNC,
+       NOUVEAU_STATE_STENCIL_MASK,
+       NOUVEAU_STATE_STENCIL_OP,
+       NOUVEAU_STATE_TEX_ENV0,
+       NOUVEAU_STATE_TEX_ENV1,
+       NOUVEAU_STATE_TEX_ENV2,
+       NOUVEAU_STATE_TEX_ENV3,
+       NOUVEAU_STATE_TEX_GEN0,
+       NOUVEAU_STATE_TEX_GEN1,
+       NOUVEAU_STATE_TEX_GEN2,
+       NOUVEAU_STATE_TEX_GEN3,
+       NOUVEAU_STATE_TEX_OBJ0,
+       NOUVEAU_STATE_TEX_OBJ1,
+       NOUVEAU_STATE_TEX_OBJ2,
+       NOUVEAU_STATE_TEX_OBJ3,
+       NOUVEAU_STATE_VIEWPORT,
+       NUM_NOUVEAU_STATE,
+
+       /* Room for card-specific states. */
+
+       MAX_NOUVEAU_STATE = NUM_NOUVEAU_STATE + 16,
+};
+
+typedef void (*nouveau_state_func)(GLcontext *ctx, int emit);
+
+void
+nouveau_state_init(GLcontext *ctx);
+
+void
+nouveau_emit_nothing(GLcontext *ctx, int emit);
+
+int
+nouveau_next_dirty_state(GLcontext *ctx);
+
+void
+nouveau_state_emit(GLcontext *ctx);
+
+#endif
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_surface.c b/src/mesa/drivers/dri/nouveau/nouveau_surface.c
new file mode 100644 (file)
index 0000000..3339397
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2009 Francisco Jerez.
+ * 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.
+ *
+ */
+
+#include "nouveau_driver.h"
+#include "nouveau_context.h"
+#include "nouveau_util.h"
+
+void
+nouveau_surface_alloc(GLcontext *ctx, struct nouveau_surface *s,
+                     enum nouveau_surface_layout layout,
+                     unsigned flags, unsigned format,
+                     unsigned width, unsigned height)
+{
+       unsigned tile_mode, cpp = _mesa_get_format_bytes(format);
+       int ret;
+
+       nouveau_bo_ref(NULL, &s->bo);
+
+       *s = (struct nouveau_surface) {
+               .layout = layout,
+               .format = format,
+               .width = width,
+               .height = height,
+               .cpp = cpp,
+               .pitch = width * cpp,
+       };
+
+       if (layout == TILED) {
+               s->pitch = align(s->pitch, 256);
+               tile_mode = s->pitch;
+       } else {
+               s->pitch = align(s->pitch, 64);
+               tile_mode = 0;
+       }
+
+       ret = nouveau_bo_new_tile(context_dev(ctx), flags, 0, s->pitch * height,
+                                 tile_mode, 0, &s->bo);
+       assert(!ret);
+}
+
+void
+nouveau_surface_ref(struct nouveau_surface *src,
+                   struct nouveau_surface *dst)
+{
+       if (src) {
+               dst->offset = src->offset;
+               dst->layout = src->layout;
+               dst->format = src->format;
+               dst->width = src->width;
+               dst->height = src->height;
+               dst->cpp = src->cpp;
+               dst->pitch = src->pitch;
+               nouveau_bo_ref(src->bo, &dst->bo);
+
+       } else {
+               nouveau_bo_ref(NULL, &dst->bo);
+       }
+}
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_surface.h b/src/mesa/drivers/dri/nouveau/nouveau_surface.h
new file mode 100644 (file)
index 0000000..ebdc89a
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2009 Francisco Jerez.
+ * 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.
+ *
+ */
+
+#ifndef __NOUVEAU_SURFACE_H__
+#define __NOUVEAU_SURFACE_H__
+
+enum nouveau_surface_layout {
+       LINEAR = 0,
+       TILED,
+       SWIZZLED,
+};
+
+struct nouveau_surface {
+       struct nouveau_bo *bo;
+       unsigned offset;
+
+       enum nouveau_surface_layout layout;
+
+       gl_format format;
+       unsigned cpp, pitch;
+
+       unsigned width, height;
+};
+
+void
+nouveau_surface_alloc(GLcontext *ctx, struct nouveau_surface *s,
+                     enum nouveau_surface_layout layout,
+                     unsigned flags, unsigned format,
+                     unsigned width, unsigned height);
+
+void
+nouveau_surface_ref(struct nouveau_surface *src,
+                   struct nouveau_surface *dst);
+
+#endif
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_swtnl_t.c b/src/mesa/drivers/dri/nouveau/nouveau_swtnl_t.c
new file mode 100644 (file)
index 0000000..8fa922f
--- /dev/null
@@ -0,0 +1,354 @@
+/*
+ * Copyright (C) 2009-2010 Francisco Jerez.
+ * 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.
+ *
+ */
+
+#include "tnl/t_context.h"
+#include "tnl/t_pipeline.h"
+#include "tnl/t_vertex.h"
+
+static enum tnl_attr_format
+swtnl_get_format(int type, int fields) {
+       switch (type) {
+       case GL_FLOAT:
+               switch (fields){
+               case 1:
+                       return EMIT_1F;
+               case 2:
+                       return EMIT_2F;
+               case 3:
+                       return EMIT_3F;
+               case 4:
+                       return EMIT_4F;
+               default:
+                       assert(0);
+               }
+       case GL_UNSIGNED_BYTE:
+               switch (fields) {
+               case 4:
+                       return EMIT_4UB_4F_RGBA;
+               default:
+                       assert(0);
+               }
+       default:
+               assert(0);
+       }
+}
+
+static struct swtnl_attr_info {
+       int type;
+       int fields;
+} swtnl_attrs[VERT_ATTRIB_MAX] = {
+       [VERT_ATTRIB_POS] = {
+               .type = GL_FLOAT,
+               .fields = 4,
+       },
+       [VERT_ATTRIB_NORMAL] = {
+               .type = GL_FLOAT,
+               .fields = -1,
+       },
+       [VERT_ATTRIB_COLOR0] = {
+               .type = GL_UNSIGNED_BYTE,
+               .fields = 4,
+       },
+       [VERT_ATTRIB_COLOR1] = {
+               .type = GL_UNSIGNED_BYTE,
+               .fields = 4,
+       },
+       [VERT_ATTRIB_FOG] = {
+               .type = GL_FLOAT,
+               .fields = 1,
+       },
+       [VERT_ATTRIB_TEX0] = {
+               .type = GL_FLOAT,
+               .fields = -1,
+       },
+       [VERT_ATTRIB_TEX1] = {
+               .type = GL_FLOAT,
+               .fields = -1,
+       },
+       [VERT_ATTRIB_TEX2] = {
+               .type = GL_FLOAT,
+               .fields = -1,
+       },
+       [VERT_ATTRIB_TEX3] = {
+               .type = GL_FLOAT,
+               .fields = -1,
+       },
+};
+
+static void
+swtnl_choose_attrs(GLcontext *ctx)
+{
+       struct nouveau_render_state *render = to_render_state(ctx);
+       TNLcontext *tnl = TNL_CONTEXT(ctx);
+       struct tnl_clipspace *vtx = &tnl->clipspace;
+       static struct tnl_attr_map map[NUM_VERTEX_ATTRS];
+       int fields, i, n = 0;
+
+       render->mode = VBO;
+       render->attr_count = NUM_VERTEX_ATTRS;
+
+       /* We always want non Ndc coords format */
+       tnl->vb.AttribPtr[VERT_ATTRIB_POS] = tnl->vb.ClipPtr;
+
+       for (i = 0; i < VERT_ATTRIB_MAX; i++) {
+               struct nouveau_attr_info *ha = &TAG(vertex_attrs)[i];
+               struct swtnl_attr_info *sa = &swtnl_attrs[i];
+               struct nouveau_array_state *a = &render->attrs[i];
+
+               if (!sa->fields)
+                       continue; /* Unsupported attribute. */
+
+               if (RENDERINPUTS_TEST(tnl->render_inputs_bitset, i)) {
+                       if (sa->fields > 0)
+                               fields = sa->fields;
+                       else
+                               fields = tnl->vb.AttribPtr[i]->size;
+
+                       map[n++] = (struct tnl_attr_map) {
+                               .attrib = i,
+                               .format = swtnl_get_format(sa->type, fields),
+                       };
+
+                       render->map[ha->vbo_index] = i;
+                       a->attr = i;
+                       a->fields = fields;
+                       a->type = sa->type;
+               }
+       }
+
+       _tnl_install_attrs(ctx, map, n, NULL, 0);
+
+       for (i = 0; i < vtx->attr_count; i++) {
+               struct tnl_clipspace_attr *ta = &vtx->attr[i];
+               struct nouveau_array_state *a = &render->attrs[ta->attrib];
+
+               a->stride = vtx->vertex_size;
+               a->offset = ta->vertoffset;
+       }
+
+       TAG(render_set_format)(ctx);
+}
+
+static void
+swtnl_alloc_vertices(GLcontext *ctx)
+{
+       struct nouveau_swtnl_state *swtnl = &to_render_state(ctx)->swtnl;
+
+       nouveau_bo_ref(NULL, &swtnl->vbo);
+       swtnl->buf = get_scratch_vbo(ctx, RENDER_SCRATCH_SIZE,
+                                    &swtnl->vbo, NULL);
+       swtnl->vertex_count = 0;
+}
+
+static void
+swtnl_bind_vertices(GLcontext *ctx)
+{
+       struct nouveau_render_state *render = to_render_state(ctx);
+       struct nouveau_swtnl_state *swtnl = &render->swtnl;
+       int i;
+
+       for (i = 0; i < render->attr_count; i++) {
+               int attr = render->map[i];
+
+               if (attr >= 0)
+                       nouveau_bo_ref(swtnl->vbo,
+                                      &render->attrs[attr].bo);
+       }
+
+       TAG(render_bind_vertices)(ctx);
+}
+
+static void
+swtnl_unbind_vertices(GLcontext *ctx)
+{
+       struct nouveau_render_state *render = to_render_state(ctx);
+       int i;
+
+       for (i = 0; i < render->attr_count; i++) {
+               int *attr = &render->map[i];
+
+               if (*attr >= 0) {
+                       nouveau_bo_ref(NULL, &render->attrs[*attr].bo);
+                       *attr = -1;
+               }
+       }
+
+       render->attr_count = 0;
+}
+
+static void
+swtnl_flush_vertices(GLcontext *ctx)
+{
+       struct nouveau_channel *chan = context_chan(ctx);
+       struct nouveau_swtnl_state *swtnl = &to_render_state(ctx)->swtnl;
+       unsigned push, start = 0, count = swtnl->vertex_count;
+       RENDER_LOCALS(ctx);
+
+       swtnl_bind_vertices(ctx);
+
+       while (count) {
+               push = get_max_vertices(ctx, NULL, chan->pushbuf->remaining);
+               push = MIN2(push / 12 * 12, count);
+               count -= push;
+
+               if (!push) {
+                       FIRE_RING(chan);
+                       continue;
+               }
+
+               BATCH_BEGIN(nvgl_primitive(swtnl->primitive));
+               EMIT_VBO(L, ctx, start, 0, push);
+               BATCH_END();
+
+               FIRE_RING(chan);
+       }
+
+       swtnl_alloc_vertices(ctx);
+}
+
+/* TnL renderer entry points */
+
+static void
+swtnl_start(GLcontext *ctx)
+{
+       swtnl_choose_attrs(ctx);
+}
+
+static void
+swtnl_finish(GLcontext *ctx)
+{
+       swtnl_flush_vertices(ctx);
+       swtnl_unbind_vertices(ctx);
+}
+
+static void
+swtnl_primitive(GLcontext *ctx, GLenum mode)
+{
+}
+
+static void
+swtnl_reset_stipple(GLcontext *ctx)
+{
+}
+
+/* Primitive rendering */
+
+#define BEGIN_PRIMITIVE(p, n)                                          \
+       struct nouveau_swtnl_state *swtnl = &to_render_state(ctx)->swtnl; \
+       int vertex_len = TNL_CONTEXT(ctx)->clipspace.vertex_size;       \
+                                                                       \
+       if (swtnl->vertex_count + (n) > swtnl->vbo->size/vertex_len     \
+           || (swtnl->vertex_count && swtnl->primitive != p))          \
+               swtnl_flush_vertices(ctx);                              \
+                                                                       \
+       swtnl->primitive = p;
+
+#define OUT_VERTEX(i) do {                                             \
+               memcpy(swtnl->buf + swtnl->vertex_count * vertex_len,   \
+                      _tnl_get_vertex(ctx, (i)), vertex_len);          \
+               swtnl->vertex_count++;                                  \
+       } while (0)
+
+static void
+swtnl_points(GLcontext *ctx, GLuint first, GLuint last)
+{
+       int i, count;
+
+       while (first < last) {
+               BEGIN_PRIMITIVE(GL_POINTS, last - first);
+
+               count = MIN2(swtnl->vbo->size / vertex_len, last - first);
+               for (i = 0; i < count; i++)
+                       OUT_VERTEX(first + i);
+
+               first += count;
+       }
+}
+
+static void
+swtnl_line(GLcontext *ctx, GLuint v1, GLuint v2)
+{
+       BEGIN_PRIMITIVE(GL_LINES, 2);
+       OUT_VERTEX(v1);
+       OUT_VERTEX(v2);
+}
+
+static void
+swtnl_triangle(GLcontext *ctx, GLuint v1, GLuint v2, GLuint v3)
+{
+       BEGIN_PRIMITIVE(GL_TRIANGLES, 3);
+       OUT_VERTEX(v1);
+       OUT_VERTEX(v2);
+       OUT_VERTEX(v3);
+}
+
+static void
+swtnl_quad(GLcontext *ctx, GLuint v1, GLuint v2, GLuint v3, GLuint v4)
+{
+       BEGIN_PRIMITIVE(GL_QUADS, 4);
+       OUT_VERTEX(v1);
+       OUT_VERTEX(v2);
+       OUT_VERTEX(v3);
+       OUT_VERTEX(v4);
+}
+
+/* TnL initialization. */
+static void
+TAG(swtnl_init)(GLcontext *ctx)
+{
+       TNLcontext *tnl = TNL_CONTEXT(ctx);
+
+       tnl->Driver.RunPipeline = _tnl_run_pipeline;
+       tnl->Driver.Render.Interp = _tnl_interp;
+       tnl->Driver.Render.CopyPV = _tnl_copy_pv;
+       tnl->Driver.Render.ClippedPolygon = _tnl_RenderClippedPolygon;
+       tnl->Driver.Render.ClippedLine = _tnl_RenderClippedLine;
+       tnl->Driver.Render.BuildVertices = _tnl_build_vertices;
+
+       tnl->Driver.Render.Start = swtnl_start;
+       tnl->Driver.Render.Finish = swtnl_finish;
+       tnl->Driver.Render.PrimitiveNotify = swtnl_primitive;
+       tnl->Driver.Render.ResetLineStipple = swtnl_reset_stipple;
+
+       tnl->Driver.Render.Points = swtnl_points;
+       tnl->Driver.Render.Line = swtnl_line;
+       tnl->Driver.Render.Triangle = swtnl_triangle;
+       tnl->Driver.Render.Quad = swtnl_quad;
+
+       _tnl_init_vertices(ctx, tnl->vb.Size,
+                          NUM_VERTEX_ATTRS * 4 * sizeof(GLfloat));
+       _tnl_need_projected_coords(ctx, GL_FALSE);
+       _tnl_allow_vertex_fog(ctx, GL_FALSE);
+       _tnl_wakeup(ctx);
+
+       swtnl_alloc_vertices(ctx);
+}
+
+static void
+TAG(swtnl_destroy)(GLcontext *ctx)
+{
+       nouveau_bo_ref(NULL, &to_render_state(ctx)->swtnl.vbo);
+}
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_texture.c b/src/mesa/drivers/dri/nouveau/nouveau_texture.c
new file mode 100644 (file)
index 0000000..ab6e93c
--- /dev/null
@@ -0,0 +1,456 @@
+/*
+ * Copyright (C) 2009 Francisco Jerez.
+ * 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.
+ *
+ */
+
+#include "nouveau_driver.h"
+#include "nouveau_context.h"
+#include "nouveau_texture.h"
+#include "nouveau_util.h"
+
+#include "main/texobj.h"
+#include "main/texstore.h"
+#include "main/texformat.h"
+#include "main/texcompress.h"
+#include "main/texgetimage.h"
+#include "main/mipmap.h"
+#include "main/texfetch.h"
+
+static struct gl_texture_object *
+nouveau_texture_new(GLcontext *ctx, GLuint name, GLenum target)
+{
+       struct nouveau_texture *nt = CALLOC_STRUCT(nouveau_texture);
+
+       _mesa_initialize_texture_object(&nt->base, name, target);
+
+       return &nt->base;
+}
+
+static void
+nouveau_texture_free(GLcontext *ctx, struct gl_texture_object *t)
+{
+       struct nouveau_texture *nt = to_nouveau_texture(t);
+       int i;
+
+       for (i = 0; i < MAX_TEXTURE_LEVELS; i++)
+               nouveau_surface_ref(NULL, &nt->surfaces[i]);
+
+       _mesa_delete_texture_object(ctx, t);
+}
+
+static struct gl_texture_image *
+nouveau_teximage_new(GLcontext *ctx)
+{
+       struct nouveau_teximage *nti = CALLOC_STRUCT(nouveau_teximage);
+
+       return &nti->base;
+}
+
+static void
+nouveau_teximage_free(GLcontext *ctx, struct gl_texture_image *ti)
+{
+       struct nouveau_teximage *nti = to_nouveau_teximage(ti);
+
+       nouveau_surface_ref(NULL, &nti->surface);
+}
+
+static void
+nouveau_teximage_map(GLcontext *ctx, struct gl_texture_image *ti)
+{
+       struct nouveau_surface *s = &to_nouveau_teximage(ti)->surface;
+       int ret;
+
+       ret = nouveau_bo_map(s->bo, NOUVEAU_BO_RDWR);
+       assert(!ret);
+
+       ti->Data = s->bo->map;
+}
+
+static void
+nouveau_teximage_unmap(GLcontext *ctx, struct gl_texture_image *ti)
+{
+       struct nouveau_surface *s = &to_nouveau_teximage(ti)->surface;
+
+       nouveau_bo_unmap(s->bo);
+       ti->Data = NULL;
+}
+
+static gl_format
+nouveau_choose_tex_format(GLcontext *ctx, GLint internalFormat,
+                         GLenum srcFormat, GLenum srcType)
+{
+       switch (internalFormat) {
+       case 4:
+       case GL_RGBA:
+       case GL_RGB10_A2:
+       case GL_RGBA12:
+       case GL_RGBA16:
+       case GL_RGBA8:
+       case GL_RGB:
+       case GL_RGB8:
+       case GL_RGB10:
+       case GL_RGB12:
+       case GL_RGB16:
+               return MESA_FORMAT_ARGB8888;
+       case GL_RGB5_A1:
+               return MESA_FORMAT_ARGB1555;
+       case GL_RGBA2:
+       case GL_RGBA4:
+               return MESA_FORMAT_ARGB4444;
+
+       case 3:
+       case GL_R3_G3_B2:
+       case GL_RGB4:
+       case GL_RGB5:
+               return MESA_FORMAT_RGB565;
+
+       case GL_ALPHA:
+       case GL_ALPHA4:
+       case GL_ALPHA12:
+       case GL_ALPHA16:
+       case GL_ALPHA8:
+               return MESA_FORMAT_A8;
+
+       case 1:
+       case GL_LUMINANCE:
+       case GL_LUMINANCE4:
+       case GL_LUMINANCE12:
+       case GL_LUMINANCE16:
+       case GL_LUMINANCE8:
+               return MESA_FORMAT_L8;
+
+       case 2:
+       case GL_LUMINANCE_ALPHA:
+       case GL_LUMINANCE4_ALPHA4:
+       case GL_LUMINANCE6_ALPHA2:
+       case GL_LUMINANCE12_ALPHA4:
+       case GL_LUMINANCE12_ALPHA12:
+       case GL_LUMINANCE16_ALPHA16:
+       case GL_LUMINANCE8_ALPHA8:
+               return MESA_FORMAT_ARGB8888;
+
+       case GL_INTENSITY:
+       case GL_INTENSITY4:
+       case GL_INTENSITY12:
+       case GL_INTENSITY16:
+       case GL_INTENSITY8:
+               return MESA_FORMAT_ARGB8888;
+
+       case GL_COLOR_INDEX:
+       case GL_COLOR_INDEX1_EXT:
+       case GL_COLOR_INDEX2_EXT:
+       case GL_COLOR_INDEX4_EXT:
+       case GL_COLOR_INDEX12_EXT:
+       case GL_COLOR_INDEX16_EXT:
+       case GL_COLOR_INDEX8_EXT:
+               return MESA_FORMAT_CI8;
+
+       default:
+               assert(0);
+       }
+}
+
+static void
+nouveau_teximage(GLcontext *ctx, GLint dims, GLenum target, GLint level,
+                GLint internalFormat,
+                GLint width, GLint height, GLint depth, GLint border,
+                GLenum format, GLenum type, const GLvoid *pixels,
+                const struct gl_pixelstore_attrib *packing,
+                struct gl_texture_object *t,
+                struct gl_texture_image *ti)
+{
+       struct nouveau_surface *s = &to_nouveau_teximage(ti)->surface;
+       unsigned bo_flags = NOUVEAU_BO_GART | NOUVEAU_BO_RDWR | NOUVEAU_BO_MAP;
+       int ret;
+
+       /* Allocate a new bo for the image. */
+       nouveau_surface_alloc(ctx, s, LINEAR, bo_flags, ti->TexFormat,
+                             width, height);
+       ti->RowStride = s->pitch / s->cpp;
+
+       pixels = _mesa_validate_pbo_teximage(ctx, dims, width, height, depth,
+                                            format, type, pixels, packing,
+                                            "glTexImage");
+       if (!pixels)
+               return;
+
+       /* Store the pixel data. */
+       nouveau_teximage_map(ctx, ti);
+
+       ret = _mesa_texstore(ctx, dims, ti->_BaseFormat,
+                            ti->TexFormat, ti->Data,
+                            0, 0, 0, s->pitch,
+                            ti->ImageOffsets,
+                            width, height, depth,
+                            format, type, pixels, packing);
+       assert(ret);
+
+       nouveau_teximage_unmap(ctx, ti);
+       _mesa_unmap_teximage_pbo(ctx, packing);
+
+       context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit);
+       context_dirty_i(ctx, TEX_ENV, ctx->Texture.CurrentUnit);
+       texture_dirty(t);
+}
+
+static void
+nouveau_teximage_1d(GLcontext *ctx, GLenum target, GLint level,
+                   GLint internalFormat,
+                   GLint width, GLint border,
+                   GLenum format, GLenum type, const GLvoid *pixels,
+                   const struct gl_pixelstore_attrib *packing,
+                   struct gl_texture_object *t,
+                   struct gl_texture_image *ti)
+{
+       nouveau_teximage(ctx, 1, target, level, internalFormat,
+                        width, 1, 1, border, format, type, pixels,
+                        packing, t, ti);
+}
+
+static void
+nouveau_teximage_2d(GLcontext *ctx, GLenum target, GLint level,
+                   GLint internalFormat,
+                   GLint width, GLint height, GLint border,
+                   GLenum format, GLenum type, const GLvoid *pixels,
+                   const struct gl_pixelstore_attrib *packing,
+                   struct gl_texture_object *t,
+                   struct gl_texture_image *ti)
+{
+       nouveau_teximage(ctx, 2, target, level, internalFormat,
+                        width, height, 1, border, format, type, pixels,
+                        packing, t, ti);
+}
+
+static void
+nouveau_teximage_3d(GLcontext *ctx, GLenum target, GLint level,
+                   GLint internalFormat,
+                   GLint width, GLint height, GLint depth, GLint border,
+                   GLenum format, GLenum type, const GLvoid *pixels,
+                   const struct gl_pixelstore_attrib *packing,
+                   struct gl_texture_object *t,
+                   struct gl_texture_image *ti)
+{
+       nouveau_teximage(ctx, 3, target, level, internalFormat,
+                        width, height, depth, border, format, type, pixels,
+                        packing, t, ti);
+}
+
+static void
+nouveau_texsubimage_3d(GLcontext *ctx, GLenum target, GLint level,
+                      GLint xoffset, GLint yoffset, GLint zoffset,
+                      GLint width, GLint height, GLint depth,
+                      GLenum format, GLenum type, const void *pixels,
+                      const struct gl_pixelstore_attrib *packing,
+                      struct gl_texture_object *t,
+                      struct gl_texture_image *ti)
+{
+       nouveau_teximage_map(ctx, ti);
+       _mesa_store_texsubimage3d(ctx, target, level, xoffset, yoffset, zoffset,
+                                 width, height, depth, format, type, pixels,
+                                 packing, t, ti);
+       nouveau_teximage_unmap(ctx, ti);
+
+       context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit);
+       texture_dirty(t);
+}
+
+static void
+nouveau_texsubimage_2d(GLcontext *ctx, GLenum target, GLint level,
+                      GLint xoffset, GLint yoffset,
+                      GLint width, GLint height,
+                      GLenum format, GLenum type, const void *pixels,
+                      const struct gl_pixelstore_attrib *packing,
+                      struct gl_texture_object *t,
+                      struct gl_texture_image *ti)
+{
+       nouveau_teximage_map(ctx, ti);
+       _mesa_store_texsubimage2d(ctx, target, level, xoffset, yoffset,
+                                 width, height, format, type, pixels,
+                                 packing, t, ti);
+       nouveau_teximage_unmap(ctx, ti);
+
+       context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit);
+       texture_dirty(t);
+}
+
+static void
+nouveau_texsubimage_1d(GLcontext *ctx, GLenum target, GLint level,
+                      GLint xoffset, GLint width,
+                      GLenum format, GLenum type, const void *pixels,
+                      const struct gl_pixelstore_attrib *packing,
+                      struct gl_texture_object *t,
+                      struct gl_texture_image *ti)
+{
+       nouveau_teximage_map(ctx, ti);
+       _mesa_store_texsubimage1d(ctx, target, level, xoffset,
+                                 width, format, type, pixels,
+                                 packing, t, ti);
+       nouveau_teximage_unmap(ctx, ti);
+
+       context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit);
+       texture_dirty(t);
+}
+
+static void
+nouveau_get_teximage(GLcontext *ctx, GLenum target, GLint level,
+                    GLenum format, GLenum type, GLvoid *pixels,
+                    struct gl_texture_object *t,
+                    struct gl_texture_image *ti)
+{
+       nouveau_teximage_map(ctx, ti);
+       _mesa_get_teximage(ctx, target, level, format, type, pixels,
+                          t, ti);
+       nouveau_teximage_unmap(ctx, ti);
+}
+
+static void
+nouveau_bind_texture(GLcontext *ctx, GLenum target,
+                    struct gl_texture_object *t)
+{
+       context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit);
+       context_dirty_i(ctx, TEX_ENV, ctx->Texture.CurrentUnit);
+}
+
+static void
+nouveau_texture_map(GLcontext *ctx, struct gl_texture_object *t)
+{
+       int i;
+
+       for (i = t->BaseLevel; i < t->_MaxLevel; i++) {
+               if (t->Image[0][i])
+                       nouveau_teximage_map(ctx, t->Image[0][i]);
+       }
+}
+
+static void
+nouveau_texture_unmap(GLcontext *ctx, struct gl_texture_object *t)
+{
+       int i;
+
+       for (i = t->BaseLevel; i < t->_MaxLevel; i++) {
+               if (t->Image[0][i])
+                       nouveau_teximage_unmap(ctx, t->Image[0][i]);
+       }
+}
+
+static void
+relayout_miptree(GLcontext *ctx, struct gl_texture_object *t)
+{
+       struct nouveau_surface *ss = to_nouveau_texture(t)->surfaces;
+       unsigned last_level, offset = 0;
+       unsigned size;
+       int i, ret;
+
+       if (t->MinFilter == GL_NEAREST ||
+           t->MinFilter == GL_LINEAR)
+               last_level = t->BaseLevel;
+       else
+               last_level = t->_MaxLevel;
+
+       /* Deallocate the old storage. */
+       for (i = 0; i < MAX_TEXTURE_LEVELS; i++)
+               nouveau_bo_ref(NULL, &ss[i].bo);
+
+       /* Relayout the mipmap tree. */
+       for (i = t->BaseLevel; i <= last_level; i++) {
+               struct nouveau_surface *s =
+                       &to_nouveau_teximage(t->Image[0][i])->surface;
+
+               size = s->width * s->height * s->cpp;
+
+               /* Images larger than 16B have to be aligned. */
+               if (size > 16)
+                       offset = align(offset, 64);
+
+               ss[i] = (struct nouveau_surface) {
+                       .offset = offset,
+                       .layout = SWIZZLED,
+                       .format = s->format,
+                       .width = s->width,
+                       .height = s->height,
+                       .cpp = s->cpp,
+                       .pitch = s->width * s->cpp,
+               };
+
+               offset += size;
+       }
+
+       /* Get new storage. */
+       size = align(offset, 64);
+
+       ret = nouveau_bo_new(context_dev(ctx),
+                            NOUVEAU_BO_GART | NOUVEAU_BO_VRAM,
+                            0, size, &ss[last_level].bo);
+       assert(!ret);
+
+       for (i = t->BaseLevel; i < last_level; i++)
+               nouveau_bo_ref(ss[last_level].bo, &ss[i].bo);
+}
+
+void
+nouveau_texture_validate(GLcontext *ctx, struct gl_texture_object *t)
+{
+       struct nouveau_texture *nt = to_nouveau_texture(t);
+       int i;
+
+       if (!nt->dirty)
+               return;
+
+       nt->dirty = GL_FALSE;
+
+       relayout_miptree(ctx, t);
+
+       /* Copy the teximages to the actual swizzled miptree. */
+       for (i = t->BaseLevel; i < MAX_TEXTURE_LEVELS; i++) {
+               struct gl_texture_image *ti = t->Image[0][i];
+               struct nouveau_surface *s = &to_nouveau_teximage(ti)->surface;
+
+               if (!nt->surfaces[i].bo)
+                       break;
+
+               context_drv(ctx)->surface_copy(ctx, &nt->surfaces[i], s,
+                                              0, 0, 0, 0,
+                                              s->width, s->height);
+       }
+}
+
+void
+nouveau_texture_functions_init(struct dd_function_table *functions)
+{
+       functions->NewTextureObject = nouveau_texture_new;
+       functions->DeleteTexture = nouveau_texture_free;
+       functions->NewTextureImage = nouveau_teximage_new;
+       functions->FreeTexImageData = nouveau_teximage_free;
+       functions->ChooseTextureFormat = nouveau_choose_tex_format;
+       functions->TexImage1D = nouveau_teximage_1d;
+       functions->TexImage2D = nouveau_teximage_2d;
+       functions->TexImage3D = nouveau_teximage_3d;
+       functions->TexSubImage1D = nouveau_texsubimage_1d;
+       functions->TexSubImage2D = nouveau_texsubimage_2d;
+       functions->TexSubImage3D = nouveau_texsubimage_3d;
+       functions->GetTexImage = nouveau_get_teximage;
+       functions->BindTexture = nouveau_bind_texture;
+       functions->MapTexture = nouveau_texture_map;
+       functions->UnmapTexture = nouveau_texture_unmap;
+}
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_texture.h b/src/mesa/drivers/dri/nouveau/nouveau_texture.h
new file mode 100644 (file)
index 0000000..695c089
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2009 Francisco Jerez.
+ * 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.
+ *
+ */
+
+#ifndef __NOUVEAU_TEXTURE_H__
+#define __NOUVEAU_TEXTURE_H__
+
+struct nouveau_teximage {
+       struct gl_texture_image base;
+       struct nouveau_surface surface;
+};
+#define to_nouveau_teximage(x) ((struct nouveau_teximage *)(x))
+
+struct nouveau_texture {
+       struct gl_texture_object base;
+       struct nouveau_surface surfaces[MAX_TEXTURE_LEVELS];
+       GLboolean dirty;
+};
+#define to_nouveau_texture(x) ((struct nouveau_texture *)(x))
+
+#define texture_dirty(t) \
+       to_nouveau_texture(t)->dirty = GL_TRUE;
+
+void
+nouveau_texture_validate(GLcontext *ctx, struct gl_texture_object *t);
+
+#endif
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_util.h b/src/mesa/drivers/dri/nouveau/nouveau_util.h
new file mode 100644 (file)
index 0000000..076f225
--- /dev/null
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2009 Francisco Jerez.
+ * 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.
+ *
+ */
+
+#ifndef __NOUVEAU_UTIL_H__
+#define __NOUVEAU_UTIL_H__
+
+#include "main/formats.h"
+#include "main/colormac.h"
+
+static inline unsigned
+pack_rgba_i(gl_format f, uint8_t c[])
+{
+       switch (f) {
+       case MESA_FORMAT_ARGB8888:
+               return PACK_COLOR_8888(c[ACOMP], c[RCOMP], c[GCOMP], c[BCOMP]);
+       case MESA_FORMAT_ARGB8888_REV:
+               return PACK_COLOR_8888(c[BCOMP], c[GCOMP], c[RCOMP], c[ACOMP]);
+       case MESA_FORMAT_XRGB8888:
+               return PACK_COLOR_8888(0, c[RCOMP], c[GCOMP], c[BCOMP]);
+       case MESA_FORMAT_XRGB8888_REV:
+               return PACK_COLOR_8888(c[BCOMP], c[GCOMP], c[RCOMP], 0);
+       case MESA_FORMAT_RGBA8888:
+               return PACK_COLOR_8888(c[RCOMP], c[GCOMP], c[BCOMP], c[ACOMP]);
+       case MESA_FORMAT_RGBA8888_REV:
+               return PACK_COLOR_8888(c[ACOMP], c[BCOMP], c[GCOMP], c[RCOMP]);
+       case MESA_FORMAT_RGB565:
+               return PACK_COLOR_565(c[RCOMP], c[GCOMP], c[BCOMP]);
+       default:
+               assert(0);
+       }
+}
+
+static inline unsigned
+pack_zs_i(gl_format f, uint32_t z, uint8_t s)
+{
+       switch (f) {
+       case MESA_FORMAT_Z24_S8:
+               return (z & 0xffffff00) | (s & 0xff);
+       case MESA_FORMAT_Z24_X8:
+               return (z & 0xffffff00);
+       case MESA_FORMAT_Z16:
+               return (z & 0xffff0000) >> 16;
+       default:
+               assert(0);
+       }
+}
+
+static inline unsigned
+pack_rgba_f(gl_format f, float c[])
+{
+       return pack_rgba_i(f, (uint8_t []) {
+                          FLOAT_TO_UBYTE(c[RCOMP]),
+                          FLOAT_TO_UBYTE(c[GCOMP]),
+                          FLOAT_TO_UBYTE(c[BCOMP]),
+                          FLOAT_TO_UBYTE(c[ACOMP]) });
+}
+
+static inline unsigned
+pack_zs_f(gl_format f, float z, uint8_t s)
+{
+       return pack_zs_i(f, FLOAT_TO_UINT(z), s);
+}
+
+/* Integer base-2 logarithm, rounded towards zero. */
+static inline unsigned
+log2i(unsigned i)
+{
+       unsigned r = 0;
+
+       if (i & 0xffff0000) {
+               i >>= 16;
+               r += 16;
+       }
+       if (i & 0x0000ff00) {
+               i >>= 8;
+               r += 8;
+       }
+       if (i & 0x000000f0) {
+               i >>= 4;
+               r += 4;
+       }
+       if (i & 0x0000000c) {
+               i >>= 2;
+               r += 2;
+       }
+       if (i & 0x00000002) {
+               r += 1;
+       }
+       return r;
+}
+
+static inline unsigned
+align(unsigned x, unsigned m)
+{
+       return (x + m - 1) & ~(m - 1);
+}
+
+static inline void
+get_scissors(struct gl_framebuffer *fb, int *x, int *y, int *w, int *h)
+{
+       *w = fb->_Xmax - fb->_Xmin;
+       *h = fb->_Ymax - fb->_Ymin;
+       *x = fb->_Xmin;
+       *y = (fb->Name ? fb->_Ymin :
+             /* Window system FBO: Flip the Y coordinate. */
+             fb->Height - fb->_Ymax);
+}
+
+static inline void
+get_viewport_scale(GLcontext *ctx, float a[16])
+{
+       struct gl_viewport_attrib *vp = &ctx->Viewport;
+       struct gl_framebuffer *fb = ctx->DrawBuffer;
+
+       a[MAT_SX] = (float)vp->Width / 2;
+
+       if (fb->Name)
+               a[MAT_SY] = (float)vp->Height / 2;
+       else
+               /* Window system FBO: Flip the Y coordinate. */
+               a[MAT_SY] = - (float)vp->Height / 2;
+
+       a[MAT_SZ] = fb->_DepthMaxF * (vp->Far - vp->Near) / 2;
+}
+
+static inline void
+get_viewport_translate(GLcontext *ctx, float a[4])
+{
+       struct gl_viewport_attrib *vp = &ctx->Viewport;
+       struct gl_framebuffer *fb = ctx->DrawBuffer;
+
+       a[0] = (float)vp->Width / 2 + vp->X;
+
+       if (fb->Name)
+               a[1] = (float)vp->Height / 2 + vp->Y;
+       else
+               /* Window system FBO: Flip the Y coordinate. */
+               a[1] = fb->Height - (float)vp->Height / 2 - vp->Y;
+
+       a[2] = fb->_DepthMaxF * (vp->Far + vp->Near) / 2;
+}
+
+static inline void
+OUT_RINGm(struct nouveau_channel *chan, float m[16])
+{
+       int i, j;
+
+       for (i = 0; i < 4; i++)
+               for (j = 0; j < 4; j++)
+                       OUT_RINGf(chan, m[4*j + i]);
+}
+
+#endif
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_vbo_t.c b/src/mesa/drivers/dri/nouveau/nouveau_vbo_t.c
new file mode 100644 (file)
index 0000000..ba1192a
--- /dev/null
@@ -0,0 +1,409 @@
+/*
+ * Copyright (C) 2009-2010 Francisco Jerez.
+ * 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.
+ *
+ */
+
+#include "main/bufferobj.h"
+#include "nouveau_bufferobj.h"
+
+/* Arbitrary pushbuf length we can assume we can get with a single
+ * WAIT_RING. */
+#define PUSHBUF_DWORDS 2048
+
+/* Functions to set up struct nouveau_array_state from something like
+ * a GL array or index buffer. */
+
+static void
+vbo_init_array(struct nouveau_array_state *a, int attr, int stride,
+              int fields, int type, struct gl_buffer_object *obj,
+              const void *ptr, GLboolean map)
+{
+       a->attr = attr;
+       a->stride = stride;
+       a->fields = fields;
+       a->type = type;
+
+       if (_mesa_is_bufferobj(obj)) {
+               nouveau_bo_ref(to_nouveau_bufferobj(obj)->bo, &a->bo);
+               a->offset = (intptr_t)ptr;
+
+               if (map) {
+                       nouveau_bo_map(a->bo, NOUVEAU_BO_RD);
+                       a->buf = a->bo->map + a->offset;
+               } else {
+                       a->buf = NULL;
+               }
+
+       } else {
+               nouveau_bo_ref(NULL, &a->bo);
+               a->offset = 0;
+               a->buf = ptr;
+       }
+
+       if (a->buf)
+               get_array_extract(a, &a->extract_u, &a->extract_f);
+}
+
+static void
+vbo_deinit_array(struct nouveau_array_state *a)
+{
+       if (a->bo) {
+               if (a->bo->map)
+                       nouveau_bo_unmap(a->bo);
+               nouveau_bo_ref(NULL, &a->bo);
+       }
+
+       a->buf = NULL;
+       a->fields = 0;
+}
+
+static void
+vbo_init_arrays(GLcontext *ctx, const struct _mesa_index_buffer *ib,
+               const struct gl_client_array **arrays)
+{
+       struct nouveau_render_state *render = to_render_state(ctx);
+       int i;
+
+       if (ib)
+               vbo_init_array(&render->ib, 0, 0, ib->count, ib->type,
+                              ib->obj, ib->ptr, GL_TRUE);
+
+       for (i = 0; i < render->attr_count; i++) {
+               int attr = render->map[i];
+
+               if (attr >= 0) {
+                       const struct gl_client_array *array = arrays[attr];
+
+                       vbo_init_array(&render->attrs[attr], attr,
+                                      array->StrideB, array->Size,
+                                      array->Type, array->BufferObj,
+                                      array->Ptr, render->mode == IMM);
+               }
+       }
+}
+
+static void
+vbo_deinit_arrays(GLcontext *ctx, const struct _mesa_index_buffer *ib,
+               const struct gl_client_array **arrays)
+{
+       struct nouveau_render_state *render = to_render_state(ctx);
+       int i;
+
+       if (ib)
+               vbo_deinit_array(&render->ib);
+
+       for (i = 0; i < render->attr_count; i++) {
+               int *attr = &render->map[i];
+
+               if (*attr >= 0) {
+                       vbo_deinit_array(&render->attrs[*attr]);
+                       *attr = -1;
+               }
+       }
+
+       render->attr_count = 0;
+}
+
+/* Make some rendering decisions from the GL context. */
+
+static void
+vbo_choose_render_mode(GLcontext *ctx, const struct gl_client_array **arrays)
+{
+       struct nouveau_render_state *render = to_render_state(ctx);
+       int i;
+
+       render->mode = VBO;
+
+       if (ctx->Light.Enabled) {
+               for (i = 0; i < MAT_ATTRIB_MAX; i++) {
+                       if (arrays[VERT_ATTRIB_GENERIC0 + i]->StrideB) {
+                               render->mode = IMM;
+                               break;
+                       }
+               }
+       }
+
+       if (render->mode == VBO)
+               render->attr_count = NUM_VERTEX_ATTRS;
+       else
+               render->attr_count = 0;
+}
+
+static void
+vbo_emit_attr(GLcontext *ctx, const struct gl_client_array **arrays, int attr)
+{
+       struct nouveau_channel *chan = context_chan(ctx);
+       struct nouveau_render_state *render = to_render_state(ctx);
+       const struct gl_client_array *array = arrays[attr];
+       struct nouveau_array_state *a = &render->attrs[attr];
+       RENDER_LOCALS(ctx);
+
+       if (!array->StrideB) {
+               if (attr >= VERT_ATTRIB_GENERIC0)
+                       /* nouveau_update_state takes care of materials. */
+                       return;
+
+               /* Constant attribute. */
+               vbo_init_array(a, attr, array->StrideB, array->Size,
+                              array->Type, array->BufferObj, array->Ptr,
+                              GL_TRUE);
+               EMIT_IMM(ctx, a, 0);
+               vbo_deinit_array(a);
+
+       } else {
+               /* Varying attribute. */
+               struct nouveau_attr_info *info = &TAG(vertex_attrs)[attr];
+
+               if (render->mode == VBO) {
+                       render->map[info->vbo_index] = attr;
+                       render->vertex_size += array->_ElementSize;
+               } else {
+                       render->map[render->attr_count++] = attr;
+                       render->vertex_size += 4 * info->imm_fields;
+               }
+       }
+}
+
+#define MAT(a) (VERT_ATTRIB_GENERIC0 + MAT_ATTRIB_##a)
+
+static void
+vbo_choose_attrs(GLcontext *ctx, const struct gl_client_array **arrays)
+{
+       struct nouveau_render_state *render = to_render_state(ctx);
+       int i;
+
+       /* Reset the vertex size. */
+       render->vertex_size = 0;
+
+       vbo_emit_attr(ctx, arrays, VERT_ATTRIB_COLOR0);
+       if (ctx->Fog.ColorSumEnabled && !ctx->Light.Enabled)
+               vbo_emit_attr(ctx, arrays, VERT_ATTRIB_COLOR1);
+
+       for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) {
+               if (ctx->Texture._EnabledCoordUnits & (1 << i))
+                       vbo_emit_attr(ctx, arrays, VERT_ATTRIB_TEX0 + i);
+       }
+
+       if (ctx->Fog.Enabled && ctx->Fog.FogCoordinateSource == GL_FOG_COORD)
+               vbo_emit_attr(ctx, arrays, VERT_ATTRIB_FOG);
+
+       if (ctx->Light.Enabled) {
+               vbo_emit_attr(ctx, arrays, VERT_ATTRIB_NORMAL);
+
+               vbo_emit_attr(ctx, arrays, MAT(FRONT_AMBIENT));
+               vbo_emit_attr(ctx, arrays, MAT(FRONT_DIFFUSE));
+               vbo_emit_attr(ctx, arrays, MAT(FRONT_SPECULAR));
+               vbo_emit_attr(ctx, arrays, MAT(FRONT_SHININESS));
+
+               if (ctx->Light.Model.TwoSide) {
+                       vbo_emit_attr(ctx, arrays, MAT(BACK_AMBIENT));
+                       vbo_emit_attr(ctx, arrays, MAT(BACK_DIFFUSE));
+                       vbo_emit_attr(ctx, arrays, MAT(BACK_SPECULAR));
+                       vbo_emit_attr(ctx, arrays, MAT(BACK_SHININESS));
+               }
+       }
+
+       vbo_emit_attr(ctx, arrays, VERT_ATTRIB_POS);
+}
+
+static void
+TAG(vbo_render_prims)(GLcontext *ctx, const struct gl_client_array **arrays,
+                     const struct _mesa_prim *prims, GLuint nr_prims,
+                     const struct _mesa_index_buffer *ib,
+                     GLboolean index_bounds_valid,
+                     GLuint min_index, GLuint max_index);
+
+static GLboolean
+vbo_maybe_split(GLcontext *ctx, const struct gl_client_array **arrays,
+           const struct _mesa_prim *prims, GLuint nr_prims,
+           const struct _mesa_index_buffer *ib,
+           GLuint min_index, GLuint max_index)
+{
+       struct nouveau_context *nctx = to_nouveau_context(ctx);
+       unsigned pushbuf_avail = PUSHBUF_DWORDS - 2 * nctx->bo.count,
+               vert_avail = get_max_vertices(ctx, NULL, pushbuf_avail),
+               idx_avail = get_max_vertices(ctx, ib, pushbuf_avail);
+
+       if ((ib && ib->count > idx_avail) ||
+           (!ib && max_index - min_index > vert_avail)) {
+               struct split_limits limits = {
+                       .max_verts = vert_avail,
+                       .max_indices = idx_avail,
+                       .max_vb_size = ~0,
+               };
+
+               vbo_split_prims(ctx, arrays, prims, nr_prims, ib, min_index,
+                               max_index, TAG(vbo_render_prims), &limits);
+               return GL_TRUE;
+       }
+
+       return GL_FALSE;
+}
+
+/* VBO rendering path. */
+
+static void
+vbo_bind_vertices(GLcontext *ctx, const struct gl_client_array **arrays,
+                 GLint basevertex, GLuint min_index, GLuint max_index)
+{
+       struct nouveau_render_state *render = to_render_state(ctx);
+       int i;
+
+       for (i = 0; i < NUM_VERTEX_ATTRS; i++) {
+               int attr = render->map[i];
+
+               if (attr >= 0) {
+                       const struct gl_client_array *array = arrays[attr];
+                       struct nouveau_array_state *a = &render->attrs[attr];
+                       unsigned delta = (basevertex + min_index) * a->stride,
+                               size = (max_index - min_index + 1) * a->stride;
+
+                       if (a->bo) {
+                               a->offset = (intptr_t)array->Ptr + delta;
+                       } else {
+                               void *scratch = get_scratch_vbo(ctx, size,
+                                                               &a->bo,
+                                                               &a->offset);
+
+                               memcpy(scratch, a->buf + delta, size);
+                       }
+               }
+       }
+
+       TAG(render_bind_vertices)(ctx);
+}
+
+static void
+vbo_draw_vbo(GLcontext *ctx, const struct gl_client_array **arrays,
+            const struct _mesa_prim *prims, GLuint nr_prims,
+            const struct _mesa_index_buffer *ib, GLuint min_index,
+            GLuint max_index)
+{
+       struct nouveau_channel *chan = context_chan(ctx);
+       dispatch_t dispatch;
+       int delta = -min_index, basevertex = 0, i;
+       RENDER_LOCALS(ctx);
+
+       get_array_dispatch(&to_render_state(ctx)->ib, &dispatch);
+
+       TAG(render_set_format)(ctx);
+
+       for (i = 0; i < nr_prims; i++) {
+               unsigned start = prims[i].start,
+                       count = prims[i].count;
+
+               if (i == 0 || basevertex != prims[i].basevertex) {
+                       basevertex = prims[i].basevertex;
+                       vbo_bind_vertices(ctx, arrays, basevertex,
+                                         min_index, max_index);
+               }
+
+               if (count > get_max_vertices(ctx, ib, chan->pushbuf->remaining))
+                       WAIT_RING(chan, PUSHBUF_DWORDS);
+
+               BATCH_BEGIN(nvgl_primitive(prims[i].mode));
+               dispatch(ctx, start, delta, count);
+               BATCH_END();
+       }
+
+       FIRE_RING(chan);
+}
+
+/* Immediate rendering path. */
+
+static unsigned
+extract_id(struct nouveau_array_state *a, int i, int j)
+{
+       return j;
+}
+
+static void
+vbo_draw_imm(GLcontext *ctx, const struct gl_client_array **arrays,
+            const struct _mesa_prim *prims, GLuint nr_prims,
+            const struct _mesa_index_buffer *ib, GLuint min_index,
+            GLuint max_index)
+{
+       struct nouveau_render_state *render = to_render_state(ctx);
+       struct nouveau_channel *chan = context_chan(ctx);
+       extract_u_t extract = ib ? render->ib.extract_u : extract_id;
+       int i, j, k;
+       RENDER_LOCALS(ctx);
+
+       for (i = 0; i < nr_prims; i++) {
+               unsigned start = prims[i].start,
+                       end = start + prims[i].count;
+
+               if (prims[i].count > get_max_vertices(ctx, ib,
+                                                     chan->pushbuf->remaining))
+                       WAIT_RING(chan, PUSHBUF_DWORDS);
+
+               BATCH_BEGIN(nvgl_primitive(prims[i].mode));
+
+               for (; start < end; start++) {
+                       j = prims[i].basevertex +
+                               extract(&render->ib, 0, start);
+
+                       for (k = 0; k < render->attr_count; k++)
+                               EMIT_IMM(ctx, &render->attrs[render->map[k]],
+                                        j);
+               }
+
+               BATCH_END();
+       }
+
+       FIRE_RING(chan);
+}
+
+/* draw_prims entry point when we're doing hw-tnl. */
+
+static void
+TAG(vbo_render_prims)(GLcontext *ctx, const struct gl_client_array **arrays,
+                     const struct _mesa_prim *prims, GLuint nr_prims,
+                     const struct _mesa_index_buffer *ib,
+                     GLboolean index_bounds_valid,
+                     GLuint min_index, GLuint max_index)
+{
+       struct nouveau_render_state *render = to_render_state(ctx);
+
+       if (!index_bounds_valid)
+               vbo_get_minmax_index(ctx, prims, ib, &min_index, &max_index);
+
+       vbo_choose_render_mode(ctx, arrays);
+       vbo_choose_attrs(ctx, arrays);
+
+       if (vbo_maybe_split(ctx, arrays, prims, nr_prims, ib, min_index,
+                           max_index))
+               return;
+
+       vbo_init_arrays(ctx, ib, arrays);
+
+       if (render->mode == VBO)
+               vbo_draw_vbo(ctx, arrays, prims, nr_prims, ib, min_index,
+                            max_index);
+       else
+               vbo_draw_imm(ctx, arrays, prims, nr_prims, ib, min_index,
+                            max_index);
+
+       vbo_deinit_arrays(ctx, ib, arrays);
+}
diff --git a/src/mesa/drivers/dri/nouveau/nv04_context.c b/src/mesa/drivers/dri/nouveau/nv04_context.c
new file mode 100644 (file)
index 0000000..5548286
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2009 Francisco Jerez.
+ * 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.
+ *
+ */
+
+#include "nouveau_driver.h"
+#include "nouveau_context.h"
+#include "nouveau_fbo.h"
+#include "nouveau_util.h"
+#include "nouveau_class.h"
+#include "nv04_driver.h"
+
+struct nouveau_grobj *
+nv04_context_engine(GLcontext *ctx)
+{
+       struct nv04_context *nctx = to_nv04_context(ctx);
+       struct nouveau_screen *screen = nctx->base.screen;
+       struct nouveau_grobj *fahrenheit;
+
+       if (ctx->Texture.Unit[0].EnvMode == GL_COMBINE ||
+           ctx->Texture.Unit[0].EnvMode == GL_BLEND ||
+           ctx->Texture.Unit[1]._ReallyEnabled ||
+           ctx->Stencil.Enabled)
+               fahrenheit = screen->eng3dm;
+       else
+               fahrenheit = screen->eng3d;
+
+       if (fahrenheit != nctx->eng3d) {
+               nctx->eng3d = fahrenheit;
+
+               if (nv04_mtex_engine(fahrenheit)) {
+                       context_dirty_i(ctx, TEX_ENV, 0);
+                       context_dirty_i(ctx, TEX_ENV, 1);
+                       context_dirty_i(ctx, TEX_OBJ, 0);
+                       context_dirty_i(ctx, TEX_OBJ, 1);
+                       context_dirty(ctx, CONTROL);
+                       context_dirty(ctx, BLEND);
+               } else {
+                       context_bctx_i(ctx, TEXTURE, 1);
+                       context_dirty_i(ctx, TEX_ENV, 0);
+                       context_dirty_i(ctx, TEX_OBJ, 0);
+                       context_dirty(ctx, CONTROL);
+                       context_dirty(ctx, BLEND);
+               }
+       }
+
+       return fahrenheit;
+}
+
+static void
+init_dummy_texture(GLcontext *ctx)
+{
+       struct nouveau_surface *s = &to_nv04_context(ctx)->dummy_texture;
+
+       nouveau_surface_alloc(ctx, s, SWIZZLED,
+                             NOUVEAU_BO_MAP | NOUVEAU_BO_VRAM,
+                             MESA_FORMAT_ARGB8888, 1, 1);
+
+       nouveau_bo_map(s->bo, NOUVEAU_BO_WR);
+       *(uint32_t *)s->bo->map = 0xffffffff;
+       nouveau_bo_unmap(s->bo);
+}
+
+GLcontext *
+nv04_context_create(struct nouveau_screen *screen, const GLvisual *visual,
+                   GLcontext *share_ctx)
+{
+       struct nv04_context *nctx;
+       GLcontext *ctx;
+
+       nctx = CALLOC_STRUCT(nv04_context);
+       if (!nctx)
+               return NULL;
+
+       ctx = &nctx->base.base;
+       nouveau_context_init(ctx, screen, visual, share_ctx);
+
+       ctx->Const.MaxTextureCoordUnits = NV04_TEXTURE_UNITS;
+       ctx->Const.MaxTextureImageUnits = NV04_TEXTURE_UNITS;
+       ctx->Const.MaxTextureUnits = NV04_TEXTURE_UNITS;
+       ctx->Const.MaxTextureMaxAnisotropy = 2;
+       ctx->Const.MaxTextureLodBias = 15;
+
+       init_dummy_texture(ctx);
+       nv04_render_init(ctx);
+
+       return ctx;
+}
+
+void
+nv04_context_destroy(GLcontext *ctx)
+{
+       nv04_render_destroy(ctx);
+       nouveau_surface_ref(NULL, &to_nv04_context(ctx)->dummy_texture);
+
+       FREE(ctx);
+}
diff --git a/src/mesa/drivers/dri/nouveau/nv04_context.h b/src/mesa/drivers/dri/nouveau/nv04_context.h
new file mode 100644 (file)
index 0000000..ed4eec9
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2009 Francisco Jerez.
+ * 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.
+ *
+ */
+
+#ifndef __NV04_CONTEXT_H__
+#define __NV04_CONTEXT_H__
+
+#include "nouveau_context.h"
+
+struct nv04_context {
+       struct nouveau_context base;
+       struct nouveau_grobj *eng3d;
+       struct nouveau_surface dummy_texture;
+       float viewport[16];
+};
+#define to_nv04_context(ctx) ((struct nv04_context *)(ctx))
+
+#define nv04_mtex_engine(obj) ((obj)->grclass == NV04_MULTITEX_TRIANGLE)
+
+struct nouveau_grobj *
+nv04_context_engine(GLcontext *ctx);
+
+GLcontext *
+nv04_context_create(struct nouveau_screen *screen, const GLvisual *visual,
+                   GLcontext *share_ctx);
+
+void
+nv04_context_destroy(GLcontext *ctx);
+
+#endif
diff --git a/src/mesa/drivers/dri/nouveau/nv04_driver.h b/src/mesa/drivers/dri/nouveau/nv04_driver.h
new file mode 100644 (file)
index 0000000..0066871
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2009 Francisco Jerez.
+ * 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.
+ *
+ */
+
+#ifndef __NV04_DRIVER_H__
+#define __NV04_DRIVER_H__
+
+#include "nv04_context.h"
+
+enum {
+       NOUVEAU_STATE_BLEND = NUM_NOUVEAU_STATE,
+       NOUVEAU_STATE_CONTROL,
+       NUM_NV04_STATE
+};
+
+#define NV04_TEXTURE_UNITS 2
+
+/* nv04_screen.c */
+GLboolean
+nv04_screen_init(struct nouveau_screen *screen);
+
+/* nv04_render.c */
+void
+nv04_render_init(GLcontext *ctx);
+
+void
+nv04_render_destroy(GLcontext *ctx);
+
+/* nv04_surface.c */
+GLboolean
+nv04_surface_init(struct nouveau_screen *screen);
+
+void
+nv04_surface_takedown(struct nouveau_screen *screen);
+
+void
+nv04_surface_copy(GLcontext *ctx,
+                 struct nouveau_surface *dst, struct nouveau_surface *src,
+                 int dx, int dy, int sx, int sy, int w, int h);
+
+void
+nv04_surface_fill(GLcontext *ctx,
+                 struct nouveau_surface *dst,
+                 unsigned mask, unsigned value,
+                 int dx, int dy, int w, int h);
+
+/* nv04_state_fb.c */
+void
+nv04_emit_framebuffer(GLcontext *ctx, int emit);
+
+void
+nv04_emit_scissor(GLcontext *ctx, int emit);
+
+/* nv04_state_raster.c */
+void
+nv04_defer_control(GLcontext *ctx, int emit);
+
+void
+nv04_emit_control(GLcontext *ctx, int emit);
+
+void
+nv04_defer_blend(GLcontext *ctx, int emit);
+
+void
+nv04_emit_blend(GLcontext *ctx, int emit);
+
+/* nv04_state_frag.c */
+void
+nv04_emit_tex_env(GLcontext *ctx, int emit);
+
+/* nv04_state_tex.c */
+void
+nv04_emit_tex_obj(GLcontext *ctx, int emit);
+
+#endif
diff --git a/src/mesa/drivers/dri/nouveau/nv04_render.c b/src/mesa/drivers/dri/nouveau/nv04_render.c
new file mode 100644 (file)
index 0000000..b5943d9
--- /dev/null
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2009 Francisco Jerez.
+ * 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.
+ *
+ */
+
+#include "nouveau_driver.h"
+#include "nouveau_context.h"
+#include "nouveau_util.h"
+#include "nouveau_class.h"
+#include "nv04_driver.h"
+
+#include "tnl/tnl.h"
+#include "tnl/t_pipeline.h"
+#include "tnl/t_vertex.h"
+
+#define NUM_VERTEX_ATTRS 6
+
+static void
+swtnl_update_viewport(GLcontext *ctx)
+{
+       float *viewport = to_nv04_context(ctx)->viewport;
+       struct gl_framebuffer *fb = ctx->DrawBuffer;
+
+       get_viewport_scale(ctx, viewport);
+       get_viewport_translate(ctx, &viewport[MAT_TX]);
+
+       /* It wants normalized Z coordinates. */
+       viewport[MAT_SZ] /= fb->_DepthMaxF;
+       viewport[MAT_TZ] /= fb->_DepthMaxF;
+}
+
+static void
+swtnl_emit_attr(GLcontext *ctx, struct tnl_attr_map *m, int attr, int emit)
+{
+       TNLcontext *tnl = TNL_CONTEXT(ctx);
+
+       if (RENDERINPUTS_TEST(tnl->render_inputs_bitset, attr))
+               *m = (struct tnl_attr_map) {
+                       .attrib = attr,
+                       .format = emit,
+               };
+       else
+               *m = (struct tnl_attr_map) {
+                       .format = EMIT_PAD,
+                       .offset = _tnl_format_info[emit].attrsize,
+               };
+}
+
+static void
+swtnl_choose_attrs(GLcontext *ctx)
+{
+       TNLcontext *tnl = TNL_CONTEXT(ctx);
+       struct nouveau_grobj *fahrenheit = nv04_context_engine(ctx);
+       struct nv04_context *nctx = to_nv04_context(ctx);
+       static struct tnl_attr_map map[NUM_VERTEX_ATTRS];
+       int n = 0;
+
+       tnl->vb.AttribPtr[VERT_ATTRIB_POS] = tnl->vb.NdcPtr;
+
+       swtnl_emit_attr(ctx, &map[n++], _TNL_ATTRIB_POS, EMIT_4F_VIEWPORT);
+       swtnl_emit_attr(ctx, &map[n++], _TNL_ATTRIB_COLOR0, EMIT_4UB_4F_BGRA);
+       swtnl_emit_attr(ctx, &map[n++], _TNL_ATTRIB_COLOR1, EMIT_3UB_3F_BGR);
+       swtnl_emit_attr(ctx, &map[n++], _TNL_ATTRIB_FOG, EMIT_1UB_1F);
+       swtnl_emit_attr(ctx, &map[n++], _TNL_ATTRIB_TEX0, EMIT_2F);
+       if (nv04_mtex_engine(fahrenheit))
+               swtnl_emit_attr(ctx, &map[n++], _TNL_ATTRIB_TEX1, EMIT_2F);
+
+       swtnl_update_viewport(ctx);
+
+       _tnl_install_attrs(ctx, map, n, nctx->viewport, 0);
+}
+
+/* TnL renderer entry points */
+
+static void
+swtnl_start(GLcontext *ctx)
+{
+       swtnl_choose_attrs(ctx);
+}
+
+static void
+swtnl_finish(GLcontext *ctx)
+{
+       FIRE_RING(context_chan(ctx));
+}
+
+static void
+swtnl_primitive(GLcontext *ctx, GLenum mode)
+{
+}
+
+static void
+swtnl_reset_stipple(GLcontext *ctx)
+{
+}
+
+/* Primitive rendering */
+
+#define BEGIN_PRIMITIVE(n)                                             \
+       struct nouveau_channel *chan = context_chan(ctx);               \
+       struct nouveau_grobj *fahrenheit = nv04_context_engine(ctx);    \
+       int vertex_len = TNL_CONTEXT(ctx)->clipspace.vertex_size / 4;   \
+                                                                       \
+       if (nv04_mtex_engine(fahrenheit))                               \
+               BEGIN_RING(chan, fahrenheit,                            \
+                          NV04_MULTITEX_TRIANGLE_TLMTVERTEX_SX(0),     \
+                          n * vertex_len);                             \
+       else                                                            \
+               BEGIN_RING(chan, fahrenheit,                            \
+                          NV04_TEXTURED_TRIANGLE_TLVERTEX_SX(0),       \
+                          n * vertex_len);                             \
+
+#define OUT_VERTEX(i)                                          \
+       OUT_RINGp(chan, _tnl_get_vertex(ctx, i), vertex_len);
+
+#define END_PRIMITIVE(draw)                                            \
+       if (nv04_mtex_engine(fahrenheit)) {                             \
+               BEGIN_RING(chan, fahrenheit,                            \
+                          NV04_MULTITEX_TRIANGLE_DRAWPRIMITIVE(0), 1); \
+               OUT_RING(chan, draw);                                   \
+       } else {                                                        \
+               BEGIN_RING(chan, fahrenheit,                            \
+                          NV04_TEXTURED_TRIANGLE_DRAWPRIMITIVE(0), 1); \
+               OUT_RING(chan, draw);                                   \
+       }
+
+static void
+swtnl_points(GLcontext *ctx, GLuint first, GLuint last)
+{
+}
+
+static void
+swtnl_line(GLcontext *ctx, GLuint v1, GLuint v2)
+{
+}
+
+static void
+swtnl_triangle(GLcontext *ctx, GLuint v1, GLuint v2, GLuint v3)
+{
+       BEGIN_PRIMITIVE(3);
+       OUT_VERTEX(v1);
+       OUT_VERTEX(v2);
+       OUT_VERTEX(v3);
+       END_PRIMITIVE(0x210);
+}
+
+static void
+swtnl_quad(GLcontext *ctx, GLuint v1, GLuint v2, GLuint v3, GLuint v4)
+{
+       BEGIN_PRIMITIVE(4);
+       OUT_VERTEX(v1);
+       OUT_VERTEX(v2);
+       OUT_VERTEX(v3);
+       OUT_VERTEX(v4);
+       END_PRIMITIVE(0x320210);
+}
+
+/* TnL initialization. */
+void
+nv04_render_init(GLcontext *ctx)
+{
+       TNLcontext *tnl = TNL_CONTEXT(ctx);
+
+       tnl->Driver.RunPipeline = _tnl_run_pipeline;
+       tnl->Driver.Render.Interp = _tnl_interp;
+       tnl->Driver.Render.CopyPV = _tnl_copy_pv;
+       tnl->Driver.Render.ClippedPolygon = _tnl_RenderClippedPolygon;
+       tnl->Driver.Render.ClippedLine = _tnl_RenderClippedLine;
+       tnl->Driver.Render.BuildVertices = _tnl_build_vertices;
+
+       tnl->Driver.Render.Start = swtnl_start;
+       tnl->Driver.Render.Finish = swtnl_finish;
+       tnl->Driver.Render.PrimitiveNotify = swtnl_primitive;
+       tnl->Driver.Render.ResetLineStipple = swtnl_reset_stipple;
+
+       tnl->Driver.Render.Points = swtnl_points;
+       tnl->Driver.Render.Line = swtnl_line;
+       tnl->Driver.Render.Triangle = swtnl_triangle;
+       tnl->Driver.Render.Quad = swtnl_quad;
+
+       _tnl_need_projected_coords(ctx, GL_TRUE);
+       _tnl_init_vertices(ctx, tnl->vb.Size,
+                          NUM_VERTEX_ATTRS * 4 * sizeof(GLfloat));
+       _tnl_allow_pixel_fog(ctx, GL_FALSE);
+       _tnl_wakeup(ctx);
+}
+
+void
+nv04_render_destroy(GLcontext *ctx)
+{
+}
diff --git a/src/mesa/drivers/dri/nouveau/nv04_screen.c b/src/mesa/drivers/dri/nouveau/nv04_screen.c
new file mode 100644 (file)
index 0000000..0fc0f4c
--- /dev/null
@@ -0,0 +1,211 @@
+/*
+ * Copyright (C) 2009 Francisco Jerez.
+ * 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.
+ *
+ */
+
+#include "nouveau_driver.h"
+#include "nouveau_screen.h"
+#include "nouveau_class.h"
+#include "nv04_driver.h"
+
+static const struct nouveau_driver nv04_driver;
+
+static void
+nv04_hwctx_init(struct nouveau_screen *screen)
+{
+       struct nouveau_channel *chan = screen->chan;
+       struct nouveau_grobj *surf3d = screen->surf3d;
+       struct nouveau_grobj *eng3d = screen->eng3d;
+       struct nouveau_grobj *eng3dm = screen->eng3dm;
+
+       BIND_RING(chan, surf3d, 7);
+       BEGIN_RING(chan, surf3d, NV04_CONTEXT_SURFACES_3D_DMA_NOTIFY, 3);
+       OUT_RING(chan, screen->ntfy->handle);
+       OUT_RING(chan, chan->vram->handle);
+       OUT_RING(chan, chan->vram->handle);
+
+       BEGIN_RING(chan, eng3d, NV04_TEXTURED_TRIANGLE_DMA_NOTIFY, 4);
+       OUT_RING(chan, screen->ntfy->handle);
+       OUT_RING(chan, chan->vram->handle);
+       OUT_RING(chan, chan->gart->handle);
+       OUT_RING(chan, surf3d->handle);
+
+       BEGIN_RING(chan, eng3dm, NV04_MULTITEX_TRIANGLE_DMA_NOTIFY, 4);
+       OUT_RING(chan, screen->ntfy->handle);
+       OUT_RING(chan, chan->vram->handle);
+       OUT_RING(chan, chan->gart->handle);
+       OUT_RING(chan, surf3d->handle);
+
+       FIRE_RING(chan);
+}
+
+static void
+nv04_channel_flush_notify(struct nouveau_channel *chan)
+{
+       struct nouveau_screen *screen = chan->user_private;
+       struct nouveau_context *nctx = screen->context;
+
+       if (nctx && nctx->fallback < SWRAST) {
+               GLcontext *ctx = &nctx->base;
+
+               /* Flushing seems to clobber the engine context. */
+               context_dirty_i(ctx, TEX_OBJ, 0);
+               context_dirty_i(ctx, TEX_OBJ, 1);
+               context_dirty_i(ctx, TEX_ENV, 0);
+               context_dirty_i(ctx, TEX_ENV, 1);
+               context_dirty(ctx, CONTROL);
+               context_dirty(ctx, BLEND);
+
+               nouveau_state_emit(ctx);
+       }
+}
+
+GLboolean
+nv04_screen_init(struct nouveau_screen *screen)
+{
+       int ret;
+
+       screen->driver = &nv04_driver;
+       screen->chan->flush_notify = nv04_channel_flush_notify;
+
+       /* 2D engine. */
+       ret = nv04_surface_init(screen);
+       if (!ret)
+               return GL_FALSE;
+
+       /* 3D engine. */
+       ret = nouveau_grobj_alloc(screen->chan, 0xbeef0001,
+                                 NV04_TEXTURED_TRIANGLE, &screen->eng3d);
+       if (ret)
+               return GL_FALSE;
+
+       ret = nouveau_grobj_alloc(screen->chan, 0xbeef0002,
+                                 NV04_MULTITEX_TRIANGLE, &screen->eng3dm);
+       if (ret)
+               return GL_FALSE;
+
+       ret = nouveau_grobj_alloc(screen->chan, 0xbeef0003,
+                                 NV04_CONTEXT_SURFACES_3D, &screen->surf3d);
+       if (ret)
+               return GL_FALSE;
+
+       nv04_hwctx_init(screen);
+
+       return GL_TRUE;
+}
+
+static void
+nv04_screen_destroy(struct nouveau_screen *screen)
+{
+       if (screen->eng3d)
+               nouveau_grobj_free(&screen->eng3d);
+
+       if (screen->eng3dm)
+               nouveau_grobj_free(&screen->eng3dm);
+
+       if (screen->surf3d)
+               nouveau_grobj_free(&screen->surf3d);
+
+       nv04_surface_takedown(screen);
+}
+
+static const struct nouveau_driver nv04_driver = {
+       .screen_destroy = nv04_screen_destroy,
+       .context_create = nv04_context_create,
+       .context_destroy = nv04_context_destroy,
+       .surface_copy = nv04_surface_copy,
+       .surface_fill = nv04_surface_fill,
+       .emit = (nouveau_state_func[]) {
+               nv04_defer_control,
+               nouveau_emit_nothing,
+               nv04_defer_blend,
+               nv04_defer_blend,
+               nouveau_emit_nothing,
+               nouveau_emit_nothing,
+               nouveau_emit_nothing,
+               nouveau_emit_nothing,
+               nouveau_emit_nothing,
+               nouveau_emit_nothing,
+               nv04_defer_control,
+               nouveau_emit_nothing,
+               nv04_defer_control,
+               nouveau_emit_nothing,
+               nv04_defer_control,
+               nv04_defer_control,
+               nouveau_emit_nothing,
+               nv04_emit_framebuffer,
+               nv04_defer_blend,
+               nouveau_emit_nothing,
+               nouveau_emit_nothing,
+               nouveau_emit_nothing,
+               nouveau_emit_nothing,
+               nouveau_emit_nothing,
+               nouveau_emit_nothing,
+               nouveau_emit_nothing,
+               nouveau_emit_nothing,
+               nouveau_emit_nothing,
+               nouveau_emit_nothing,
+               nouveau_emit_nothing,
+               nouveau_emit_nothing,
+               nouveau_emit_nothing,
+               nouveau_emit_nothing,
+               nouveau_emit_nothing,
+               nouveau_emit_nothing,
+               nouveau_emit_nothing,
+               nouveau_emit_nothing,
+               nouveau_emit_nothing,
+               nouveau_emit_nothing,
+               nouveau_emit_nothing,
+               nouveau_emit_nothing,
+               nouveau_emit_nothing,
+               nouveau_emit_nothing,
+               nouveau_emit_nothing,
+               nouveau_emit_nothing,
+               nouveau_emit_nothing,
+               nouveau_emit_nothing,
+               nouveau_emit_nothing,
+               nouveau_emit_nothing,
+               nv04_emit_scissor,
+               nv04_defer_blend,
+               nv04_defer_control,
+               nv04_defer_control,
+               nv04_defer_control,
+               nv04_emit_tex_env,
+               nv04_emit_tex_env,
+               nouveau_emit_nothing,
+               nouveau_emit_nothing,
+               nouveau_emit_nothing,
+               nouveau_emit_nothing,
+               nouveau_emit_nothing,
+               nouveau_emit_nothing,
+               nv04_emit_tex_obj,
+               nv04_emit_tex_obj,
+               nouveau_emit_nothing,
+               nouveau_emit_nothing,
+               nouveau_emit_nothing,
+               nv04_emit_blend,
+               nv04_emit_control,
+       },
+       .num_emit = NUM_NV04_STATE,
+};
diff --git a/src/mesa/drivers/dri/nouveau/nv04_state_fb.c b/src/mesa/drivers/dri/nouveau/nv04_state_fb.c
new file mode 100644 (file)
index 0000000..e97eb2a
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2009 Francisco Jerez.
+ * 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.
+ *
+ */
+
+#include "nouveau_driver.h"
+#include "nouveau_context.h"
+#include "nouveau_fbo.h"
+#include "nouveau_util.h"
+#include "nouveau_class.h"
+#include "nv04_driver.h"
+
+static inline unsigned
+get_rt_format(gl_format format)
+{
+       switch (format) {
+       case MESA_FORMAT_XRGB8888:
+               return 0x05;
+       case MESA_FORMAT_ARGB8888:
+               return 0x08;
+       case MESA_FORMAT_RGB565:
+               return 0x03;
+       default:
+               assert(0);
+       }
+}
+
+void
+nv04_emit_framebuffer(GLcontext *ctx, int emit)
+{
+       struct nouveau_channel *chan = context_chan(ctx);
+       struct nouveau_screen *screen = to_nouveau_context(ctx)->screen;
+       struct nouveau_grobj *surf3d = screen->surf3d;
+       struct nouveau_bo_context *bctx = context_bctx(ctx, FRAMEBUFFER);
+       struct gl_framebuffer *fb = ctx->DrawBuffer;
+       struct nouveau_surface *s;
+       uint32_t rt_format = NV04_CONTEXT_SURFACES_3D_FORMAT_TYPE_PITCH;
+       uint32_t rt_pitch = 0, zeta_pitch = 0;
+       unsigned bo_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR;
+
+       if (fb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT)
+               return;
+
+       /* Render target */
+       if (fb->_NumColorDrawBuffers) {
+               s = &to_nouveau_renderbuffer(
+                       fb->_ColorDrawBuffers[0])->surface;
+
+               rt_format |= get_rt_format(s->format);
+               zeta_pitch = rt_pitch = s->pitch;
+
+               nouveau_bo_markl(bctx, surf3d,
+                                NV04_CONTEXT_SURFACES_3D_OFFSET_COLOR,
+                                s->bo, 0, bo_flags);
+       }
+
+       /* depth/stencil */
+       if (fb->_DepthBuffer) {
+               s = &to_nouveau_renderbuffer(
+                       fb->_DepthBuffer->Wrapped)->surface;
+
+               zeta_pitch = s->pitch;
+
+               nouveau_bo_markl(bctx, surf3d,
+                                NV04_CONTEXT_SURFACES_3D_OFFSET_ZETA,
+                                s->bo, 0, bo_flags);
+       }
+
+       BEGIN_RING(chan, surf3d, NV04_CONTEXT_SURFACES_3D_FORMAT, 1);
+       OUT_RING(chan, rt_format);
+       BEGIN_RING(chan, surf3d, NV04_CONTEXT_SURFACES_3D_PITCH, 1);
+       OUT_RING(chan, zeta_pitch << 16 | rt_pitch);
+
+       /* Recompute the scissor state. */
+       context_dirty(ctx, SCISSOR);
+}
+
+void
+nv04_emit_scissor(GLcontext *ctx, int emit)
+{
+       struct nouveau_channel *chan = context_chan(ctx);
+       struct nouveau_screen *screen = to_nouveau_context(ctx)->screen;
+       struct nouveau_grobj *surf3d = screen->surf3d;
+       int x, y, w, h;
+
+       get_scissors(ctx->DrawBuffer, &x, &y, &w, &h);
+
+       BEGIN_RING(chan, surf3d, NV04_CONTEXT_SURFACES_3D_CLIP_HORIZONTAL, 2);
+       OUT_RING(chan, w << 16 | x);
+       OUT_RING(chan, h << 16 | y);
+
+       /* Messing with surf3d invalidates some engine state. */
+       context_dirty(ctx, CONTROL);
+       context_dirty(ctx, BLEND);
+}
diff --git a/src/mesa/drivers/dri/nouveau/nv04_state_frag.c b/src/mesa/drivers/dri/nouveau/nv04_state_frag.c
new file mode 100644 (file)
index 0000000..34ee296
--- /dev/null
@@ -0,0 +1,261 @@
+/*
+ * Copyright (C) 2009 Francisco Jerez.
+ * 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.
+ *
+ */
+
+#include "nouveau_driver.h"
+#include "nouveau_context.h"
+#include "nouveau_util.h"
+#include "nouveau_class.h"
+#include "nv04_driver.h"
+
+#define COMBINER_SHIFT(in)                                             \
+       (NV04_MULTITEX_TRIANGLE_COMBINE_COLOR_ARGUMENT##in##_SHIFT      \
+        - NV04_MULTITEX_TRIANGLE_COMBINE_COLOR_ARGUMENT0_SHIFT)
+#define COMBINER_SOURCE(reg)                                   \
+       NV04_MULTITEX_TRIANGLE_COMBINE_COLOR_ARGUMENT0_##reg
+#define COMBINER_INVERT                                        \
+       NV04_MULTITEX_TRIANGLE_COMBINE_COLOR_INVERSE0
+#define COMBINER_ALPHA                                 \
+       NV04_MULTITEX_TRIANGLE_COMBINE_COLOR_ALPHA0
+
+struct combiner_state {
+       int unit;
+       GLboolean alpha;
+
+       /* GL state */
+       GLenum mode;
+       GLenum *source;
+       GLenum *operand;
+       GLuint logscale;
+
+       /* Derived HW state */
+       uint32_t hw;
+};
+
+#define __INIT_COMBINER_ALPHA_A GL_TRUE
+#define __INIT_COMBINER_ALPHA_RGB GL_FALSE
+
+/* Initialize a combiner_state struct from the texture unit
+ * context. */
+#define INIT_COMBINER(chan, rc, i) do {                                \
+               struct gl_tex_env_combine_state *c =            \
+                       ctx->Texture.Unit[i]._CurrentCombine;   \
+               (rc)->alpha = __INIT_COMBINER_ALPHA_##chan;     \
+               (rc)->unit = i;                                 \
+               (rc)->mode = c->Mode##chan;                     \
+               (rc)->source = c->Source##chan;                 \
+               (rc)->operand = c->Operand##chan;               \
+               (rc)->logscale = c->ScaleShift##chan;           \
+               (rc)->hw = 0;                                   \
+       } while (0)
+
+/* Get the combiner source for the specified EXT_texture_env_combine
+ * argument. */
+static uint32_t
+get_arg_source(struct combiner_state *rc, int arg)
+{
+       switch (rc->source[arg]) {
+       case GL_TEXTURE:
+               return rc->unit ? COMBINER_SOURCE(TEXTURE1) :
+                       COMBINER_SOURCE(TEXTURE0);
+
+       case GL_TEXTURE0:
+               return COMBINER_SOURCE(TEXTURE0);
+
+       case GL_TEXTURE1:
+               return COMBINER_SOURCE(TEXTURE1);
+
+       case GL_CONSTANT:
+               return COMBINER_SOURCE(CONSTANT);
+
+       case GL_PRIMARY_COLOR:
+               return COMBINER_SOURCE(PRIMARY_COLOR);
+
+       case GL_PREVIOUS:
+               return rc->unit ? COMBINER_SOURCE(PREVIOUS) :
+                       COMBINER_SOURCE(PRIMARY_COLOR);
+
+       default:
+               assert(0);
+       }
+}
+
+/* Get the (possibly inverted) combiner input mapping for the
+ * specified argument. */
+#define INVERT 0x1
+
+static uint32_t
+get_arg_mapping(struct combiner_state *rc, int arg, int flags)
+{
+       int map = 0;
+
+       switch (rc->operand[arg]) {
+       case GL_SRC_COLOR:
+       case GL_ONE_MINUS_SRC_COLOR:
+               break;
+
+       case GL_SRC_ALPHA:
+       case GL_ONE_MINUS_SRC_ALPHA:
+               map |= rc->alpha ? 0 : COMBINER_ALPHA;
+               break;
+       }
+
+       switch (rc->operand[arg]) {
+       case GL_SRC_COLOR:
+       case GL_SRC_ALPHA:
+               map |= flags & INVERT ? COMBINER_INVERT : 0;
+               break;
+
+       case GL_ONE_MINUS_SRC_COLOR:
+       case GL_ONE_MINUS_SRC_ALPHA:
+               map |= flags & INVERT ? 0 : COMBINER_INVERT;
+               break;
+       }
+
+       return map;
+}
+
+/* Bind the combiner input <in> to the combiner source <src>,
+ * possibly inverted. */
+#define INPUT_SRC(rc, in, src, flags)                                  \
+       (rc)->hw |= ((flags & INVERT ? COMBINER_INVERT : 0) |           \
+                  COMBINER_SOURCE(src)) << COMBINER_SHIFT(in)
+
+/* Bind the combiner input <in> to the EXT_texture_env_combine
+ * argument <arg>, possibly inverted. */
+#define INPUT_ARG(rc, in, arg, flags)                                  \
+       (rc)->hw |= (get_arg_source(rc, arg) |                          \
+                    get_arg_mapping(rc, arg, flags)) << COMBINER_SHIFT(in)
+
+#define UNSIGNED_OP(rc)                                                        \
+       (rc)->hw |= ((rc)->logscale ?                                   \
+                    NV04_MULTITEX_TRIANGLE_COMBINE_COLOR_MAP_SCALE2 :  \
+                    NV04_MULTITEX_TRIANGLE_COMBINE_COLOR_MAP_IDENTITY)
+#define SIGNED_OP(rc)                                                  \
+       (rc)->hw |= ((rc)->logscale ?                                   \
+                    NV04_MULTITEX_TRIANGLE_COMBINE_COLOR_MAP_BIAS_SCALE2 : \
+                    NV04_MULTITEX_TRIANGLE_COMBINE_COLOR_MAP_BIAS)
+
+static void
+setup_combiner(struct combiner_state *rc)
+{
+       switch (rc->mode) {
+       case GL_REPLACE:
+               INPUT_ARG(rc, 0, 0, 0);
+               INPUT_SRC(rc, 1, ZERO, INVERT);
+               INPUT_SRC(rc, 2, ZERO, 0);
+               INPUT_SRC(rc, 3, ZERO, 0);
+               UNSIGNED_OP(rc);
+               break;
+
+       case GL_MODULATE:
+               INPUT_ARG(rc, 0, 0, 0);
+               INPUT_ARG(rc, 1, 1, 0);
+               INPUT_SRC(rc, 2, ZERO, 0);
+               INPUT_SRC(rc, 3, ZERO, 0);
+               UNSIGNED_OP(rc);
+               break;
+
+       case GL_ADD:
+               INPUT_ARG(rc, 0, 0, 0);
+               INPUT_SRC(rc, 1, ZERO, INVERT);
+               INPUT_ARG(rc, 2, 1, 0);
+               INPUT_SRC(rc, 3, ZERO, INVERT);
+               UNSIGNED_OP(rc);
+               break;
+
+       case GL_INTERPOLATE:
+               INPUT_ARG(rc, 0, 0, 0);
+               INPUT_ARG(rc, 1, 2, 0);
+               INPUT_ARG(rc, 2, 1, 0);
+               INPUT_ARG(rc, 3, 2, INVERT);
+               UNSIGNED_OP(rc);
+               break;
+
+       case GL_ADD_SIGNED:
+               INPUT_ARG(rc, 0, 0, 0);
+               INPUT_SRC(rc, 1, ZERO, INVERT);
+               INPUT_ARG(rc, 2, 1, 0);
+               INPUT_SRC(rc, 3, ZERO, INVERT);
+               SIGNED_OP(rc);
+               break;
+
+       default:
+               assert(0);
+       }
+}
+
+void
+nv04_emit_tex_env(GLcontext *ctx, int emit)
+{
+       const int i = emit - NOUVEAU_STATE_TEX_ENV0;
+       struct nouveau_channel *chan = context_chan(ctx);
+       struct nouveau_grobj *fahrenheit = nv04_context_engine(ctx);
+       struct combiner_state rc_a = {}, rc_c = {};
+
+       if (!nv04_mtex_engine(fahrenheit)) {
+               context_dirty(ctx, BLEND);
+               return;
+       }
+
+       /* Compute the new combiner state. */
+       if (ctx->Texture.Unit[i]._ReallyEnabled) {
+               INIT_COMBINER(A, &rc_a, i);
+               setup_combiner(&rc_a);
+
+               INIT_COMBINER(RGB, &rc_c, i);
+               setup_combiner(&rc_c);
+
+       } else {
+               if (i == 0) {
+                       INPUT_SRC(&rc_a, 0, PRIMARY_COLOR, 0);
+                       INPUT_SRC(&rc_c, 0, PRIMARY_COLOR, 0);
+               } else {
+                       INPUT_SRC(&rc_a, 0, PREVIOUS, 0);
+                       INPUT_SRC(&rc_c, 0, PREVIOUS, 0);
+               }
+
+               INPUT_SRC(&rc_a, 1, ZERO, INVERT);
+               INPUT_SRC(&rc_c, 1, ZERO, INVERT);
+               INPUT_SRC(&rc_a, 2, ZERO, 0);
+               INPUT_SRC(&rc_c, 2, ZERO, 0);
+               INPUT_SRC(&rc_a, 3, ZERO, 0);
+               INPUT_SRC(&rc_c, 3, ZERO, 0);
+
+               UNSIGNED_OP(&rc_a);
+               UNSIGNED_OP(&rc_c);
+       }
+
+       /* Write the register combiner state out to the hardware. */
+       BEGIN_RING(chan, fahrenheit,
+                  NV04_MULTITEX_TRIANGLE_COMBINE_ALPHA(i), 2);
+       OUT_RING(chan, rc_a.hw);
+       OUT_RING(chan, rc_c.hw);
+
+       BEGIN_RING(chan, fahrenheit,
+                  NV04_MULTITEX_TRIANGLE_COMBINE_FACTOR, 1);
+       OUT_RING(chan, pack_rgba_f(MESA_FORMAT_ARGB8888,
+                                  ctx->Texture.Unit[0].EnvColor));
+}
diff --git a/src/mesa/drivers/dri/nouveau/nv04_state_raster.c b/src/mesa/drivers/dri/nouveau/nv04_state_raster.c
new file mode 100644 (file)
index 0000000..5e3788d
--- /dev/null
@@ -0,0 +1,314 @@
+/*
+ * Copyright (C) 2009 Francisco Jerez.
+ * 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.
+ *
+ */
+
+#include "nouveau_driver.h"
+#include "nouveau_context.h"
+#include "nouveau_util.h"
+#include "nouveau_class.h"
+#include "nv04_driver.h"
+
+static unsigned
+get_comparison_op(unsigned op)
+{
+       switch (op) {
+       case GL_NEVER:
+               return 0x1;
+       case GL_LESS:
+               return 0x2;
+       case GL_EQUAL:
+               return 0x3;
+       case GL_LEQUAL:
+               return 0x4;
+       case GL_GREATER:
+               return 0x5;
+       case GL_NOTEQUAL:
+               return 0x6;
+       case GL_GEQUAL:
+               return 0x7;
+       case GL_ALWAYS:
+               return 0x8;
+       default:
+               assert(0);
+       }
+}
+
+static unsigned
+get_stencil_op(unsigned op)
+{
+       switch (op) {
+       case GL_KEEP:
+               return 0x1;
+       case GL_INCR:
+               return 0x4;
+       case GL_DECR:
+               return 0x5;
+       case GL_INVERT:
+               return 0x6;
+       default:
+               assert(0);
+       }
+}
+
+static unsigned
+get_texenv_mode(unsigned mode)
+{
+       switch (mode) {
+       case GL_REPLACE:
+               return 0x1;
+       case GL_ADD:
+               return 0x2;
+       case GL_DECAL:
+               return 0x3;
+       case GL_MODULATE:
+               return 0x4;
+       default:
+               assert(0);
+       }
+}
+
+static unsigned
+get_blend_func(unsigned func)
+{
+       switch (func) {
+       case GL_ZERO:
+               return 0x1;
+       case GL_ONE:
+               return 0x2;
+       case GL_SRC_COLOR:
+               return 0x3;
+       case GL_ONE_MINUS_SRC_COLOR:
+               return 0x4;
+       case GL_SRC_ALPHA:
+               return 0x5;
+       case GL_ONE_MINUS_SRC_ALPHA:
+               return 0x6;
+       case GL_DST_ALPHA:
+               return 0x7;
+       case GL_ONE_MINUS_DST_ALPHA:
+               return 0x8;
+       case GL_DST_COLOR:
+               return 0x9;
+       case GL_ONE_MINUS_DST_COLOR:
+               return 0xa;
+       case GL_SRC_ALPHA_SATURATE:
+               return 0xb;
+       default:
+               assert(0);
+       }
+}
+
+void
+nv04_defer_control(GLcontext *ctx, int emit)
+{
+       context_dirty(ctx, CONTROL);
+}
+
+void
+nv04_emit_control(GLcontext *ctx, int emit)
+{
+       struct nouveau_channel *chan = context_chan(ctx);
+       struct nouveau_grobj *fahrenheit = nv04_context_engine(ctx);
+
+       if (nv04_mtex_engine(fahrenheit)) {
+               int cull_mode = ctx->Polygon.CullFaceMode;
+               int front_face = ctx->Polygon.FrontFace;
+               uint32_t ctrl0 = 1 << 30 |
+                       NV04_MULTITEX_TRIANGLE_CONTROL0_ORIGIN;
+               uint32_t ctrl1 = 0, ctrl2 = 0;
+
+               /* Color mask. */
+               if (ctx->Color.ColorMask[0][RCOMP])
+                       ctrl0 |= NV04_MULTITEX_TRIANGLE_CONTROL0_RED_WRITE;
+               if (ctx->Color.ColorMask[0][GCOMP])
+                       ctrl0 |= NV04_MULTITEX_TRIANGLE_CONTROL0_GREEN_WRITE;
+               if (ctx->Color.ColorMask[0][BCOMP])
+                       ctrl0 |= NV04_MULTITEX_TRIANGLE_CONTROL0_BLUE_WRITE;
+               if (ctx->Color.ColorMask[0][ACOMP])
+                       ctrl0 |= NV04_MULTITEX_TRIANGLE_CONTROL0_ALPHA_WRITE;
+
+               /* Dithering. */
+               if (ctx->Color.DitherFlag)
+                       ctrl0 |= NV04_MULTITEX_TRIANGLE_CONTROL0_DITHER_ENABLE;
+
+               /* Cull mode. */
+               if (!ctx->Polygon.CullFlag)
+                       ctrl0 |= NV04_MULTITEX_TRIANGLE_CONTROL0_CULL_MODE_NONE;
+               else if (cull_mode == GL_FRONT_AND_BACK)
+                       ctrl0 |= NV04_MULTITEX_TRIANGLE_CONTROL0_CULL_MODE_BOTH;
+               else
+                       ctrl0 |= (cull_mode == GL_FRONT) ^ (front_face == GL_CCW) ?
+                               NV04_MULTITEX_TRIANGLE_CONTROL0_CULL_MODE_CW :
+                               NV04_MULTITEX_TRIANGLE_CONTROL0_CULL_MODE_CCW;
+
+               /* Depth test. */
+               if (ctx->Depth.Test)
+                       ctrl0 |= NV04_MULTITEX_TRIANGLE_CONTROL0_Z_ENABLE;
+
+               if (ctx->Depth.Mask)
+                       ctrl0 |= NV04_MULTITEX_TRIANGLE_CONTROL0_Z_WRITE;
+
+               ctrl0 |= get_comparison_op(ctx->Depth.Func) << 16;
+
+               /* Alpha test. */
+               if (ctx->Color.AlphaEnabled)
+                       ctrl0 |= NV04_MULTITEX_TRIANGLE_CONTROL0_ALPHA_ENABLE;
+
+               ctrl0 |= get_comparison_op(ctx->Color.AlphaFunc) << 8 |
+                       FLOAT_TO_UBYTE(ctx->Color.AlphaRef);
+
+               /* Stencil test. */
+               if (ctx->Stencil.WriteMask[0])
+                       ctrl0 |= NV04_MULTITEX_TRIANGLE_CONTROL0_STENCIL_WRITE;
+
+               if (ctx->Stencil.Enabled)
+                       ctrl1 |= NV04_MULTITEX_TRIANGLE_CONTROL1_STENCIL_ENABLE;
+
+               ctrl1 |= get_comparison_op(ctx->Stencil.Function[0]) << 4 |
+                       ctx->Stencil.Ref[0] << 8 |
+                       ctx->Stencil.ValueMask[0] << 16 |
+                       ctx->Stencil.WriteMask[0] << 24;
+
+               ctrl2 |= get_stencil_op(ctx->Stencil.ZPassFunc[0]) << 8 |
+                       get_stencil_op(ctx->Stencil.ZFailFunc[0]) << 4 |
+                       get_stencil_op(ctx->Stencil.FailFunc[0]);
+
+               BEGIN_RING(chan, fahrenheit, NV04_MULTITEX_TRIANGLE_CONTROL0, 3);
+               OUT_RING(chan, ctrl0);
+               OUT_RING(chan, ctrl1);
+               OUT_RING(chan, ctrl2);
+
+       } else {
+               int cull_mode = ctx->Polygon.CullFaceMode;
+               int front_face = ctx->Polygon.FrontFace;
+               uint32_t ctrl = 1 << 30 |
+                       NV04_TEXTURED_TRIANGLE_CONTROL_ORIGIN;
+
+               /* Dithering. */
+               if (ctx->Color.DitherFlag)
+                       ctrl |= NV04_TEXTURED_TRIANGLE_CONTROL_DITHER_ENABLE;
+
+               /* Cull mode. */
+               if (!ctx->Polygon.CullFlag)
+                       ctrl |= NV04_TEXTURED_TRIANGLE_CONTROL_CULL_MODE_NONE;
+               else if (cull_mode == GL_FRONT_AND_BACK)
+                       ctrl |= NV04_TEXTURED_TRIANGLE_CONTROL_CULL_MODE_BOTH;
+               else
+                       ctrl |= (cull_mode == GL_FRONT) ^ (front_face == GL_CCW) ?
+                               NV04_TEXTURED_TRIANGLE_CONTROL_CULL_MODE_CW :
+                               NV04_TEXTURED_TRIANGLE_CONTROL_CULL_MODE_CCW;
+
+               /* Depth test. */
+               if (ctx->Depth.Test)
+                       ctrl |= NV04_TEXTURED_TRIANGLE_CONTROL_Z_ENABLE;
+               if (ctx->Depth.Mask)
+                       ctrl |= NV04_TEXTURED_TRIANGLE_CONTROL_Z_WRITE;
+
+               ctrl |= get_comparison_op(ctx->Depth.Func) << 16;
+
+               /* Alpha test. */
+               if (ctx->Color.AlphaEnabled)
+                       ctrl |= NV04_TEXTURED_TRIANGLE_CONTROL_ALPHA_ENABLE;
+
+               ctrl |= get_comparison_op(ctx->Color.AlphaFunc) << 8 |
+                       FLOAT_TO_UBYTE(ctx->Color.AlphaRef);
+
+               BEGIN_RING(chan, fahrenheit, NV04_TEXTURED_TRIANGLE_CONTROL, 1);
+               OUT_RING(chan, ctrl);
+       }
+}
+
+void
+nv04_defer_blend(GLcontext *ctx, int emit)
+{
+       context_dirty(ctx, BLEND);
+}
+
+void
+nv04_emit_blend(GLcontext *ctx, int emit)
+{
+       struct nouveau_channel *chan = context_chan(ctx);
+       struct nouveau_grobj *fahrenheit = nv04_context_engine(ctx);
+
+       if (nv04_mtex_engine(fahrenheit)) {
+               uint32_t blend = 0x2 << 4 |
+                       NV04_MULTITEX_TRIANGLE_BLEND_TEXTURE_PERSPECTIVE_ENABLE;
+
+               /* Alpha blending. */
+               blend |= get_blend_func(ctx->Color.BlendDstRGB) << 28 |
+                       get_blend_func(ctx->Color.BlendSrcRGB) << 24;
+
+               if (ctx->Color.BlendEnabled)
+                       blend |= NV04_MULTITEX_TRIANGLE_BLEND_BLEND_ENABLE;
+
+               /* Shade model. */
+               if (ctx->Light.ShadeModel == GL_SMOOTH)
+                       blend |= NV04_MULTITEX_TRIANGLE_BLEND_SHADE_MODE_GOURAUD;
+               else
+                       blend |= NV04_MULTITEX_TRIANGLE_BLEND_SHADE_MODE_FLAT;
+
+               /* Fog. */
+               if (ctx->Fog.Enabled)
+                       blend |= NV04_MULTITEX_TRIANGLE_BLEND_FOG_ENABLE;
+
+               BEGIN_RING(chan, fahrenheit, NV04_MULTITEX_TRIANGLE_BLEND, 1);
+               OUT_RING(chan, blend);
+
+               BEGIN_RING(chan, fahrenheit, NV04_MULTITEX_TRIANGLE_FOGCOLOR, 1);
+               OUT_RING(chan, pack_rgba_f(MESA_FORMAT_ARGB8888,
+                                          ctx->Fog.Color));
+
+       } else {
+               uint32_t blend = 0x2 << 4 |
+                       NV04_TEXTURED_TRIANGLE_BLEND_TEXTURE_PERSPECTIVE_ENABLE;
+
+               /* Alpha blending. */
+               blend |= get_blend_func(ctx->Color.BlendDstRGB) << 28 |
+                       get_blend_func(ctx->Color.BlendSrcRGB) << 24;
+
+               if (ctx->Color.BlendEnabled)
+                       blend |= NV04_TEXTURED_TRIANGLE_BLEND_BLEND_ENABLE;
+
+               /* Shade model. */
+               if (ctx->Light.ShadeModel == GL_SMOOTH)
+                       blend |= NV04_TEXTURED_TRIANGLE_BLEND_SHADE_MODE_GOURAUD;
+               else
+                       blend |= NV04_TEXTURED_TRIANGLE_BLEND_SHADE_MODE_FLAT;
+
+               /* Texture environment. */
+               blend |= get_texenv_mode(ctx->Texture.Unit[0].EnvMode);
+
+               /* Fog. */
+               if (ctx->Fog.Enabled)
+                       blend |= NV04_TEXTURED_TRIANGLE_BLEND_FOG_ENABLE;
+
+               BEGIN_RING(chan, fahrenheit, NV04_TEXTURED_TRIANGLE_BLEND, 1);
+               OUT_RING(chan, blend);
+
+               BEGIN_RING(chan, fahrenheit, NV04_TEXTURED_TRIANGLE_FOGCOLOR, 1);
+               OUT_RING(chan, pack_rgba_f(MESA_FORMAT_ARGB8888,
+                                          ctx->Fog.Color));
+       }
+}
diff --git a/src/mesa/drivers/dri/nouveau/nv04_state_tex.c b/src/mesa/drivers/dri/nouveau/nv04_state_tex.c
new file mode 100644 (file)
index 0000000..99ea310
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2009 Francisco Jerez.
+ * 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.
+ *
+ */
+
+#include "nouveau_driver.h"
+#include "nouveau_context.h"
+#include "nouveau_texture.h"
+#include "nouveau_util.h"
+#include "nouveau_gldefs.h"
+#include "nouveau_class.h"
+#include "nv04_driver.h"
+
+static uint32_t
+get_tex_format(struct gl_texture_image *ti)
+{
+       switch (ti->TexFormat) {
+       case MESA_FORMAT_A8:
+       case MESA_FORMAT_L8:
+               return NV04_TEXTURED_TRIANGLE_FORMAT_COLOR_Y8;
+       case MESA_FORMAT_ARGB1555:
+               return NV04_TEXTURED_TRIANGLE_FORMAT_COLOR_A1R5G5B5;
+       case MESA_FORMAT_ARGB4444:
+               return NV04_TEXTURED_TRIANGLE_FORMAT_COLOR_A4R4G4B4;
+       case MESA_FORMAT_RGB565:
+               return NV04_TEXTURED_TRIANGLE_FORMAT_COLOR_R5G6B5;
+       case MESA_FORMAT_ARGB8888:
+               return NV04_TEXTURED_TRIANGLE_FORMAT_COLOR_A8R8G8B8;
+       default:
+               assert(0);
+       }
+}
+
+static inline unsigned
+get_wrap_mode(unsigned wrap)
+{
+       switch (wrap) {
+       case GL_REPEAT:
+               return 0x1;
+       case GL_MIRRORED_REPEAT:
+               return 0x2;
+       case GL_CLAMP:
+       case GL_CLAMP_TO_EDGE:
+               return 0x3;
+       case GL_CLAMP_TO_BORDER:
+               return 0x4;
+       default:
+               assert(0);
+       }
+}
+
+void
+nv04_emit_tex_obj(GLcontext *ctx, int emit)
+{
+       const int i = emit - NOUVEAU_STATE_TEX_OBJ0;
+       struct nouveau_channel *chan = context_chan(ctx);
+       struct nouveau_grobj *fahrenheit = nv04_context_engine(ctx);
+       struct nouveau_bo_context *bctx = context_bctx_i(ctx, TEXTURE, i);
+       const int bo_flags = NOUVEAU_BO_RD | NOUVEAU_BO_GART | NOUVEAU_BO_VRAM;
+       struct nouveau_surface *s;
+       uint32_t format = 0xa0, filter = 0x1010;
+
+       if (i && !nv04_mtex_engine(fahrenheit))
+               return;
+
+       if (ctx->Texture.Unit[i]._ReallyEnabled) {
+               struct gl_texture_object *t = ctx->Texture.Unit[i]._Current;
+               struct gl_texture_image *ti = t->Image[0][t->BaseLevel];
+               int lod_max = 1, lod_bias = 0;
+
+               nouveau_texture_validate(ctx, t);
+               s = &to_nouveau_texture(t)->surfaces[t->BaseLevel];
+
+               if (t->MinFilter != GL_NEAREST &&
+                   t->MinFilter != GL_LINEAR) {
+                       lod_max = CLAMP(MIN2(t->MaxLod, t->_MaxLambda),
+                                       0, 15) + 1;
+
+                       lod_bias = CLAMP(ctx->Texture.Unit[i].LodBias +
+                                        t->LodBias, 0, 15);
+               }
+
+               format |= get_wrap_mode(t->WrapT) << 28 |
+                       get_wrap_mode(t->WrapS) << 24 |
+                       ti->HeightLog2 << 20 |
+                       ti->WidthLog2 << 16 |
+                       lod_max << 12 |
+                       get_tex_format(ti);
+
+               filter |= log2i(t->MaxAnisotropy) << 31 |
+                       nvgl_filter_mode(t->MagFilter) << 28 |
+                       log2i(t->MaxAnisotropy) << 27 |
+                       nvgl_filter_mode(t->MinFilter) << 24 |
+                       lod_bias << 16;
+
+       } else {
+               s = &to_nv04_context(ctx)->dummy_texture;
+
+               format |= NV04_TEXTURED_TRIANGLE_FORMAT_ADDRESSU_REPEAT |
+                       NV04_TEXTURED_TRIANGLE_FORMAT_ADDRESSV_REPEAT |
+                       1 << 12 |
+                       NV04_TEXTURED_TRIANGLE_FORMAT_COLOR_A8R8G8B8;
+
+               filter |= NV04_TEXTURED_TRIANGLE_FILTER_MINIFY_NEAREST |
+                       NV04_TEXTURED_TRIANGLE_FILTER_MAGNIFY_NEAREST;
+       }
+
+       if (nv04_mtex_engine(fahrenheit)) {
+               nouveau_bo_markl(bctx, fahrenheit,
+                                NV04_MULTITEX_TRIANGLE_OFFSET(i),
+                                s->bo, 0, bo_flags);
+
+               nouveau_bo_mark(bctx, fahrenheit,
+                               NV04_MULTITEX_TRIANGLE_FORMAT(i),
+                               s->bo, format, 0,
+                               NV04_MULTITEX_TRIANGLE_FORMAT_DMA_A,
+                               NV04_MULTITEX_TRIANGLE_FORMAT_DMA_B,
+                               bo_flags | NOUVEAU_BO_OR);
+
+               BEGIN_RING(chan, fahrenheit, NV04_MULTITEX_TRIANGLE_FILTER(i), 1);
+               OUT_RING(chan, filter);
+
+       } else {
+               nouveau_bo_markl(bctx, fahrenheit,
+                                NV04_TEXTURED_TRIANGLE_OFFSET,
+                                s->bo, 0, bo_flags);
+
+               nouveau_bo_mark(bctx, fahrenheit,
+                               NV04_TEXTURED_TRIANGLE_FORMAT,
+                               s->bo, format, 0,
+                               NV04_TEXTURED_TRIANGLE_FORMAT_DMA_A,
+                               NV04_TEXTURED_TRIANGLE_FORMAT_DMA_B,
+                               bo_flags | NOUVEAU_BO_OR);
+
+               BEGIN_RING(chan, fahrenheit, NV04_TEXTURED_TRIANGLE_COLORKEY, 1);
+               OUT_RING(chan, 0);
+
+               BEGIN_RING(chan, fahrenheit, NV04_TEXTURED_TRIANGLE_FILTER, 1);
+               OUT_RING(chan, filter);
+       }
+}
diff --git a/src/mesa/drivers/dri/nouveau/nv04_surface.c b/src/mesa/drivers/dri/nouveau/nv04_surface.c
new file mode 100644 (file)
index 0000000..0d40349
--- /dev/null
@@ -0,0 +1,547 @@
+/*
+ * Copyright (C) 2007-2010 The Nouveau Project.
+ * 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.
+ *
+ */
+
+#include "nouveau_driver.h"
+#include "nouveau_class.h"
+#include "nouveau_context.h"
+#include "nouveau_util.h"
+#include "nv04_driver.h"
+
+static inline int
+swzsurf_format(gl_format format)
+{
+       switch (format) {
+       case MESA_FORMAT_A8:
+       case MESA_FORMAT_L8:
+       case MESA_FORMAT_I8:
+       case MESA_FORMAT_RGB332:
+       case MESA_FORMAT_CI8:
+               return NV04_SWIZZLED_SURFACE_FORMAT_COLOR_Y8;
+
+       case MESA_FORMAT_RGB565:
+       case MESA_FORMAT_RGB565_REV:
+       case MESA_FORMAT_ARGB4444:
+       case MESA_FORMAT_ARGB4444_REV:
+       case MESA_FORMAT_ARGB1555:
+       case MESA_FORMAT_RGBA5551:
+       case MESA_FORMAT_ARGB1555_REV:
+       case MESA_FORMAT_AL88:
+       case MESA_FORMAT_AL88_REV:
+       case MESA_FORMAT_YCBCR:
+       case MESA_FORMAT_YCBCR_REV:
+       case MESA_FORMAT_Z16:
+               return NV04_SWIZZLED_SURFACE_FORMAT_COLOR_R5G6B5;
+
+       case MESA_FORMAT_RGBA8888:
+       case MESA_FORMAT_RGBA8888_REV:
+       case MESA_FORMAT_XRGB8888:
+       case MESA_FORMAT_ARGB8888:
+       case MESA_FORMAT_ARGB8888_REV:
+       case MESA_FORMAT_S8_Z24:
+       case MESA_FORMAT_Z24_S8:
+       case MESA_FORMAT_Z32:
+               return NV04_SWIZZLED_SURFACE_FORMAT_COLOR_A8R8G8B8;
+
+       default:
+               assert(0);
+       }
+}
+
+static inline int
+surf2d_format(gl_format format)
+{
+       switch (format) {
+       case MESA_FORMAT_A8:
+       case MESA_FORMAT_L8:
+       case MESA_FORMAT_I8:
+       case MESA_FORMAT_RGB332:
+       case MESA_FORMAT_CI8:
+               return NV04_CONTEXT_SURFACES_2D_FORMAT_Y8;
+
+       case MESA_FORMAT_RGB565:
+       case MESA_FORMAT_RGB565_REV:
+       case MESA_FORMAT_ARGB4444:
+       case MESA_FORMAT_ARGB4444_REV:
+       case MESA_FORMAT_ARGB1555:
+       case MESA_FORMAT_RGBA5551:
+       case MESA_FORMAT_ARGB1555_REV:
+       case MESA_FORMAT_AL88:
+       case MESA_FORMAT_AL88_REV:
+       case MESA_FORMAT_YCBCR:
+       case MESA_FORMAT_YCBCR_REV:
+       case MESA_FORMAT_Z16:
+               return NV04_CONTEXT_SURFACES_2D_FORMAT_R5G6B5;
+
+       case MESA_FORMAT_RGBA8888:
+       case MESA_FORMAT_RGBA8888_REV:
+       case MESA_FORMAT_XRGB8888:
+       case MESA_FORMAT_ARGB8888:
+       case MESA_FORMAT_ARGB8888_REV:
+       case MESA_FORMAT_S8_Z24:
+       case MESA_FORMAT_Z24_S8:
+       case MESA_FORMAT_Z32:
+               return NV04_CONTEXT_SURFACES_2D_FORMAT_Y32;
+
+       default:
+               assert(0);
+       }
+}
+
+static inline int
+rect_format(gl_format format)
+{
+       switch (format) {
+       case MESA_FORMAT_A8:
+       case MESA_FORMAT_L8:
+       case MESA_FORMAT_I8:
+       case MESA_FORMAT_RGB332:
+       case MESA_FORMAT_CI8:
+               return NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A8R8G8B8;
+
+       case MESA_FORMAT_RGB565:
+       case MESA_FORMAT_RGB565_REV:
+       case MESA_FORMAT_ARGB4444:
+       case MESA_FORMAT_ARGB4444_REV:
+       case MESA_FORMAT_ARGB1555:
+       case MESA_FORMAT_RGBA5551:
+       case MESA_FORMAT_ARGB1555_REV:
+       case MESA_FORMAT_AL88:
+       case MESA_FORMAT_AL88_REV:
+       case MESA_FORMAT_YCBCR:
+       case MESA_FORMAT_YCBCR_REV:
+       case MESA_FORMAT_Z16:
+               return NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A16R5G6B5;
+
+       case MESA_FORMAT_RGBA8888:
+       case MESA_FORMAT_RGBA8888_REV:
+       case MESA_FORMAT_XRGB8888:
+       case MESA_FORMAT_ARGB8888:
+       case MESA_FORMAT_ARGB8888_REV:
+       case MESA_FORMAT_S8_Z24:
+       case MESA_FORMAT_Z24_S8:
+       case MESA_FORMAT_Z32:
+               return NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A8R8G8B8;
+
+       default:
+               assert(0);
+       }
+}
+
+static inline int
+sifm_format(gl_format format)
+{
+       switch (format) {
+       case MESA_FORMAT_A8:
+       case MESA_FORMAT_L8:
+       case MESA_FORMAT_I8:
+       case MESA_FORMAT_RGB332:
+       case MESA_FORMAT_CI8:
+               return NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_AY8;
+
+       case MESA_FORMAT_RGB565:
+       case MESA_FORMAT_RGB565_REV:
+       case MESA_FORMAT_ARGB4444:
+       case MESA_FORMAT_ARGB4444_REV:
+       case MESA_FORMAT_ARGB1555:
+       case MESA_FORMAT_RGBA5551:
+       case MESA_FORMAT_ARGB1555_REV:
+       case MESA_FORMAT_AL88:
+       case MESA_FORMAT_AL88_REV:
+       case MESA_FORMAT_YCBCR:
+       case MESA_FORMAT_YCBCR_REV:
+       case MESA_FORMAT_Z16:
+               return NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_R5G6B5;
+
+       case MESA_FORMAT_RGBA8888:
+       case MESA_FORMAT_RGBA8888_REV:
+       case MESA_FORMAT_XRGB8888:
+       case MESA_FORMAT_ARGB8888:
+       case MESA_FORMAT_ARGB8888_REV:
+       case MESA_FORMAT_S8_Z24:
+       case MESA_FORMAT_Z24_S8:
+       case MESA_FORMAT_Z32:
+               return NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_A8R8G8B8;
+
+       default:
+               assert(0);
+       }
+}
+
+static void
+nv04_surface_copy_swizzle(GLcontext *ctx,
+                         struct nouveau_surface *dst,
+                         struct nouveau_surface *src,
+                         int dx, int dy, int sx, int sy,
+                         int w, int h)
+{
+       struct nouveau_channel *chan = context_chan(ctx);
+       struct nouveau_screen *screen = to_nouveau_context(ctx)->screen;
+       struct nouveau_grobj *swzsurf = screen->swzsurf;
+       struct nouveau_grobj *sifm = screen->sifm;
+       struct nouveau_bo_context *bctx = context_bctx(ctx, SURFACE);
+       const unsigned bo_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART;
+       /* Max width & height may not be the same on all HW, but must be POT */
+       const unsigned max_w = 1024;
+       const unsigned max_h = 1024;
+       unsigned sub_w = w > max_w ? max_w : w;
+       unsigned sub_h = h > max_h ? max_h : h;
+       unsigned x, y;
+
+        /* Swizzled surfaces must be POT  */
+       assert(_mesa_is_pow_two(dst->width) &&
+              _mesa_is_pow_two(dst->height));
+
+        /* If area is too large to copy in one shot we must copy it in
+        * POT chunks to meet alignment requirements */
+       assert(sub_w == w || _mesa_is_pow_two(sub_w));
+       assert(sub_h == h || _mesa_is_pow_two(sub_h));
+
+       nouveau_bo_marko(bctx, sifm, NV03_SCALED_IMAGE_FROM_MEMORY_DMA_IMAGE,
+                        src->bo, bo_flags | NOUVEAU_BO_RD);
+       nouveau_bo_marko(bctx, swzsurf, NV04_SWIZZLED_SURFACE_DMA_IMAGE,
+                        dst->bo, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+       nouveau_bo_markl(bctx, swzsurf, NV04_SWIZZLED_SURFACE_OFFSET,
+                        dst->bo, dst->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+
+       BEGIN_RING(chan, swzsurf, NV04_SWIZZLED_SURFACE_FORMAT, 1);
+       OUT_RING  (chan, swzsurf_format(dst->format) |
+                  log2i(dst->width) << 16 |
+                  log2i(dst->height) << 24);
+
+       BEGIN_RING(chan, sifm, NV04_SCALED_IMAGE_FROM_MEMORY_SURFACE, 1);
+       OUT_RING  (chan, swzsurf->handle);
+
+       for (y = 0; y < h; y += sub_h) {
+               sub_h = MIN2(sub_h, h - y);
+
+               for (x = 0; x < w; x += sub_w) {
+                       sub_w = MIN2(sub_w, w - x);
+                       /* Must be 64-byte aligned */
+                       assert(!(dst->offset & 63));
+
+                       MARK_RING(chan, 15, 1);
+
+                       BEGIN_RING(chan, sifm,
+                                  NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT, 8);
+                       OUT_RING(chan, sifm_format(src->format));
+                       OUT_RING(chan, NV03_SCALED_IMAGE_FROM_MEMORY_OPERATION_SRCCOPY);
+                       OUT_RING(chan, (y + dy) << 16 | (x + dx));
+                       OUT_RING(chan, sub_h << 16 | sub_w);
+                       OUT_RING(chan, (y + dy) << 16 | (x + dx));
+                       OUT_RING(chan, sub_h << 16 | sub_w);
+                       OUT_RING(chan, 1 << 20);
+                       OUT_RING(chan, 1 << 20);
+
+                       BEGIN_RING(chan, sifm,
+                                  NV03_SCALED_IMAGE_FROM_MEMORY_SIZE, 4);
+                       OUT_RING(chan, sub_h << 16 | sub_w);
+                       OUT_RING(chan, src->pitch  |
+                                NV03_SCALED_IMAGE_FROM_MEMORY_FORMAT_ORIGIN_CENTER |
+                                NV03_SCALED_IMAGE_FROM_MEMORY_FORMAT_FILTER_POINT_SAMPLE);
+                       OUT_RELOCl(chan, src->bo, src->offset +
+                                  (y + sy) * src->pitch +
+                                  (x + sx) * src->cpp,
+                                  bo_flags | NOUVEAU_BO_RD);
+                       OUT_RING(chan, 0);
+               }
+       }
+
+       nouveau_bo_context_reset(bctx);
+
+       if (context_chipset(ctx) < 0x10)
+               FIRE_RING(chan);
+}
+
+static void
+nv04_surface_copy_m2mf(GLcontext *ctx,
+                         struct nouveau_surface *dst,
+                         struct nouveau_surface *src,
+                         int dx, int dy, int sx, int sy,
+                         int w, int h)
+{
+       struct nouveau_channel *chan = context_chan(ctx);
+       struct nouveau_screen *screen = to_nouveau_context(ctx)->screen;
+       struct nouveau_grobj *m2mf = screen->m2mf;
+       struct nouveau_bo_context *bctx = context_bctx(ctx, SURFACE);
+       const unsigned bo_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART;
+       unsigned dst_offset = dst->offset + dy * dst->pitch + dx * dst->cpp;
+       unsigned src_offset = src->offset + sy * src->pitch + sx * src->cpp;
+
+       nouveau_bo_marko(bctx, m2mf, NV04_MEMORY_TO_MEMORY_FORMAT_DMA_BUFFER_IN,
+                        src->bo, bo_flags | NOUVEAU_BO_RD);
+       nouveau_bo_marko(bctx, m2mf, NV04_MEMORY_TO_MEMORY_FORMAT_DMA_BUFFER_OUT,
+                        dst->bo, bo_flags | NOUVEAU_BO_WR);
+
+       while (h) {
+               int count = (h > 2047) ? 2047 : h;
+
+               MARK_RING(chan, 9, 2);
+
+               BEGIN_RING(chan, m2mf, NV04_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
+               OUT_RELOCl(chan, src->bo, src_offset,
+                          bo_flags | NOUVEAU_BO_RD);
+               OUT_RELOCl(chan, dst->bo, dst_offset,
+                          bo_flags | NOUVEAU_BO_WR);
+               OUT_RING  (chan, src->pitch);
+               OUT_RING  (chan, dst->pitch);
+               OUT_RING  (chan, w * src->cpp);
+               OUT_RING  (chan, count);
+               OUT_RING  (chan, 0x0101);
+               OUT_RING  (chan, 0);
+
+               h -= count;
+               src_offset += src->pitch * count;
+               dst_offset += dst->pitch * count;
+       }
+
+       nouveau_bo_context_reset(bctx);
+
+       if (context_chipset(ctx) < 0x10)
+               FIRE_RING(chan);
+}
+
+void
+nv04_surface_copy(GLcontext *ctx,
+                 struct nouveau_surface *dst,
+                 struct nouveau_surface *src,
+                 int dx, int dy, int sx, int sy,
+                 int w, int h)
+{
+       /* Setup transfer to swizzle the texture to vram if needed */
+        if (src->layout != SWIZZLED &&
+           dst->layout == SWIZZLED &&
+           dst->width > 2 && dst->height > 1) {
+               nv04_surface_copy_swizzle(ctx, dst, src,
+                                         dx, dy, sx, sy, w, h);
+               return;
+       }
+
+       nv04_surface_copy_m2mf(ctx, dst, src, dx, dy, sx, sy, w, h);
+}
+
+void
+nv04_surface_fill(GLcontext *ctx,
+                 struct nouveau_surface *dst,
+                 unsigned mask, unsigned value,
+                 int dx, int dy, int w, int h)
+{
+       struct nouveau_channel *chan = context_chan(ctx);
+       struct nouveau_screen *screen = to_nouveau_context(ctx)->screen;
+       struct nouveau_grobj *surf2d = screen->surf2d;
+       struct nouveau_grobj *patt = screen->patt;
+       struct nouveau_grobj *rect = screen->rect;
+       unsigned bo_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART;
+
+       MARK_RING (chan, 19, 4);
+
+       BEGIN_RING(chan, surf2d, NV04_CONTEXT_SURFACES_2D_DMA_IMAGE_SOURCE, 2);
+       OUT_RELOCo(chan, dst->bo, bo_flags | NOUVEAU_BO_WR);
+       OUT_RELOCo(chan, dst->bo, bo_flags | NOUVEAU_BO_WR);
+       BEGIN_RING(chan, surf2d, NV04_CONTEXT_SURFACES_2D_FORMAT, 4);
+       OUT_RING  (chan, surf2d_format(dst->format));
+       OUT_RING  (chan, (dst->pitch << 16) | dst->pitch);
+       OUT_RELOCl(chan, dst->bo, dst->offset, bo_flags | NOUVEAU_BO_WR);
+       OUT_RELOCl(chan, dst->bo, dst->offset, bo_flags | NOUVEAU_BO_WR);
+
+       BEGIN_RING(chan, patt, NV04_IMAGE_PATTERN_COLOR_FORMAT, 1);
+       OUT_RING  (chan, rect_format(dst->format));
+       BEGIN_RING(chan, patt, NV04_IMAGE_PATTERN_MONOCHROME_COLOR1, 1);
+       OUT_RING  (chan, mask | ~0 << (8 * dst->cpp));
+
+       BEGIN_RING(chan, rect, NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT, 1);
+       OUT_RING  (chan, rect_format(dst->format));
+       BEGIN_RING(chan, rect, NV04_GDI_RECTANGLE_TEXT_COLOR1_A, 1);
+       OUT_RING  (chan, value);
+       BEGIN_RING(chan, rect,
+                  NV04_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_POINT(0), 2);
+       OUT_RING  (chan, (dx << 16) | dy);
+       OUT_RING  (chan, ( w << 16) |  h);
+
+       if (context_chipset(ctx) < 0x10)
+               FIRE_RING(chan);
+}
+
+void
+nv04_surface_takedown(struct nouveau_screen *screen)
+{
+       nouveau_grobj_free(&screen->swzsurf);
+       nouveau_grobj_free(&screen->sifm);
+       nouveau_grobj_free(&screen->rect);
+       nouveau_grobj_free(&screen->rop);
+       nouveau_grobj_free(&screen->patt);
+       nouveau_grobj_free(&screen->surf2d);
+       nouveau_grobj_free(&screen->m2mf);
+       nouveau_notifier_free(&screen->ntfy);
+}
+
+GLboolean
+nv04_surface_init(struct nouveau_screen *screen)
+{
+       struct nouveau_channel *chan = screen->chan;
+       const unsigned chipset = screen->device->chipset;
+       unsigned handle = 0x88000000, class;
+       int ret;
+
+       /* Notifier object. */
+       ret = nouveau_notifier_alloc(chan, handle++, 1, &screen->ntfy);
+       if (ret)
+               goto fail;
+
+       /* Memory to memory format. */
+       ret = nouveau_grobj_alloc(chan, handle++, NV04_MEMORY_TO_MEMORY_FORMAT,
+                                 &screen->m2mf);
+       if (ret)
+               goto fail;
+
+       BEGIN_RING(chan, screen->m2mf, NV04_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 1);
+       OUT_RING  (chan, screen->ntfy->handle);
+
+       /* Context surfaces 2D. */
+       if (chan->device->chipset < 0x10)
+               class = NV04_CONTEXT_SURFACES_2D;
+       else
+               class = NV10_CONTEXT_SURFACES_2D;
+
+       ret = nouveau_grobj_alloc(chan, handle++, class, &screen->surf2d);
+       if (ret)
+               goto fail;
+
+       /* Raster op. */
+       ret = nouveau_grobj_alloc(chan, handle++, NV03_CONTEXT_ROP,
+                                 &screen->rop);
+       if (ret)
+               goto fail;
+
+       BEGIN_RING(chan, screen->rop, NV03_CONTEXT_ROP_DMA_NOTIFY, 1);
+       OUT_RING  (chan, screen->ntfy->handle);
+
+       BEGIN_RING(chan, screen->rop, NV03_CONTEXT_ROP_ROP, 1);
+       OUT_RING  (chan, 0xca); /* DPSDxax in the GDI speech. */
+
+       /* Image pattern. */
+       ret = nouveau_grobj_alloc(chan, handle++, NV04_IMAGE_PATTERN,
+                                 &screen->patt);
+       if (ret)
+               goto fail;
+
+       BEGIN_RING(chan, screen->patt,
+                  NV04_IMAGE_PATTERN_DMA_NOTIFY, 1);
+       OUT_RING  (chan, screen->ntfy->handle);
+
+       BEGIN_RING(chan, screen->patt,
+                  NV04_IMAGE_PATTERN_MONOCHROME_FORMAT, 3);
+       OUT_RING  (chan, NV04_IMAGE_PATTERN_MONOCHROME_FORMAT_LE);
+       OUT_RING  (chan, NV04_IMAGE_PATTERN_MONOCHROME_SHAPE_8X8);
+       OUT_RING  (chan, NV04_IMAGE_PATTERN_PATTERN_SELECT_MONO);
+
+       BEGIN_RING(chan, screen->patt,
+                  NV04_IMAGE_PATTERN_MONOCHROME_COLOR0, 4);
+       OUT_RING  (chan, 0);
+       OUT_RING  (chan, 0);
+       OUT_RING  (chan, ~0);
+       OUT_RING  (chan, ~0);
+
+       /* GDI rectangle text. */
+       ret = nouveau_grobj_alloc(chan, handle++, NV04_GDI_RECTANGLE_TEXT,
+                                 &screen->rect);
+       if (ret)
+               goto fail;
+
+       BEGIN_RING(chan, screen->rect, NV04_GDI_RECTANGLE_TEXT_DMA_NOTIFY, 1);
+       OUT_RING  (chan, screen->ntfy->handle);
+       BEGIN_RING(chan, screen->rect, NV04_GDI_RECTANGLE_TEXT_SURFACE, 1);
+       OUT_RING  (chan, screen->surf2d->handle);
+       BEGIN_RING(chan, screen->rect, NV04_GDI_RECTANGLE_TEXT_ROP, 1);
+       OUT_RING  (chan, screen->rop->handle);
+       BEGIN_RING(chan, screen->rect, NV04_GDI_RECTANGLE_TEXT_PATTERN, 1);
+       OUT_RING  (chan, screen->patt->handle);
+
+       BEGIN_RING(chan, screen->rect, NV04_GDI_RECTANGLE_TEXT_OPERATION, 1);
+       OUT_RING  (chan, NV04_GDI_RECTANGLE_TEXT_OPERATION_ROP_AND);
+       BEGIN_RING(chan, screen->rect,
+                  NV04_GDI_RECTANGLE_TEXT_MONOCHROME_FORMAT, 1);
+       OUT_RING  (chan, NV04_GDI_RECTANGLE_TEXT_MONOCHROME_FORMAT_LE);
+
+       /* Swizzled surface. */
+       switch (chan->device->chipset & 0xf0) {
+       case 0x00:
+       case 0x10:
+               class = NV04_SWIZZLED_SURFACE;
+               break;
+       case 0x20:
+               class = NV20_SWIZZLED_SURFACE;
+               break;
+       case 0x30:
+               class = NV30_SWIZZLED_SURFACE;
+               break;
+       case 0x40:
+       case 0x60:
+               class = NV40_SWIZZLED_SURFACE;
+               break;
+       default:
+               /* Famous last words: this really can't happen.. */
+               assert(0);
+               break;
+       }
+
+       ret = nouveau_grobj_alloc(chan, handle++, class, &screen->swzsurf);
+       if (ret)
+               goto fail;
+
+       /* Scaled image from memory. */
+       switch (chan->device->chipset & 0xf0) {
+       case 0x10:
+       case 0x20:
+               class = NV10_SCALED_IMAGE_FROM_MEMORY;
+               break;
+       case 0x30:
+               class = NV30_SCALED_IMAGE_FROM_MEMORY;
+               break;
+       case 0x40:
+       case 0x60:
+               class = NV40_SCALED_IMAGE_FROM_MEMORY;
+               break;
+       default:
+               class = NV04_SCALED_IMAGE_FROM_MEMORY;
+               break;
+       }
+
+       ret = nouveau_grobj_alloc(chan, handle++, class, &screen->sifm);
+       if (ret)
+               goto fail;
+
+       if (chipset >= 0x10) {
+               BEGIN_RING(chan, screen->sifm,
+                          NV05_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION, 1);
+               OUT_RING(chan, NV05_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION_TRUNCATE);
+       }
+
+       return GL_TRUE;
+
+fail:
+       nv04_surface_takedown(screen);
+       return GL_FALSE;
+}
diff --git a/src/mesa/drivers/dri/nouveau/nv10_context.c b/src/mesa/drivers/dri/nouveau/nv10_context.c
new file mode 100644 (file)
index 0000000..d1afa87
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2009 Francisco Jerez.
+ * 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.
+ *
+ */
+
+#include "nouveau_driver.h"
+#include "nouveau_context.h"
+#include "nouveau_fbo.h"
+#include "nouveau_util.h"
+#include "nouveau_class.h"
+#include "nv10_driver.h"
+
+static void
+nv10_clear(GLcontext *ctx, GLbitfield buffers)
+{
+       struct nouveau_channel *chan = context_chan(ctx);
+       struct nouveau_grobj *celsius = context_eng3d(ctx);
+       struct nouveau_framebuffer *nfb = to_nouveau_framebuffer(
+               ctx->DrawBuffer);
+
+       nouveau_validate_framebuffer(ctx);
+
+       /* Clear the LMA depth buffer, if present. */
+       if ((buffers & BUFFER_BIT_DEPTH) && ctx->Depth.Mask &&
+           nfb->lma_bo) {
+               struct nouveau_surface *s = &to_nouveau_renderbuffer(
+                       nfb->base._DepthBuffer->Wrapped)->surface;
+
+               BEGIN_RING(chan, celsius, NV17TCL_LMA_DEPTH_FILL_VALUE, 1);
+               OUT_RING(chan, pack_zs_f(s->format, ctx->Depth.Clear, 0));
+               BEGIN_RING(chan, celsius, NV17TCL_LMA_DEPTH_BUFFER_CLEAR, 1);
+               OUT_RING(chan, 1);
+       }
+
+       nouveau_clear(ctx, buffers);
+}
+
+GLcontext *
+nv10_context_create(struct nouveau_screen *screen, const GLvisual *visual,
+                   GLcontext *share_ctx)
+{
+       struct nouveau_context *nctx;
+       GLcontext *ctx;
+
+       nctx = CALLOC_STRUCT(nouveau_context);
+       if (!nctx)
+               return NULL;
+
+       ctx = &nctx->base;
+       nouveau_context_init(ctx, screen, visual, share_ctx);
+
+       ctx->Const.MaxTextureLevels = 12;
+       ctx->Const.MaxTextureCoordUnits = NV10_TEXTURE_UNITS;
+       ctx->Const.MaxTextureImageUnits = NV10_TEXTURE_UNITS;
+       ctx->Const.MaxTextureUnits = NV10_TEXTURE_UNITS;
+       ctx->Const.MaxTextureMaxAnisotropy = 2;
+       ctx->Const.MaxTextureLodBias = 15;
+       ctx->Driver.Clear = nv10_clear;
+
+       nv10_render_init(ctx);
+
+       return ctx;
+}
+
+void
+nv10_context_destroy(GLcontext *ctx)
+{
+       nv10_render_destroy(ctx);
+       FREE(ctx);
+}
diff --git a/src/mesa/drivers/dri/nouveau/nv10_driver.h b/src/mesa/drivers/dri/nouveau/nv10_driver.h
new file mode 100644 (file)
index 0000000..2a1ef7b
--- /dev/null
@@ -0,0 +1,192 @@
+/*
+ * Copyright (C) 2009 Francisco Jerez.
+ * 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.
+ *
+ */
+
+#ifndef __NV10_DRIVER_H__
+#define __NV10_DRIVER_H__
+
+#define NV10_TEXTURE_UNITS 2
+
+/* nv10_screen.c */
+GLboolean
+nv10_screen_init(struct nouveau_screen *screen);
+
+/* nv10_context.c */
+GLcontext *
+nv10_context_create(struct nouveau_screen *screen, const GLvisual *visual,
+                   GLcontext *share_ctx);
+
+void
+nv10_context_destroy(GLcontext *ctx);
+
+/* nv10_render.c */
+void
+nv10_render_init(GLcontext *ctx);
+
+void
+nv10_render_destroy(GLcontext *ctx);
+
+/* nv10_state_fb.c */
+void
+nv10_emit_framebuffer(GLcontext *ctx, int emit);
+
+void
+nv10_emit_render_mode(GLcontext *ctx, int emit);
+
+void
+nv10_emit_scissor(GLcontext *ctx, int emit);
+
+void
+nv10_emit_viewport(GLcontext *ctx, int emit);
+
+/* nv10_state_polygon.c */
+void
+nv10_emit_cull_face(GLcontext *ctx, int emit);
+
+void
+nv10_emit_front_face(GLcontext *ctx, int emit);
+
+void
+nv10_emit_line_mode(GLcontext *ctx, int emit);
+
+void
+nv10_emit_line_stipple(GLcontext *ctx, int emit);
+
+void
+nv10_emit_point_mode(GLcontext *ctx, int emit);
+
+void
+nv10_emit_polygon_mode(GLcontext *ctx, int emit);
+
+void
+nv10_emit_polygon_offset(GLcontext *ctx, int emit);
+
+void
+nv10_emit_polygon_stipple(GLcontext *ctx, int emit);
+
+/* nv10_state_raster.c */
+void
+nv10_emit_alpha_func(GLcontext *ctx, int emit);
+
+void
+nv10_emit_blend_color(GLcontext *ctx, int emit);
+
+void
+nv10_emit_blend_equation(GLcontext *ctx, int emit);
+
+void
+nv10_emit_blend_func(GLcontext *ctx, int emit);
+
+void
+nv10_emit_color_mask(GLcontext *ctx, int emit);
+
+void
+nv10_emit_depth(GLcontext *ctx, int emit);
+
+void
+nv10_emit_dither(GLcontext *ctx, int emit);
+
+void
+nv10_emit_index_mask(GLcontext *ctx, int emit);
+
+void
+nv10_emit_logic_opcode(GLcontext *ctx, int emit);
+
+void
+nv10_emit_shade_model(GLcontext *ctx, int emit);
+
+void
+nv10_emit_stencil_func(GLcontext *ctx, int emit);
+
+void
+nv10_emit_stencil_mask(GLcontext *ctx, int emit);
+
+void
+nv10_emit_stencil_op(GLcontext *ctx, int emit);
+
+/* nv10_state_frag.c */
+void
+nv10_emit_tex_env(GLcontext *ctx, int emit);
+
+void
+nv10_emit_frag(GLcontext *ctx, int emit);
+
+/* nv10_state_tex.c */
+void
+nv10_emit_tex_gen(GLcontext *ctx, int emit);
+
+void
+nv10_emit_tex_obj(GLcontext *ctx, int emit);
+
+/* nv10_state_tnl.c */
+void
+nv10_get_fog_coeff(GLcontext *ctx, float k[3]);
+
+void
+nv10_get_spot_coeff(struct gl_light *l, float k[7]);
+
+void
+nv10_get_shininess_coeff(float s, float k[6]);
+
+void
+nv10_emit_clip_plane(GLcontext *ctx, int emit);
+
+void
+nv10_emit_color_material(GLcontext *ctx, int emit);
+
+void
+nv10_emit_fog(GLcontext *ctx, int emit);
+
+void
+nv10_emit_light_enable(GLcontext *ctx, int emit);
+
+void
+nv10_emit_light_model(GLcontext *ctx, int emit);
+
+void
+nv10_emit_light_source(GLcontext *ctx, int emit);
+
+void
+nv10_emit_material_ambient(GLcontext *ctx, int emit);
+
+void
+nv10_emit_material_diffuse(GLcontext *ctx, int emit);
+
+void
+nv10_emit_material_specular(GLcontext *ctx, int emit);
+
+void
+nv10_emit_material_shininess(GLcontext *ctx, int emit);
+
+void
+nv10_emit_modelview(GLcontext *ctx, int emit);
+
+void
+nv10_emit_point_parameter(GLcontext *ctx, int emit);
+
+void
+nv10_emit_projection(GLcontext *ctx, int emit);
+
+#endif
diff --git a/src/mesa/drivers/dri/nouveau/nv10_render.c b/src/mesa/drivers/dri/nouveau/nv10_render.c
new file mode 100644 (file)
index 0000000..54245ea
--- /dev/null
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2009-2010 Francisco Jerez.
+ * 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.
+ *
+ */
+
+#include "nouveau_driver.h"
+#include "nouveau_context.h"
+#include "nouveau_class.h"
+#include "nv10_driver.h"
+
+#define NUM_VERTEX_ATTRS 8
+
+static void
+nv10_emit_material(GLcontext *ctx, struct nouveau_array_state *a,
+                  const void *v);
+
+/* Vertex attribute format. */
+static struct nouveau_attr_info nv10_vertex_attrs[VERT_ATTRIB_MAX] = {
+       [VERT_ATTRIB_POS] = {
+               .vbo_index = 0,
+               .imm_method = NV10TCL_VERTEX_POS_4F_X,
+               .imm_fields = 4,
+       },
+       [VERT_ATTRIB_COLOR0] = {
+               .vbo_index = 1,
+               .imm_method = NV10TCL_VERTEX_COL_4F_R,
+               .imm_fields = 4,
+       },
+       [VERT_ATTRIB_COLOR1] = {
+               .vbo_index = 2,
+               .imm_method = NV10TCL_VERTEX_COL2_3F_R,
+               .imm_fields = 3,
+       },
+       [VERT_ATTRIB_TEX0] = {
+               .vbo_index = 3,
+               .imm_method = NV10TCL_VERTEX_TX0_4F_S,
+               .imm_fields = 4,
+       },
+       [VERT_ATTRIB_TEX1] = {
+               .vbo_index = 4,
+               .imm_method = NV10TCL_VERTEX_TX1_4F_S,
+               .imm_fields = 4,
+       },
+       [VERT_ATTRIB_NORMAL] = {
+               .vbo_index = 5,
+               .imm_method = NV10TCL_VERTEX_NOR_3F_X,
+               .imm_fields = 3,
+       },
+       [VERT_ATTRIB_FOG] = {
+               .vbo_index = 7,
+               .imm_method = NV10TCL_VERTEX_FOG_1F,
+               .imm_fields = 1,
+       },
+       [VERT_ATTRIB_GENERIC0] = {
+               .emit = nv10_emit_material,
+       },
+       [VERT_ATTRIB_GENERIC2] = {
+               .emit = nv10_emit_material,
+       },
+       [VERT_ATTRIB_GENERIC4] = {
+               .emit = nv10_emit_material,
+       },
+       [VERT_ATTRIB_GENERIC6] = {
+               .emit = nv10_emit_material,
+       },
+       [VERT_ATTRIB_GENERIC8] = {
+               .emit = nv10_emit_material,
+       },
+};
+
+static int
+get_hw_format(int type)
+{
+       switch (type) {
+       case GL_FLOAT:
+               return NV10TCL_VTXFMT_TYPE_FLOAT;
+       case GL_SHORT:
+       case GL_UNSIGNED_SHORT:
+               return NV10TCL_VTXFMT_TYPE_SHORT;
+       case GL_UNSIGNED_BYTE:
+               return NV10TCL_VTXFMT_TYPE_BYTE_RGBA;
+       default:
+               assert(0);
+       }
+}
+
+static void
+nv10_render_set_format(GLcontext *ctx)
+{
+       struct nouveau_render_state *render = to_render_state(ctx);
+       struct nouveau_channel *chan = context_chan(ctx);
+       struct nouveau_grobj *celsius = context_eng3d(ctx);
+       int i, hw_format;
+
+       for (i = 0; i < NUM_VERTEX_ATTRS; i++) {
+               int attr = render->map[i];
+
+               if (attr >= 0) {
+                       struct nouveau_array_state *a = &render->attrs[attr];
+
+                       hw_format = a->stride << 8 |
+                               a->fields << 4 |
+                               get_hw_format(a->type);
+
+                       if (attr == VERT_ATTRIB_POS && a->fields == 4)
+                               hw_format |= NV10TCL_VTXFMT_POS_HOMOGENEOUS;
+               } else {
+                       /* Unused attribute. */
+                       hw_format = NV10TCL_VTXFMT_TYPE_FLOAT;
+               }
+
+               BEGIN_RING(chan, celsius, NV10TCL_VTXFMT(i), 1);
+               OUT_RING(chan, hw_format);
+       }
+}
+
+static void
+nv10_render_bind_vertices(GLcontext *ctx)
+{
+       struct nouveau_render_state *render = to_render_state(ctx);
+       struct nouveau_bo_context *bctx = context_bctx(ctx, VERTEX);
+       struct nouveau_channel *chan = context_chan(ctx);
+       struct nouveau_grobj *celsius = context_eng3d(ctx);
+       int i;
+
+       for (i = 0; i < NUM_VERTEX_ATTRS; i++) {
+               int attr = render->map[i];
+
+               if (attr >= 0) {
+                       struct nouveau_array_state *a = &render->attrs[attr];
+
+                       nouveau_bo_markl(bctx, celsius,
+                                        NV10TCL_VTXBUF_ADDRESS(i),
+                                        a->bo, a->offset,
+                                        NOUVEAU_BO_GART | NOUVEAU_BO_RD);
+               }
+       }
+
+       BEGIN_RING(chan, celsius, NV10TCL_VERTEX_ARRAY_VALIDATE, 1);
+       OUT_RING(chan, 0);
+}
+
+/* Vertex array rendering defs. */
+#define RENDER_LOCALS(ctx)                                     \
+       struct nouveau_grobj *celsius = context_eng3d(ctx)
+
+#define BATCH_BEGIN(prim)                                              \
+       BEGIN_RING(chan, celsius, NV10TCL_VERTEX_BUFFER_BEGIN_END, 1);  \
+       OUT_RING(chan, prim);
+#define BATCH_END()                                                    \
+       BEGIN_RING(chan, celsius, NV10TCL_VERTEX_BUFFER_BEGIN_END, 1);  \
+       OUT_RING(chan, 0);
+
+#define MAX_PACKET 0x400
+
+#define MAX_OUT_L 0x100
+#define BATCH_PACKET_L(n)                                              \
+       BEGIN_RING_NI(chan, celsius, NV10TCL_VERTEX_BUFFER_DRAW_ARRAYS, n);
+#define BATCH_OUT_L(i, n)                      \
+       OUT_RING(chan, ((n) - 1) << 24 | (i));
+
+#define MAX_OUT_I16 0x2
+#define BATCH_PACKET_I16(n)                                            \
+       BEGIN_RING_NI(chan, celsius, NV10TCL_VB_ELEMENT_U16, n);
+#define BATCH_OUT_I16(i0, i1)                  \
+       OUT_RING(chan, (i1) << 16 | (i0));
+
+#define MAX_OUT_I32 0x1
+#define BATCH_PACKET_I32(n)                                            \
+       BEGIN_RING_NI(chan, celsius, NV10TCL_VB_ELEMENT_U32, n);
+#define BATCH_OUT_I32(i)                       \
+       OUT_RING(chan, i);
+
+#define IMM_PACKET(m, n)                       \
+       BEGIN_RING(chan, celsius, m, n);
+#define IMM_OUT(x)                             \
+       OUT_RINGf(chan, x);
+
+#define TAG(x) nv10_##x
+#include "nouveau_render_t.c"
diff --git a/src/mesa/drivers/dri/nouveau/nv10_screen.c b/src/mesa/drivers/dri/nouveau/nv10_screen.c
new file mode 100644 (file)
index 0000000..8665ad1
--- /dev/null
@@ -0,0 +1,364 @@
+/*
+ * Copyright (C) 2009 Francisco Jerez.
+ * 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.
+ *
+ */
+
+#include "nouveau_driver.h"
+#include "nouveau_screen.h"
+#include "nouveau_class.h"
+#include "nv04_driver.h"
+#include "nv10_driver.h"
+
+static const struct nouveau_driver nv10_driver;
+
+static void
+nv10_hwctx_init(struct nouveau_screen *screen)
+{
+       struct nouveau_channel *chan = screen->chan;
+       struct nouveau_grobj *celsius = screen->eng3d;
+       const unsigned chipset = screen->device->chipset;
+       int i;
+
+       BEGIN_RING(chan, celsius, NV10TCL_DMA_NOTIFY, 1);
+       OUT_RING(chan, screen->ntfy->handle);
+
+       BEGIN_RING(chan, celsius, NV10TCL_DMA_IN_MEMORY0, 3);
+       OUT_RING(chan, chan->vram->handle);
+       OUT_RING(chan, chan->gart->handle);
+       OUT_RING(chan, chan->gart->handle);
+       BEGIN_RING(chan, celsius, NV10TCL_DMA_IN_MEMORY2, 2);
+       OUT_RING(chan, chan->vram->handle);
+       OUT_RING(chan, chan->vram->handle);
+
+       BEGIN_RING(chan, celsius, NV10TCL_NOP, 1);
+       OUT_RING(chan, 0);
+
+       BEGIN_RING(chan, celsius, NV10TCL_RT_HORIZ, 2);
+       OUT_RING(chan, 0);
+       OUT_RING(chan, 0);
+
+       BEGIN_RING(chan, celsius, NV10TCL_VIEWPORT_CLIP_HORIZ(0), 1);
+       OUT_RING(chan, 0x7ff << 16 | 0x800);
+       BEGIN_RING(chan, celsius, NV10TCL_VIEWPORT_CLIP_VERT(0), 1);
+       OUT_RING(chan, 0x7ff << 16 | 0x800);
+
+       for (i = 1; i < 8; i++) {
+               BEGIN_RING(chan, celsius, NV10TCL_VIEWPORT_CLIP_HORIZ(i), 1);
+               OUT_RING(chan, 0);
+               BEGIN_RING(chan, celsius, NV10TCL_VIEWPORT_CLIP_VERT(i), 1);
+               OUT_RING(chan, 0);
+       }
+
+       BEGIN_RING(chan, celsius, 0x290, 1);
+       OUT_RING(chan, 0x10 << 16 | 1);
+       BEGIN_RING(chan, celsius, 0x3f4, 1);
+       OUT_RING(chan, 0);
+
+       BEGIN_RING(chan, celsius, NV10TCL_NOP, 1);
+       OUT_RING(chan, 0);
+
+       if (chipset >= 0x17) {
+               BEGIN_RING(chan, celsius, NV17TCL_DMA_IN_MEMORY4, 2);
+               OUT_RING(chan, chan->vram->handle);
+               OUT_RING(chan, chan->vram->handle);
+
+               BEGIN_RING(chan, celsius, 0xd84, 1);
+               OUT_RING(chan, 0x3);
+
+               BEGIN_RING(chan, celsius, NV17TCL_COLOR_MASK_ENABLE, 1);
+               OUT_RING(chan, 1);
+       }
+
+       if (chipset >= 0x11) {
+               BEGIN_RING(chan, celsius, 0x120, 3);
+               OUT_RING(chan, 0);
+               OUT_RING(chan, 1);
+               OUT_RING(chan, 2);
+
+               BEGIN_RING(chan, celsius, NV10TCL_NOP, 1);
+               OUT_RING(chan, 0);
+       }
+
+       BEGIN_RING(chan, celsius, NV10TCL_NOP, 1);
+       OUT_RING(chan, 0);
+
+       /* Set state */
+       BEGIN_RING(chan, celsius, NV10TCL_FOG_ENABLE, 1);
+       OUT_RING(chan, 0);
+       BEGIN_RING(chan, celsius, NV10TCL_ALPHA_FUNC_ENABLE, 1);
+       OUT_RING(chan, 0);
+       BEGIN_RING(chan, celsius, NV10TCL_ALPHA_FUNC_FUNC, 2);
+       OUT_RING(chan, 0x207);
+       OUT_RING(chan, 0);
+       BEGIN_RING(chan, celsius, NV10TCL_TX_ENABLE(0), 2);
+       OUT_RING(chan, 0);
+       OUT_RING(chan, 0);
+
+       BEGIN_RING(chan, celsius, NV10TCL_BLEND_FUNC_ENABLE, 1);
+       OUT_RING(chan, 0);
+       BEGIN_RING(chan, celsius, NV10TCL_DITHER_ENABLE, 2);
+       OUT_RING(chan, 1);
+       OUT_RING(chan, 0);
+       BEGIN_RING(chan, celsius, NV10TCL_LINE_SMOOTH_ENABLE, 1);
+       OUT_RING(chan, 0);
+       BEGIN_RING(chan, celsius, NV10TCL_VERTEX_WEIGHT_ENABLE, 2);
+       OUT_RING(chan, 0);
+       OUT_RING(chan, 0);
+       BEGIN_RING(chan, celsius, NV10TCL_BLEND_FUNC_SRC, 4);
+       OUT_RING(chan, 1);
+       OUT_RING(chan, 0);
+       OUT_RING(chan, 0);
+       OUT_RING(chan, 0x8006);
+       BEGIN_RING(chan, celsius, NV10TCL_STENCIL_MASK, 8);
+       OUT_RING(chan, 0xff);
+       OUT_RING(chan, 0x207);
+       OUT_RING(chan, 0);
+       OUT_RING(chan, 0xff);
+       OUT_RING(chan, 0x1e00);
+       OUT_RING(chan, 0x1e00);
+       OUT_RING(chan, 0x1e00);
+       OUT_RING(chan, 0x1d01);
+       BEGIN_RING(chan, celsius, NV10TCL_NORMALIZE_ENABLE, 1);
+       OUT_RING(chan, 0);
+       BEGIN_RING(chan, celsius, NV10TCL_FOG_ENABLE, 2);
+       OUT_RING(chan, 0);
+       OUT_RING(chan, 0);
+       BEGIN_RING(chan, celsius, NV10TCL_LIGHT_MODEL, 1);
+       OUT_RING(chan, 0);
+       BEGIN_RING(chan, celsius, NV10TCL_SEPARATE_SPECULAR_ENABLE, 1);
+       OUT_RING(chan, 0);
+       BEGIN_RING(chan, celsius, NV10TCL_ENABLED_LIGHTS, 1);
+       OUT_RING(chan, 0);
+       BEGIN_RING(chan, celsius, NV10TCL_POLYGON_OFFSET_POINT_ENABLE, 3);
+       OUT_RING(chan, 0);
+       OUT_RING(chan, 0);
+       OUT_RING(chan, 0);
+       BEGIN_RING(chan, celsius, NV10TCL_DEPTH_FUNC, 1);
+       OUT_RING(chan, 0x201);
+       BEGIN_RING(chan, celsius, NV10TCL_DEPTH_WRITE_ENABLE, 1);
+       OUT_RING(chan, 0);
+       BEGIN_RING(chan, celsius, NV10TCL_DEPTH_TEST_ENABLE, 1);
+       OUT_RING(chan, 0);
+       BEGIN_RING(chan, celsius, NV10TCL_POLYGON_OFFSET_FACTOR, 2);
+       OUT_RING(chan, 0);
+       OUT_RING(chan, 0);
+       BEGIN_RING(chan, celsius, NV10TCL_POINT_SIZE, 1);
+       OUT_RING(chan, 8);
+       BEGIN_RING(chan, celsius, NV10TCL_POINT_PARAMETERS_ENABLE, 2);
+       OUT_RING(chan, 0);
+       OUT_RING(chan, 0);
+       BEGIN_RING(chan, celsius, NV10TCL_LINE_WIDTH, 1);
+       OUT_RING(chan, 8);
+       BEGIN_RING(chan, celsius, NV10TCL_LINE_SMOOTH_ENABLE, 1);
+       OUT_RING(chan, 0);
+       BEGIN_RING(chan, celsius, NV10TCL_POLYGON_MODE_FRONT, 2);
+       OUT_RING(chan, 0x1b02);
+       OUT_RING(chan, 0x1b02);
+       BEGIN_RING(chan, celsius, NV10TCL_CULL_FACE, 2);
+       OUT_RING(chan, 0x405);
+       OUT_RING(chan, 0x901);
+       BEGIN_RING(chan, celsius, NV10TCL_POLYGON_SMOOTH_ENABLE, 1);
+       OUT_RING(chan, 0);
+       BEGIN_RING(chan, celsius, NV10TCL_CULL_FACE_ENABLE, 1);
+       OUT_RING(chan, 0);
+       BEGIN_RING(chan, celsius, NV10TCL_TX_GEN_S(0), 8);
+       for (i = 0; i < 8; i++)
+               OUT_RING(chan, 0);
+
+       BEGIN_RING(chan, celsius, NV10TCL_TX_MATRIX_ENABLE(0), 2);
+       OUT_RING(chan, 0);
+       OUT_RING(chan, 0);
+       BEGIN_RING(chan, celsius, NV10TCL_FOG_EQUATION_CONSTANT, 3);
+       OUT_RING(chan, 0x3fc00000);     /* -1.50 */
+       OUT_RING(chan, 0xbdb8aa0a);     /* -0.09 */
+       OUT_RING(chan, 0);              /*  0.00 */
+
+       BEGIN_RING(chan, celsius, NV10TCL_NOP, 1);
+       OUT_RING(chan, 0);
+
+       BEGIN_RING(chan, celsius, NV10TCL_FOG_MODE, 2);
+       OUT_RING(chan, 0x802);
+       OUT_RING(chan, 2);
+       /* for some reason VIEW_MATRIX_ENABLE need to be 6 instead of 4 when
+        * using texturing, except when using the texture matrix
+        */
+       BEGIN_RING(chan, celsius, NV10TCL_VIEW_MATRIX_ENABLE, 1);
+       OUT_RING(chan, 6);
+       BEGIN_RING(chan, celsius, NV10TCL_COLOR_MASK, 1);
+       OUT_RING(chan, 0x01010101);
+
+       /* Set vertex component */
+       BEGIN_RING(chan, celsius, NV10TCL_VERTEX_COL_4F_R, 4);
+       OUT_RINGf(chan, 1.0);
+       OUT_RINGf(chan, 0.0);
+       OUT_RINGf(chan, 0.0);
+       OUT_RINGf(chan, 1.0);
+       BEGIN_RING(chan, celsius, NV10TCL_VERTEX_COL2_3F_R, 3);
+       OUT_RING(chan, 0);
+       OUT_RING(chan, 0);
+       OUT_RING(chan, 0);
+       BEGIN_RING(chan, celsius, NV10TCL_VERTEX_NOR_3F_X, 3);
+       OUT_RING(chan, 0);
+       OUT_RING(chan, 0);
+       OUT_RINGf(chan, 1.0);
+       BEGIN_RING(chan, celsius, NV10TCL_VERTEX_TX0_4F_S, 4);
+       OUT_RINGf(chan, 0.0);
+       OUT_RINGf(chan, 0.0);
+       OUT_RINGf(chan, 0.0);
+       OUT_RINGf(chan, 1.0);
+       BEGIN_RING(chan, celsius, NV10TCL_VERTEX_TX1_4F_S, 4);
+       OUT_RINGf(chan, 0.0);
+       OUT_RINGf(chan, 0.0);
+       OUT_RINGf(chan, 0.0);
+       OUT_RINGf(chan, 1.0);
+       BEGIN_RING(chan, celsius, NV10TCL_VERTEX_FOG_1F, 1);
+       OUT_RINGf(chan, 0.0);
+       BEGIN_RING(chan, celsius, NV10TCL_EDGEFLAG_ENABLE, 1);
+       OUT_RING(chan, 1);
+
+       BEGIN_RING(chan, celsius, NV10TCL_DEPTH_RANGE_NEAR, 2);
+       OUT_RING(chan, 0.0);
+       OUT_RINGf(chan, 16777216.0);
+
+       FIRE_RING(chan);
+}
+
+GLboolean
+nv10_screen_init(struct nouveau_screen *screen)
+{
+       unsigned chipset = screen->device->chipset;
+       unsigned celsius_class;
+       int ret;
+
+       screen->driver = &nv10_driver;
+
+       /* 2D engine. */
+       ret = nv04_surface_init(screen);
+       if (!ret)
+               return GL_FALSE;
+
+       /* 3D engine. */
+       if (chipset >= 0x17)
+               celsius_class = NV17TCL;
+       else if (chipset >= 0x11)
+               celsius_class = NV11TCL;
+       else
+               celsius_class = NV10TCL;
+
+       ret = nouveau_grobj_alloc(screen->chan, 0xbeef0001, celsius_class,
+                                 &screen->eng3d);
+       if (ret)
+               return GL_FALSE;
+
+       nv10_hwctx_init(screen);
+
+       return GL_TRUE;
+}
+
+static void
+nv10_screen_destroy(struct nouveau_screen *screen)
+{
+       if (screen->eng3d)
+               nouveau_grobj_free(&screen->eng3d);
+
+       nv04_surface_takedown(screen);
+}
+
+static const struct nouveau_driver nv10_driver = {
+       .screen_destroy = nv10_screen_destroy,
+       .context_create = nv10_context_create,
+       .context_destroy = nv10_context_destroy,
+       .surface_copy = nv04_surface_copy,
+       .surface_fill = nv04_surface_fill,
+       .emit = (nouveau_state_func[]) {
+               nv10_emit_alpha_func,
+               nv10_emit_blend_color,
+               nv10_emit_blend_equation,
+               nv10_emit_blend_func,
+               nv10_emit_clip_plane,
+               nv10_emit_clip_plane,
+               nv10_emit_clip_plane,
+               nv10_emit_clip_plane,
+               nv10_emit_clip_plane,
+               nv10_emit_clip_plane,
+               nv10_emit_color_mask,
+               nv10_emit_color_material,
+               nv10_emit_cull_face,
+               nv10_emit_front_face,
+               nv10_emit_depth,
+               nv10_emit_dither,
+               nv10_emit_frag,
+               nv10_emit_framebuffer,
+               nv10_emit_fog,
+               nv10_emit_index_mask,
+               nv10_emit_light_enable,
+               nv10_emit_light_model,
+               nv10_emit_light_source,
+               nv10_emit_light_source,
+               nv10_emit_light_source,
+               nv10_emit_light_source,
+               nv10_emit_light_source,
+               nv10_emit_light_source,
+               nv10_emit_light_source,
+               nv10_emit_light_source,
+               nv10_emit_line_stipple,
+               nv10_emit_line_mode,
+               nv10_emit_logic_opcode,
+               nv10_emit_material_ambient,
+               nouveau_emit_nothing,
+               nv10_emit_material_diffuse,
+               nouveau_emit_nothing,
+               nv10_emit_material_specular,
+               nouveau_emit_nothing,
+               nv10_emit_material_shininess,
+               nouveau_emit_nothing,
+               nv10_emit_modelview,
+               nv10_emit_point_mode,
+               nv10_emit_point_parameter,
+               nv10_emit_polygon_mode,
+               nv10_emit_polygon_offset,
+               nv10_emit_polygon_stipple,
+               nv10_emit_projection,
+               nv10_emit_render_mode,
+               nv10_emit_scissor,
+               nv10_emit_shade_model,
+               nv10_emit_stencil_func,
+               nv10_emit_stencil_mask,
+               nv10_emit_stencil_op,
+               nv10_emit_tex_env,
+               nv10_emit_tex_env,
+               nouveau_emit_nothing,
+               nouveau_emit_nothing,
+               nv10_emit_tex_gen,
+               nv10_emit_tex_gen,
+               nouveau_emit_nothing,
+               nouveau_emit_nothing,
+               nv10_emit_tex_obj,
+               nv10_emit_tex_obj,
+               nouveau_emit_nothing,
+               nouveau_emit_nothing,
+               nv10_emit_viewport
+       },
+       .num_emit = NUM_NOUVEAU_STATE,
+};
diff --git a/src/mesa/drivers/dri/nouveau/nv10_state_fb.c b/src/mesa/drivers/dri/nouveau/nv10_state_fb.c
new file mode 100644 (file)
index 0000000..05c36b4
--- /dev/null
@@ -0,0 +1,190 @@
+/*
+ * Copyright (C) 2009 Francisco Jerez.
+ * 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.
+ *
+ */
+
+#include "nouveau_driver.h"
+#include "nouveau_context.h"
+#include "nouveau_fbo.h"
+#include "nouveau_class.h"
+#include "nouveau_util.h"
+#include "nv10_driver.h"
+
+static inline unsigned
+get_rt_format(gl_format format)
+{
+       switch (format) {
+       case MESA_FORMAT_XRGB8888:
+               return 0x05;
+       case MESA_FORMAT_ARGB8888:
+               return 0x08;
+       case MESA_FORMAT_RGB565:
+               return 0x03;
+       case MESA_FORMAT_Z16:
+               return 0x10;
+       case MESA_FORMAT_Z24_S8:
+               return 0x0;
+       default:
+               assert(0);
+       }
+}
+
+static void
+setup_lma_buffer(GLcontext *ctx)
+{
+       struct nouveau_channel *chan = context_chan(ctx);
+       struct nouveau_grobj *celsius = context_eng3d(ctx);
+       struct nouveau_bo_context *bctx = context_bctx(ctx, LMA_DEPTH);
+       struct gl_framebuffer *fb = ctx->DrawBuffer;
+       struct nouveau_framebuffer *nfb = to_nouveau_framebuffer(fb);
+       unsigned pitch = align(fb->Width, 128),
+               height = align(fb->Height, 2),
+               size = pitch * height;
+
+       if (!nfb->lma_bo || nfb->lma_bo->size != size) {
+               nouveau_bo_ref(NULL, &nfb->lma_bo);
+               nouveau_bo_new(context_dev(ctx), NOUVEAU_BO_VRAM, 0, size,
+                              &nfb->lma_bo);
+       }
+
+       nouveau_bo_markl(bctx, celsius, NV17TCL_LMA_DEPTH_BUFFER_OFFSET,
+                        nfb->lma_bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR);
+
+       BEGIN_RING(chan, celsius, NV17TCL_LMA_DEPTH_WINDOW_X, 4);
+       OUT_RINGf(chan, - 1792);
+       OUT_RINGf(chan, - 2304 + fb->Height);
+       OUT_RINGf(chan, fb->_DepthMaxF / 2);
+       OUT_RINGf(chan, 0);
+
+       BEGIN_RING(chan, celsius, NV17TCL_LMA_DEPTH_BUFFER_PITCH, 1);
+       OUT_RING(chan, pitch);
+
+       BEGIN_RING(chan, celsius, NV17TCL_LMA_DEPTH_ENABLE, 1);
+       OUT_RING(chan, 1);
+}
+
+void
+nv10_emit_framebuffer(GLcontext *ctx, int emit)
+{
+       struct nouveau_channel *chan = context_chan(ctx);
+       struct nouveau_grobj *celsius = context_eng3d(ctx);
+       struct nouveau_bo_context *bctx = context_bctx(ctx, FRAMEBUFFER);
+       struct gl_framebuffer *fb = ctx->DrawBuffer;
+       struct nouveau_surface *s;
+       unsigned rt_format = NV10TCL_RT_FORMAT_TYPE_LINEAR;
+       unsigned rt_pitch = 0, zeta_pitch = 0;
+       unsigned bo_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR;
+
+       if (fb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT)
+               return;
+
+       /* At least nv11 seems to get sad if we don't do this before
+        * swapping RTs.*/
+       if (context_chipset(ctx) < 0x17) {
+               int i;
+
+               for (i = 0; i < 6; i++) {
+                       BEGIN_RING(chan, celsius, NV10TCL_NOP, 1);
+                       OUT_RING(chan, 0);
+               }
+       }
+
+       /* Render target */
+       if (fb->_NumColorDrawBuffers) {
+               s = &to_nouveau_renderbuffer(
+                       fb->_ColorDrawBuffers[0])->surface;
+
+               rt_format |= get_rt_format(s->format);
+               zeta_pitch = rt_pitch = s->pitch;
+
+               nouveau_bo_markl(bctx, celsius, NV10TCL_COLOR_OFFSET,
+                                s->bo, 0, bo_flags);
+       }
+
+       /* depth/stencil */
+       if (fb->_DepthBuffer) {
+               s = &to_nouveau_renderbuffer(
+                       fb->_DepthBuffer->Wrapped)->surface;
+
+               rt_format |= get_rt_format(s->format);
+               zeta_pitch = s->pitch;
+
+               nouveau_bo_markl(bctx, celsius, NV10TCL_ZETA_OFFSET,
+                                s->bo, 0, bo_flags);
+
+               if (context_chipset(ctx) >= 0x17)
+                       setup_lma_buffer(ctx);
+       }
+
+       BEGIN_RING(chan, celsius, NV10TCL_RT_FORMAT, 2);
+       OUT_RING(chan, rt_format);
+       OUT_RING(chan, zeta_pitch << 16 | rt_pitch);
+
+       context_dirty(ctx, VIEWPORT);
+       context_dirty(ctx, SCISSOR);
+}
+
+void
+nv10_emit_render_mode(GLcontext *ctx, int emit)
+{
+}
+
+void
+nv10_emit_scissor(GLcontext *ctx, int emit)
+{
+       struct nouveau_channel *chan = context_chan(ctx);
+       struct nouveau_grobj *celsius = context_eng3d(ctx);
+       int x, y, w, h;
+
+       get_scissors(ctx->DrawBuffer, &x, &y, &w, &h);
+
+       BEGIN_RING(chan, celsius, NV10TCL_RT_HORIZ, 2);
+       OUT_RING(chan, w << 16 | x);
+       OUT_RING(chan, h << 16 | y);
+}
+
+void
+nv10_emit_viewport(GLcontext *ctx, int emit)
+{
+       struct nouveau_channel *chan = context_chan(ctx);
+       struct nouveau_grobj *celsius = context_eng3d(ctx);
+       struct gl_framebuffer *fb = ctx->DrawBuffer;
+       float a[4] = {};
+       int i;
+
+       get_viewport_translate(ctx, a);
+       a[0] -= 2048;
+       a[1] -= 2048;
+
+       BEGIN_RING(chan, celsius, NV10TCL_VIEWPORT_TRANSLATE_X, 4);
+       for (i = 0; i < 4; i++)
+               OUT_RINGf(chan, a[i]);
+
+       BEGIN_RING(chan, celsius, NV10TCL_VIEWPORT_CLIP_HORIZ(0), 1);
+       OUT_RING(chan, (fb->Width - 1) << 16 | 0x08000800);
+       BEGIN_RING(chan, celsius, NV10TCL_VIEWPORT_CLIP_VERT(0), 1);
+       OUT_RING(chan, (fb->Height - 1) << 16 | 0x08000800);
+
+       context_dirty(ctx, PROJECTION);
+}
diff --git a/src/mesa/drivers/dri/nouveau/nv10_state_frag.c b/src/mesa/drivers/dri/nouveau/nv10_state_frag.c
new file mode 100644 (file)
index 0000000..c1df26e
--- /dev/null
@@ -0,0 +1,416 @@
+/*
+ * Copyright (C) 2009 Francisco Jerez.
+ * 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.
+ *
+ */
+
+#include "nouveau_driver.h"
+#include "nouveau_context.h"
+#include "nouveau_gldefs.h"
+#include "nouveau_class.h"
+#include "nouveau_util.h"
+#include "nv10_driver.h"
+#include "nv20_driver.h"
+
+#define RC_IN_SHIFT_A  24
+#define RC_IN_SHIFT_B  16
+#define RC_IN_SHIFT_C  8
+#define RC_IN_SHIFT_D  0
+#define RC_IN_SHIFT_E  56
+#define RC_IN_SHIFT_F  48
+#define RC_IN_SHIFT_G  40
+
+#define RC_IN_SOURCE(source)                           \
+       ((uint64_t)NV10TCL_RC_IN_RGB_D_INPUT_##source)
+#define RC_IN_USAGE(usage)                                     \
+       ((uint64_t)NV10TCL_RC_IN_RGB_D_COMPONENT_USAGE_##usage)
+#define RC_IN_MAPPING(mapping)                                 \
+       ((uint64_t)NV10TCL_RC_IN_RGB_D_MAPPING_##mapping)
+
+#define RC_OUT_BIAS    NV10TCL_RC_OUT_RGB_BIAS_BIAS_BY_NEGATIVE_ONE_HALF
+#define RC_OUT_SCALE_1 NV10TCL_RC_OUT_RGB_SCALE_NONE
+#define RC_OUT_SCALE_2 NV10TCL_RC_OUT_RGB_SCALE_SCALE_BY_TWO
+#define RC_OUT_SCALE_4 NV10TCL_RC_OUT_RGB_SCALE_SCALE_BY_FOUR
+
+/* Make the combiner do: spare0_i = A_i * B_i */
+#define RC_OUT_AB      NV10TCL_RC_OUT_RGB_AB_OUTPUT_SPARE0
+/* spare0_i = dot3(A, B) */
+#define RC_OUT_DOT_AB  (NV10TCL_RC_OUT_RGB_AB_OUTPUT_SPARE0 |  \
+                        NV10TCL_RC_OUT_RGB_AB_DOT_PRODUCT)
+/* spare0_i = A_i * B_i + C_i * D_i */
+#define RC_OUT_SUM     NV10TCL_RC_OUT_RGB_SUM_OUTPUT_SPARE0
+
+struct combiner_state {
+       GLcontext *ctx;
+       int unit;
+
+       /* GL state */
+       GLenum mode;
+       GLenum *source;
+       GLenum *operand;
+       GLuint logscale;
+
+       /* Derived HW state */
+       uint64_t in;
+       uint32_t out;
+};
+
+/* Initialize a combiner_state struct from the texture unit
+ * context. */
+#define INIT_COMBINER(chan, ctx, rc, i) do {                   \
+               struct gl_tex_env_combine_state *c =            \
+                       ctx->Texture.Unit[i]._CurrentCombine;   \
+               (rc)->ctx = ctx;                                \
+               (rc)->unit = i;                                 \
+               (rc)->mode = c->Mode##chan;                     \
+               (rc)->source = c->Source##chan;                 \
+               (rc)->operand = c->Operand##chan;               \
+               (rc)->logscale = c->ScaleShift##chan;           \
+               (rc)->in = (rc)->out = 0;                       \
+       } while (0)
+
+/* Get the RC input source for the specified EXT_texture_env_combine
+ * argument. */
+static uint32_t
+get_input_source(struct combiner_state *rc, int arg)
+{
+       switch (rc->source[arg]) {
+       case GL_TEXTURE:
+               return RC_IN_SOURCE(TEXTURE0) + rc->unit;
+
+       case GL_TEXTURE0:
+               return RC_IN_SOURCE(TEXTURE0);
+
+       case GL_TEXTURE1:
+               return RC_IN_SOURCE(TEXTURE1);
+
+       case GL_TEXTURE2:
+               return RC_IN_SOURCE(TEXTURE2);
+
+       case GL_TEXTURE3:
+               return RC_IN_SOURCE(TEXTURE3);
+
+       case GL_CONSTANT:
+               return context_chipset(rc->ctx) >= 0x20 ?
+                       RC_IN_SOURCE(CONSTANT_COLOR0) :
+                       RC_IN_SOURCE(CONSTANT_COLOR0) + rc->unit;
+
+       case GL_PRIMARY_COLOR:
+               return RC_IN_SOURCE(PRIMARY_COLOR);
+
+       case GL_PREVIOUS:
+               return rc->unit ? RC_IN_SOURCE(SPARE0)
+                       : RC_IN_SOURCE(PRIMARY_COLOR);
+
+       default:
+               assert(0);
+       }
+}
+
+/* Get the RC input mapping for the specified argument, possibly
+ * inverted or biased. */
+#define INVERT 0x1
+#define HALF_BIAS 0x2
+
+static uint32_t
+get_input_mapping(struct combiner_state *rc, int arg, int flags)
+{
+       int map = 0;
+
+       switch (rc->operand[arg]) {
+       case GL_SRC_COLOR:
+       case GL_ONE_MINUS_SRC_COLOR:
+               map |= RC_IN_USAGE(RGB);
+               break;
+
+       case GL_SRC_ALPHA:
+       case GL_ONE_MINUS_SRC_ALPHA:
+               map |= RC_IN_USAGE(ALPHA);
+               break;
+       }
+
+       switch (rc->operand[arg]) {
+       case GL_SRC_COLOR:
+       case GL_SRC_ALPHA:
+               map |= (flags & INVERT ? RC_IN_MAPPING(UNSIGNED_INVERT) :
+                       flags & HALF_BIAS ? RC_IN_MAPPING(HALF_BIAS_NORMAL) :
+                       RC_IN_MAPPING(UNSIGNED_IDENTITY));
+               break;
+
+       case GL_ONE_MINUS_SRC_COLOR:
+       case GL_ONE_MINUS_SRC_ALPHA:
+               map |= (flags & INVERT ? RC_IN_MAPPING(UNSIGNED_IDENTITY) :
+                       flags & HALF_BIAS ? RC_IN_MAPPING(HALF_BIAS_NEGATE) :
+                       RC_IN_MAPPING(UNSIGNED_INVERT));
+               break;
+       }
+
+       return map;
+}
+
+/* Bind the RC input variable <var> to the EXT_texture_env_combine
+ * argument <arg>, possibly inverted or biased. */
+#define INPUT_ARG(rc, var, arg, flags)                                 \
+       (rc)->in |= (get_input_mapping(rc, arg, flags) |                \
+                    get_input_source(rc, arg)) << RC_IN_SHIFT_##var
+
+/* Bind the RC input variable <var> to the RC source <src>. */
+#define INPUT_SRC(rc, var, src, chan)                                  \
+       (rc)->in |= (RC_IN_SOURCE(src) |                                \
+                    RC_IN_USAGE(chan)) << RC_IN_SHIFT_##var
+
+/* Bind the RC input variable <var> to a constant +/-1 */
+#define INPUT_ONE(rc, var, flags)                                      \
+       (rc)->in |= (RC_IN_SOURCE(ZERO) |                               \
+                    (flags & INVERT ? RC_IN_MAPPING(EXPAND_NORMAL) :   \
+                     RC_IN_MAPPING(UNSIGNED_INVERT))) << RC_IN_SHIFT_##var
+
+static void
+setup_combiner(struct combiner_state *rc)
+{
+       switch (rc->mode) {
+       case GL_REPLACE:
+               INPUT_ARG(rc, A, 0, 0);
+               INPUT_ONE(rc, B, 0);
+
+               rc->out = RC_OUT_AB;
+               break;
+
+       case GL_MODULATE:
+               INPUT_ARG(rc, A, 0, 0);
+               INPUT_ARG(rc, B, 1, 0);
+
+               rc->out = RC_OUT_AB;
+               break;
+
+       case GL_ADD:
+               INPUT_ARG(rc, A, 0, 0);
+               INPUT_ONE(rc, B, 0);
+               INPUT_ARG(rc, C, 1, 0);
+               INPUT_ONE(rc, D, 0);
+
+               rc->out = RC_OUT_SUM;
+               break;
+
+       case GL_ADD_SIGNED:
+               INPUT_ARG(rc, A, 0, 0);
+               INPUT_ONE(rc, B, 0);
+               INPUT_ARG(rc, C, 1, 0);
+               INPUT_ONE(rc, D, 0);
+
+               rc->out = RC_OUT_SUM | RC_OUT_BIAS;
+               break;
+
+       case GL_INTERPOLATE:
+               INPUT_ARG(rc, A, 0, 0);
+               INPUT_ARG(rc, B, 2, 0);
+               INPUT_ARG(rc, C, 1, 0);
+               INPUT_ARG(rc, D, 2, INVERT);
+
+               rc->out = RC_OUT_SUM;
+               break;
+
+       case GL_SUBTRACT:
+               INPUT_ARG(rc, A, 0, 0);
+               INPUT_ONE(rc, B, 0);
+               INPUT_ARG(rc, C, 1, 0);
+               INPUT_ONE(rc, D, INVERT);
+
+               rc->out = RC_OUT_SUM;
+               break;
+
+       case GL_DOT3_RGB:
+       case GL_DOT3_RGBA:
+               INPUT_ARG(rc, A, 0, HALF_BIAS);
+               INPUT_ARG(rc, B, 1, HALF_BIAS);
+
+               rc->out = RC_OUT_DOT_AB | RC_OUT_SCALE_4;
+
+               assert(!rc->logscale);
+               break;
+
+       default:
+               assert(0);
+       }
+
+       switch (rc->logscale) {
+       case 0:
+               rc->out |= RC_OUT_SCALE_1;
+               break;
+       case 1:
+               rc->out |= RC_OUT_SCALE_2;
+               break;
+       case 2:
+               rc->out |= RC_OUT_SCALE_4;
+               break;
+       default:
+               assert(0);
+       }
+}
+
+/* Write the register combiner state out to the hardware. */
+static void
+nv10_load_combiner(GLcontext *ctx, int i, struct combiner_state *rc_a,
+                  struct combiner_state *rc_c, uint32_t rc_const)
+{
+       struct nouveau_channel *chan = context_chan(ctx);
+       struct nouveau_grobj *celsius = context_eng3d(ctx);
+
+       /* Enable the combiners we're going to need. */
+       if (i == 1) {
+               if (rc_c->out || rc_a->out)
+                       rc_c->out |= 0x5 << 27;
+               else
+                       rc_c->out |= 0x3 << 27;
+       }
+
+       BEGIN_RING(chan, celsius, NV10TCL_RC_IN_ALPHA(i), 1);
+       OUT_RING(chan, rc_a->in);
+       BEGIN_RING(chan, celsius, NV10TCL_RC_IN_RGB(i), 1);
+       OUT_RING(chan, rc_c->in);
+       BEGIN_RING(chan, celsius, NV10TCL_RC_COLOR(i), 1);
+       OUT_RING(chan, rc_const);
+       BEGIN_RING(chan, celsius, NV10TCL_RC_OUT_ALPHA(i), 1);
+       OUT_RING(chan, rc_a->out);
+       BEGIN_RING(chan, celsius, NV10TCL_RC_OUT_RGB(i), 1);
+       OUT_RING(chan, rc_c->out);
+}
+
+static void
+nv10_load_final(GLcontext *ctx, struct combiner_state *rc, int n)
+{
+       struct nouveau_channel *chan = context_chan(ctx);
+       struct nouveau_grobj *celsius = context_eng3d(ctx);
+
+       BEGIN_RING(chan, celsius, NV10TCL_RC_FINAL0, 2);
+       OUT_RING(chan, rc->in);
+       OUT_RING(chan, rc->in >> 32);
+}
+
+static void
+nv20_load_combiner(GLcontext *ctx, int i, struct combiner_state *rc_a,
+                  struct combiner_state *rc_c, uint32_t rc_const)
+{
+       struct nouveau_channel *chan = context_chan(ctx);
+       struct nouveau_grobj *kelvin = context_eng3d(ctx);
+
+       BEGIN_RING(chan, kelvin, NV20TCL_RC_IN_ALPHA(i), 1);
+       OUT_RING(chan, rc_a->in);
+       BEGIN_RING(chan, kelvin, NV20TCL_RC_OUT_ALPHA(i), 1);
+       OUT_RING(chan, rc_a->out);
+       BEGIN_RING(chan, kelvin, NV20TCL_RC_IN_RGB(i), 1);
+       OUT_RING(chan, rc_c->in);
+       BEGIN_RING(chan, kelvin, NV20TCL_RC_OUT_RGB(i), 1);
+       OUT_RING(chan, rc_c->out);
+       BEGIN_RING(chan, kelvin, NV20TCL_RC_CONSTANT_COLOR0(i), 1);
+       OUT_RING(chan, rc_const);
+}
+
+static void
+nv20_load_final(GLcontext *ctx, struct combiner_state *rc, int n)
+{
+       struct nouveau_channel *chan = context_chan(ctx);
+       struct nouveau_grobj *kelvin = context_eng3d(ctx);
+
+       BEGIN_RING(chan, kelvin, NV20TCL_RC_FINAL0, 2);
+       OUT_RING(chan, rc->in);
+       OUT_RING(chan, rc->in >> 32);
+
+       BEGIN_RING(chan, kelvin, NV20TCL_RC_ENABLE, 1);
+       OUT_RING(chan, n);
+}
+
+void
+nv10_emit_tex_env(GLcontext *ctx, int emit)
+{
+       const int i = emit - NOUVEAU_STATE_TEX_ENV0;
+       struct combiner_state rc_a, rc_c;
+       uint32_t rc_const;
+
+       /* Compute the new combiner state. */
+       if (ctx->Texture.Unit[i]._ReallyEnabled) {
+               INIT_COMBINER(RGB, ctx, &rc_c, i);
+
+               if (rc_c.mode == GL_DOT3_RGBA)
+                       rc_a = rc_c;
+               else
+                       INIT_COMBINER(A, ctx, &rc_a, i);
+
+               setup_combiner(&rc_c);
+               setup_combiner(&rc_a);
+
+               rc_const = pack_rgba_f(MESA_FORMAT_ARGB8888,
+                                      ctx->Texture.Unit[i].EnvColor);
+
+       } else {
+               rc_a.in = rc_a.out = rc_c.in = rc_c.out = rc_const = 0;
+       }
+
+       if (context_chipset(ctx) >= 0x20)
+               nv20_load_combiner(ctx, i, &rc_a, &rc_c, rc_const);
+       else
+               nv10_load_combiner(ctx, i, &rc_a, &rc_c, rc_const);
+
+       context_dirty(ctx, FRAG);
+}
+
+void
+nv10_emit_frag(GLcontext *ctx, int emit)
+{
+       struct combiner_state rc = {};
+       int n = log2i(ctx->Texture._EnabledUnits) + 1;
+
+       /*
+        * The final fragment value equation is something like:
+        *      x_i = A_i * B_i + (1 - A_i) * C_i + D_i
+        *      x_alpha = G_alpha
+        * where D_i = E_i * F_i, i one of {red, green, blue}.
+        */
+       if (ctx->Fog.ColorSumEnabled || ctx->Light.Enabled) {
+               INPUT_SRC(&rc, D, E_TIMES_F, RGB);
+               INPUT_SRC(&rc, F, SECONDARY_COLOR, RGB);
+       }
+
+       if (ctx->Fog.Enabled) {
+               INPUT_SRC(&rc, A, FOG, ALPHA);
+               INPUT_SRC(&rc, C, FOG, RGB);
+               INPUT_SRC(&rc, E, FOG, ALPHA);
+       } else {
+               INPUT_ONE(&rc, A, 0);
+               INPUT_ONE(&rc, C, 0);
+               INPUT_ONE(&rc, E, 0);
+       }
+
+       if (ctx->Texture._EnabledUnits) {
+               INPUT_SRC(&rc, B, SPARE0, RGB);
+               INPUT_SRC(&rc, G, SPARE0, ALPHA);
+       } else {
+               INPUT_SRC(&rc, B, PRIMARY_COLOR, RGB);
+               INPUT_SRC(&rc, G, PRIMARY_COLOR, ALPHA);
+       }
+
+       if (context_chipset(ctx) >= 0x20)
+               nv20_load_final(ctx, &rc, n);
+       else
+               nv10_load_final(ctx, &rc, n);
+}
diff --git a/src/mesa/drivers/dri/nouveau/nv10_state_polygon.c b/src/mesa/drivers/dri/nouveau/nv10_state_polygon.c
new file mode 100644 (file)
index 0000000..deddca1
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2009 Francisco Jerez.
+ * 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.
+ *
+ */
+
+#include "nouveau_driver.h"
+#include "nouveau_context.h"
+#include "nouveau_gldefs.h"
+#include "nouveau_class.h"
+#include "nv10_driver.h"
+
+void
+nv10_emit_cull_face(GLcontext *ctx, int emit)
+{
+       struct nouveau_channel *chan = context_chan(ctx);
+       struct nouveau_grobj *celsius = context_eng3d(ctx);
+       GLenum mode = ctx->Polygon.CullFaceMode;
+
+       BEGIN_RING(chan, celsius, NV10TCL_CULL_FACE_ENABLE, 1);
+       OUT_RING(chan, ctx->Polygon.CullFlag ? 1 : 0);
+
+       BEGIN_RING(chan, celsius, NV10TCL_CULL_FACE, 1);
+       OUT_RING(chan, (mode == GL_FRONT ? NV10TCL_CULL_FACE_FRONT :
+                       mode == GL_BACK ? NV10TCL_CULL_FACE_BACK :
+                       NV10TCL_CULL_FACE_FRONT_AND_BACK));
+}
+
+void
+nv10_emit_front_face(GLcontext *ctx, int emit)
+{
+       struct nouveau_channel *chan = context_chan(ctx);
+       struct nouveau_grobj *celsius = context_eng3d(ctx);
+
+       BEGIN_RING(chan, celsius, NV10TCL_FRONT_FACE, 1);
+       OUT_RING(chan, ctx->Polygon.FrontFace == GL_CW ?
+                NV10TCL_FRONT_FACE_CW : NV10TCL_FRONT_FACE_CCW);
+}
+
+void
+nv10_emit_line_mode(GLcontext *ctx, int emit)
+{
+       struct nouveau_channel *chan = context_chan(ctx);
+       struct nouveau_grobj *celsius = context_eng3d(ctx);
+       GLboolean smooth = ctx->Line.SmoothFlag &&
+               ctx->Hint.LineSmooth == GL_NICEST;
+
+       BEGIN_RING(chan, celsius, NV10TCL_LINE_WIDTH, 1);
+       OUT_RING(chan, MAX2(smooth ? 0 : 1,
+                           ctx->Line.Width) * 8);
+       BEGIN_RING(chan, celsius, NV10TCL_LINE_SMOOTH_ENABLE, 1);
+       OUT_RING(chan, smooth ? 1 : 0);
+}
+
+void
+nv10_emit_line_stipple(GLcontext *ctx, int emit)
+{
+}
+
+void
+nv10_emit_point_mode(GLcontext *ctx, int emit)
+{
+       struct nouveau_channel *chan = context_chan(ctx);
+       struct nouveau_grobj *celsius = context_eng3d(ctx);
+
+       BEGIN_RING(chan, celsius, NV10TCL_POINT_SIZE, 1);
+       OUT_RING(chan, (uint32_t)(ctx->Point.Size * 8));
+
+       BEGIN_RING(chan, celsius, NV10TCL_POINT_SMOOTH_ENABLE, 1);
+       OUT_RING(chan, ctx->Point.SmoothFlag ? 1 : 0);
+}
+
+void
+nv10_emit_polygon_mode(GLcontext *ctx, int emit)
+{
+       struct nouveau_channel *chan = context_chan(ctx);
+       struct nouveau_grobj *celsius = context_eng3d(ctx);
+
+       BEGIN_RING(chan, celsius, NV10TCL_POLYGON_MODE_FRONT, 2);
+       OUT_RING(chan, nvgl_polygon_mode(ctx->Polygon.FrontMode));
+       OUT_RING(chan, nvgl_polygon_mode(ctx->Polygon.BackMode));
+
+       BEGIN_RING(chan, celsius, NV10TCL_POLYGON_SMOOTH_ENABLE, 1);
+       OUT_RING(chan, ctx->Polygon.SmoothFlag ? 1 : 0);
+}
+
+void
+nv10_emit_polygon_offset(GLcontext *ctx, int emit)
+{
+       struct nouveau_channel *chan = context_chan(ctx);
+       struct nouveau_grobj *celsius = context_eng3d(ctx);
+
+       BEGIN_RING(chan, celsius, NV10TCL_POLYGON_OFFSET_POINT_ENABLE, 3);
+       OUT_RING(chan, ctx->Polygon.OffsetPoint ? 1 : 0);
+       OUT_RING(chan, ctx->Polygon.OffsetLine ? 1 : 0);
+       OUT_RING(chan, ctx->Polygon.OffsetFill ? 1 : 0);
+
+       BEGIN_RING(chan, celsius, NV10TCL_POLYGON_OFFSET_FACTOR, 2);
+       OUT_RINGf(chan, ctx->Polygon.OffsetFactor);
+       OUT_RINGf(chan, ctx->Polygon.OffsetUnits);
+}
+
+void
+nv10_emit_polygon_stipple(GLcontext *ctx, int emit)
+{
+}
diff --git a/src/mesa/drivers/dri/nouveau/nv10_state_raster.c b/src/mesa/drivers/dri/nouveau/nv10_state_raster.c
new file mode 100644 (file)
index 0000000..68882ef
--- /dev/null
@@ -0,0 +1,186 @@
+/*
+ * Copyright (C) 2009 Francisco Jerez.
+ * 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.
+ *
+ */
+
+#include "nouveau_driver.h"
+#include "nouveau_context.h"
+#include "nouveau_gldefs.h"
+#include "nouveau_class.h"
+#include "nv10_driver.h"
+
+void
+nv10_emit_alpha_func(GLcontext *ctx, int emit)
+{
+       struct nouveau_channel *chan = context_chan(ctx);
+       struct nouveau_grobj *celsius = context_eng3d(ctx);
+
+       BEGIN_RING(chan, celsius, NV10TCL_ALPHA_FUNC_ENABLE, 1);
+       OUT_RING(chan, ctx->Color.AlphaEnabled ? 1 : 0);
+
+       BEGIN_RING(chan, celsius, NV10TCL_ALPHA_FUNC_FUNC, 2);
+       OUT_RING(chan, nvgl_comparison_op(ctx->Color.AlphaFunc));
+       OUT_RING(chan, FLOAT_TO_UBYTE(ctx->Color.AlphaRef));
+}
+
+void
+nv10_emit_blend_color(GLcontext *ctx, int emit)
+{
+       struct nouveau_channel *chan = context_chan(ctx);
+       struct nouveau_grobj *celsius = context_eng3d(ctx);
+
+       BEGIN_RING(chan, celsius, NV10TCL_BLEND_COLOR, 1);
+       OUT_RING(chan, FLOAT_TO_UBYTE(ctx->Color.BlendColor[3]) << 24 |
+                FLOAT_TO_UBYTE(ctx->Color.BlendColor[0]) << 16 |
+                FLOAT_TO_UBYTE(ctx->Color.BlendColor[1]) << 8 |
+                FLOAT_TO_UBYTE(ctx->Color.BlendColor[2]) << 0);
+}
+
+void
+nv10_emit_blend_equation(GLcontext *ctx, int emit)
+{
+       struct nouveau_channel *chan = context_chan(ctx);
+       struct nouveau_grobj *celsius = context_eng3d(ctx);
+
+       BEGIN_RING(chan, celsius, NV10TCL_BLEND_FUNC_ENABLE, 1);
+       OUT_RING(chan, ctx->Color.BlendEnabled ? 1 : 0);
+
+       BEGIN_RING(chan, celsius, NV10TCL_BLEND_EQUATION, 1);
+       OUT_RING(chan, nvgl_blend_eqn(ctx->Color.BlendEquationRGB));
+}
+
+void
+nv10_emit_blend_func(GLcontext *ctx, int emit)
+{
+       struct nouveau_channel *chan = context_chan(ctx);
+       struct nouveau_grobj *celsius = context_eng3d(ctx);
+
+       BEGIN_RING(chan, celsius, NV10TCL_BLEND_FUNC_SRC, 2);
+       OUT_RING(chan, nvgl_blend_func(ctx->Color.BlendSrcRGB));
+       OUT_RING(chan, nvgl_blend_func(ctx->Color.BlendDstRGB));
+}
+
+void
+nv10_emit_color_mask(GLcontext *ctx, int emit)
+{
+       struct nouveau_channel *chan = context_chan(ctx);
+       struct nouveau_grobj *celsius = context_eng3d(ctx);
+
+       BEGIN_RING(chan, celsius, NV10TCL_COLOR_MASK, 1);
+       OUT_RING(chan, ((ctx->Color.ColorMask[0][3] ? 1 << 24 : 0) |
+                       (ctx->Color.ColorMask[0][0] ? 1 << 16 : 0) |
+                       (ctx->Color.ColorMask[0][1] ? 1 << 8 : 0) |
+                       (ctx->Color.ColorMask[0][2] ? 1 << 0 : 0)));
+}
+
+void
+nv10_emit_depth(GLcontext *ctx, int emit)
+{
+       struct nouveau_channel *chan = context_chan(ctx);
+       struct nouveau_grobj *celsius = context_eng3d(ctx);
+
+       BEGIN_RING(chan, celsius, NV10TCL_DEPTH_TEST_ENABLE, 1);
+       OUT_RING(chan, ctx->Depth.Test ? 1 : 0);
+       BEGIN_RING(chan, celsius, NV10TCL_DEPTH_WRITE_ENABLE, 1);
+       OUT_RING(chan, ctx->Depth.Mask ? 1 : 0);
+       BEGIN_RING(chan, celsius, NV10TCL_DEPTH_FUNC, 1);
+       OUT_RING(chan, nvgl_comparison_op(ctx->Depth.Func));
+}
+
+void
+nv10_emit_dither(GLcontext *ctx, int emit)
+{
+       struct nouveau_channel *chan = context_chan(ctx);
+       struct nouveau_grobj *celsius = context_eng3d(ctx);
+
+       BEGIN_RING(chan, celsius, NV10TCL_DITHER_ENABLE, 1);
+       OUT_RING(chan, ctx->Color.DitherFlag ? 1 : 0);
+}
+
+void
+nv10_emit_index_mask(GLcontext *ctx, int emit)
+{
+}
+
+void
+nv10_emit_logic_opcode(GLcontext *ctx, int emit)
+{
+       struct nouveau_channel *chan = context_chan(ctx);
+       struct nouveau_grobj *celsius = context_eng3d(ctx);
+
+       assert(!ctx->Color.ColorLogicOpEnabled
+              || context_chipset(ctx) >= 0x11);
+
+       BEGIN_RING(chan, celsius, NV11TCL_COLOR_LOGIC_OP_ENABLE, 2);
+       OUT_RING(chan, ctx->Color.ColorLogicOpEnabled ? 1 : 0);
+       OUT_RING(chan, nvgl_logicop_func(ctx->Color.LogicOp));
+}
+
+void
+nv10_emit_shade_model(GLcontext *ctx, int emit)
+{
+       struct nouveau_channel *chan = context_chan(ctx);
+       struct nouveau_grobj *celsius = context_eng3d(ctx);
+
+       BEGIN_RING(chan, celsius, NV10TCL_SHADE_MODEL, 1);
+       OUT_RING(chan, ctx->Light.ShadeModel == GL_SMOOTH ?
+                NV10TCL_SHADE_MODEL_SMOOTH : NV10TCL_SHADE_MODEL_FLAT);
+}
+
+void
+nv10_emit_stencil_func(GLcontext *ctx, int emit)
+{
+       struct nouveau_channel *chan = context_chan(ctx);
+       struct nouveau_grobj *celsius = context_eng3d(ctx);
+
+       BEGIN_RING(chan, celsius, NV10TCL_STENCIL_ENABLE, 1);
+       OUT_RING(chan, ctx->Stencil.Enabled ? 1 : 0);
+
+       BEGIN_RING(chan, celsius, NV10TCL_STENCIL_FUNC_FUNC, 3);
+       OUT_RING(chan, nvgl_comparison_op(ctx->Stencil.Function[0]));
+       OUT_RING(chan, ctx->Stencil.Ref[0]);
+       OUT_RING(chan, ctx->Stencil.ValueMask[0]);
+}
+
+void
+nv10_emit_stencil_mask(GLcontext *ctx, int emit)
+{
+       struct nouveau_channel *chan = context_chan(ctx);
+       struct nouveau_grobj *celsius = context_eng3d(ctx);
+
+       BEGIN_RING(chan, celsius, NV10TCL_STENCIL_MASK, 1);
+       OUT_RING(chan, ctx->Stencil.WriteMask[0]);
+}
+
+void
+nv10_emit_stencil_op(GLcontext *ctx, int emit)
+{
+       struct nouveau_channel *chan = context_chan(ctx);
+       struct nouveau_grobj *celsius = context_eng3d(ctx);
+
+       BEGIN_RING(chan, celsius, NV10TCL_STENCIL_OP_FAIL, 3);
+       OUT_RING(chan, nvgl_stencil_op(ctx->Stencil.FailFunc[0]));
+       OUT_RING(chan, nvgl_stencil_op(ctx->Stencil.ZFailFunc[0]));
+       OUT_RING(chan, nvgl_stencil_op(ctx->Stencil.ZPassFunc[0]));
+}
diff --git a/src/mesa/drivers/dri/nouveau/nv10_state_tex.c b/src/mesa/drivers/dri/nouveau/nv10_state_tex.c
new file mode 100644 (file)
index 0000000..e5d4f3d
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2009 Francisco Jerez.
+ * 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.
+ *
+ */
+
+#include "nouveau_driver.h"
+#include "nouveau_context.h"
+#include "nouveau_gldefs.h"
+#include "nouveau_texture.h"
+#include "nouveau_class.h"
+#include "nouveau_util.h"
+#include "nv10_driver.h"
+
+void
+nv10_emit_tex_gen(GLcontext *ctx, int emit)
+{
+}
+
+static uint32_t
+get_tex_format(struct gl_texture_image *ti)
+{
+       switch (ti->TexFormat) {
+       case MESA_FORMAT_ARGB8888:
+               return NV10TCL_TX_FORMAT_FORMAT_A8R8G8B8;
+
+       case MESA_FORMAT_ARGB1555:
+               return NV10TCL_TX_FORMAT_FORMAT_A1R5G5B5;
+
+       case MESA_FORMAT_ARGB4444:
+               return NV10TCL_TX_FORMAT_FORMAT_A4R4G4B4;
+
+       case MESA_FORMAT_RGB565:
+               return NV10TCL_TX_FORMAT_FORMAT_R5G6B5;
+
+       case MESA_FORMAT_A8:
+               return NV10TCL_TX_FORMAT_FORMAT_A8;
+
+       case MESA_FORMAT_L8:
+               return NV10TCL_TX_FORMAT_FORMAT_L8;
+
+       case MESA_FORMAT_CI8:
+               return NV10TCL_TX_FORMAT_FORMAT_INDEX8;
+
+       default:
+               assert(0);
+       }
+}
+
+void
+nv10_emit_tex_obj(GLcontext *ctx, int emit)
+{
+       const int i = emit - NOUVEAU_STATE_TEX_OBJ0;
+       struct nouveau_channel *chan = context_chan(ctx);
+       struct nouveau_grobj *celsius = context_eng3d(ctx);
+       struct nouveau_bo_context *bctx = context_bctx_i(ctx, TEXTURE, i);
+       const int bo_flags = NOUVEAU_BO_RD | NOUVEAU_BO_GART | NOUVEAU_BO_VRAM;
+       struct gl_texture_object *t;
+       struct nouveau_surface *s;
+       struct gl_texture_image *ti;
+       uint32_t tx_format, tx_filter, tx_enable;
+
+       if (!ctx->Texture.Unit[i]._ReallyEnabled) {
+               BEGIN_RING(chan, celsius, NV10TCL_TX_ENABLE(i), 1);
+               OUT_RING(chan, 0);
+               return;
+       }
+
+       t = ctx->Texture.Unit[i]._Current;
+       s = &to_nouveau_texture(t)->surfaces[t->BaseLevel];
+       ti = t->Image[0][t->BaseLevel];
+
+       nouveau_texture_validate(ctx, t);
+
+       /* Recompute the texturing registers. */
+       tx_format = nvgl_wrap_mode(t->WrapT) << 28
+               | nvgl_wrap_mode(t->WrapS) << 24
+               | ti->HeightLog2 << 20
+               | ti->WidthLog2 << 16
+               | get_tex_format(ti)
+               | 5 << 4 | 1 << 12;
+
+       tx_filter = nvgl_filter_mode(t->MagFilter) << 28
+               | nvgl_filter_mode(t->MinFilter) << 24;
+
+       tx_enable = NV10TCL_TX_ENABLE_ENABLE
+               | log2i(t->MaxAnisotropy) << 4;
+
+       if (t->MinFilter != GL_NEAREST &&
+           t->MinFilter != GL_LINEAR) {
+               int lod_min = t->MinLod;
+               int lod_max = MIN2(t->MaxLod, t->_MaxLambda);
+               int lod_bias = t->LodBias
+                       + ctx->Texture.Unit[i].LodBias;
+
+               lod_max = CLAMP(lod_max, 0, 15);
+               lod_min = CLAMP(lod_min, 0, 15);
+               lod_bias = CLAMP(lod_bias, 0, 15);
+
+               tx_format |= NV10TCL_TX_FORMAT_MIPMAP;
+               tx_filter |= lod_bias << 8;
+               tx_enable |= lod_min << 26
+                       | lod_max << 14;
+       }
+
+       /* Write it to the hardware. */
+       nouveau_bo_mark(bctx, celsius, NV10TCL_TX_FORMAT(i),
+                       s->bo, tx_format, 0,
+                       NV10TCL_TX_FORMAT_DMA0,
+                       NV10TCL_TX_FORMAT_DMA1,
+                       bo_flags | NOUVEAU_BO_OR);
+
+       nouveau_bo_markl(bctx, celsius, NV10TCL_TX_OFFSET(i),
+                        s->bo, 0, bo_flags);
+
+       BEGIN_RING(chan, celsius, NV10TCL_TX_FILTER(i), 1);
+       OUT_RING(chan, tx_filter);
+
+       BEGIN_RING(chan, celsius, NV10TCL_TX_ENABLE(i), 1);
+       OUT_RING(chan, tx_enable);
+}
+
diff --git a/src/mesa/drivers/dri/nouveau/nv10_state_tnl.c b/src/mesa/drivers/dri/nouveau/nv10_state_tnl.c
new file mode 100644 (file)
index 0000000..6db14d8
--- /dev/null
@@ -0,0 +1,514 @@
+/*
+ * Copyright (C) 2009-2010 Francisco Jerez.
+ * 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.
+ *
+ */
+
+#include "nouveau_driver.h"
+#include "nouveau_context.h"
+#include "nouveau_gldefs.h"
+#include "nouveau_util.h"
+#include "nouveau_class.h"
+#include "nv10_driver.h"
+
+void
+nv10_emit_clip_plane(GLcontext *ctx, int emit)
+{
+}
+
+static inline unsigned
+get_material_bitmask(unsigned m)
+{
+       unsigned ret = 0;
+
+       if (m & MAT_BIT_FRONT_EMISSION)
+               ret |= NV10TCL_COLOR_MATERIAL_EMISSION;
+       if (m & MAT_BIT_FRONT_AMBIENT)
+               ret |= NV10TCL_COLOR_MATERIAL_AMBIENT;
+       if (m & MAT_BIT_FRONT_DIFFUSE)
+               ret |= NV10TCL_COLOR_MATERIAL_DIFFUSE;
+       if (m & MAT_BIT_FRONT_SPECULAR)
+               ret |= NV10TCL_COLOR_MATERIAL_SPECULAR;
+
+       return ret;
+}
+
+void
+nv10_emit_color_material(GLcontext *ctx, int emit)
+{
+       struct nouveau_channel *chan = context_chan(ctx);
+       struct nouveau_grobj *celsius = context_eng3d(ctx);
+       unsigned mask = get_material_bitmask(ctx->Light.ColorMaterialBitmask);
+
+       BEGIN_RING(chan, celsius, NV10TCL_COLOR_MATERIAL, 1);
+       OUT_RING(chan, ctx->Light.ColorMaterialEnabled ? mask : 0);
+}
+
+static unsigned
+get_fog_mode(unsigned mode)
+{
+       switch (mode) {
+       case GL_LINEAR:
+               return NV10TCL_FOG_MODE_LINEAR;
+       case GL_EXP:
+               return NV10TCL_FOG_MODE_EXP;
+       case GL_EXP2:
+               return NV10TCL_FOG_MODE_EXP2;
+       default:
+               assert(0);
+       }
+}
+
+static unsigned
+get_fog_source(unsigned source)
+{
+       switch (source) {
+       case GL_FOG_COORDINATE_EXT:
+               return NV10TCL_FOG_COORD_FOG;
+       case GL_FRAGMENT_DEPTH_EXT:
+               return NV10TCL_FOG_COORD_DIST_ORTHOGONAL_ABS;
+       default:
+               assert(0);
+       }
+}
+
+void
+nv10_get_fog_coeff(GLcontext *ctx, float k[3])
+{
+       struct gl_fog_attrib *f = &ctx->Fog;
+
+       switch (f->Mode) {
+       case GL_LINEAR:
+               k[0] = 2 + f->Start / (f->End - f->Start);
+               k[1] = -1 / (f->End - f->Start);
+               break;
+
+       case GL_EXP:
+               k[0] = 1.5;
+               k[1] = -0.09 * f->Density;
+               break;
+
+       case GL_EXP2:
+               k[0] = 1.5;
+               k[1] = -0.21 * f->Density;
+               break;
+
+       default:
+               assert(0);
+       }
+
+       k[2] = 0;
+}
+
+void
+nv10_emit_fog(GLcontext *ctx, int emit)
+{
+       struct nouveau_context *nctx = to_nouveau_context(ctx);
+       struct nouveau_channel *chan = context_chan(ctx);
+       struct nouveau_grobj *celsius = context_eng3d(ctx);
+       struct gl_fog_attrib *f = &ctx->Fog;
+       unsigned source = nctx->fallback == HWTNL ?
+               f->FogCoordinateSource : GL_FOG_COORDINATE_EXT;
+       float k[3];
+
+       nv10_get_fog_coeff(ctx, k);
+
+       BEGIN_RING(chan, celsius, NV10TCL_FOG_MODE, 4);
+       OUT_RING(chan, get_fog_mode(f->Mode));
+       OUT_RING(chan, get_fog_source(source));
+       OUT_RING(chan, f->Enabled ? 1 : 0);
+       OUT_RING(chan, pack_rgba_f(MESA_FORMAT_RGBA8888_REV, f->Color));
+
+       BEGIN_RING(chan, celsius, NV10TCL_FOG_EQUATION_CONSTANT, 3);
+       OUT_RINGf(chan, k[0]);
+       OUT_RINGf(chan, k[1]);
+       OUT_RINGf(chan, k[2]);
+
+       context_dirty(ctx, FRAG);
+}
+
+static inline unsigned
+get_light_mode(struct gl_light *l)
+{
+       if (l->Enabled) {
+               if (l->_Flags & LIGHT_SPOT)
+                       return NV10TCL_ENABLED_LIGHTS_0_DIRECTIONAL;
+               else if (l->_Flags & LIGHT_POSITIONAL)
+                       return NV10TCL_ENABLED_LIGHTS_0_POSITIONAL;
+               else
+                       return NV10TCL_ENABLED_LIGHTS_0_NONPOSITIONAL;
+       } else {
+               return NV10TCL_ENABLED_LIGHTS_0_DISABLED;
+       }
+}
+
+void
+nv10_emit_light_enable(GLcontext *ctx, int emit)
+{
+       struct nouveau_context *nctx = to_nouveau_context(ctx);
+       struct nouveau_channel *chan = context_chan(ctx);
+       struct nouveau_grobj *celsius = context_eng3d(ctx);
+       uint32_t en_lights = 0;
+       int i;
+
+       if (nctx->fallback != HWTNL) {
+               BEGIN_RING(chan, celsius, NV10TCL_LIGHTING_ENABLE, 1);
+               OUT_RING(chan, 0);
+               return;
+       }
+
+       for (i = 0; i < MAX_LIGHTS; i++)
+               en_lights |= get_light_mode(&ctx->Light.Light[i]) << 2 * i;
+
+       BEGIN_RING(chan, celsius, NV10TCL_ENABLED_LIGHTS, 1);
+       OUT_RING(chan, en_lights);
+       BEGIN_RING(chan, celsius, NV10TCL_LIGHTING_ENABLE, 1);
+       OUT_RING(chan, ctx->Light.Enabled ? 1 : 0);
+       BEGIN_RING(chan, celsius, NV10TCL_NORMALIZE_ENABLE, 1);
+       OUT_RING(chan, ctx->Transform.Normalize ? 1 : 0);
+}
+
+void
+nv10_emit_light_model(GLcontext *ctx, int emit)
+{
+       struct nouveau_channel *chan = context_chan(ctx);
+       struct nouveau_grobj *celsius = context_eng3d(ctx);
+       struct gl_lightmodel *m = &ctx->Light.Model;
+
+       BEGIN_RING(chan, celsius, NV10TCL_SEPARATE_SPECULAR_ENABLE, 1);
+       OUT_RING(chan, m->ColorControl == GL_SEPARATE_SPECULAR_COLOR ? 1 : 0);
+
+       BEGIN_RING(chan, celsius, NV10TCL_LIGHT_MODEL, 1);
+       OUT_RING(chan, ((m->LocalViewer ?
+                        NV10TCL_LIGHT_MODEL_LOCAL_VIEWER : 0) |
+                       (m->ColorControl == GL_SEPARATE_SPECULAR_COLOR ?
+                        NV10TCL_LIGHT_MODEL_SEPARATE_SPECULAR : 0)));
+}
+
+static float
+get_shine(const float p[], float x)
+{
+       const int n = 15;
+       const float *y = &p[1];
+       float f = (n - 1) * (1 - 1 / (1 + p[0] * x))
+               / (1 - 1 / (1 + p[0] * 1024));
+       int i = f;
+
+       /* Linear interpolation in f-space (Faster and somewhat more
+        * accurate than x-space). */
+       if (x == 0)
+               return y[0];
+       else if (i > n - 2)
+               return y[n - 1];
+       else
+               return y[i] + (y[i + 1] - y[i]) * (f - i);
+}
+
+static const float nv10_spot_params[2][16] = {
+       { 0.02, -3.80e-05, -1.77, -2.41, -2.71, -2.88, -2.98, -3.06,
+         -3.11, -3.17, -3.23, -3.28, -3.37, -3.47, -3.83, -5.11 },
+       { 0.02, -0.01, 1.77, 2.39, 2.70, 2.87, 2.98, 3.06,
+         3.10, 3.16, 3.23, 3.27, 3.37, 3.47, 3.83, 5.11 },
+};
+
+void
+nv10_get_spot_coeff(struct gl_light *l, float k[7])
+{
+       float e = l->SpotExponent;
+       float a0, b0, a1, a2, b2, a3;
+
+       if (e > 0)
+               a0 = -1 - 5.36e-3 / sqrt(e);
+       else
+               a0 = -1;
+       b0 = 1 / (1 + 0.273 * e);
+
+       a1 = get_shine(nv10_spot_params[0], e);
+
+       a2 = get_shine(nv10_spot_params[1], e);
+       b2 = 1 / (1 + 0.273 * e);
+
+       a3 = 0.9 + 0.278 * e;
+
+       if (l->SpotCutoff > 0) {
+               float cutoff = MAX2(a3, 1 / (1 - l->_CosCutoff));
+
+               k[0] = MAX2(0, a0 + b0 * cutoff);
+               k[1] = a1;
+               k[2] = a2 + b2 * cutoff;
+               k[3] = - cutoff * l->_NormSpotDirection[0];
+               k[4] = - cutoff * l->_NormSpotDirection[1];
+               k[5] = - cutoff * l->_NormSpotDirection[2];
+               k[6] = 1 - cutoff;
+
+       } else {
+               k[0] = b0;
+               k[1] = a1;
+               k[2] = a2 + b2;
+               k[3] = - l->_NormSpotDirection[0];
+               k[4] = - l->_NormSpotDirection[1];
+               k[5] = - l->_NormSpotDirection[2];
+               k[6] = -1;
+       }
+}
+
+void
+nv10_emit_light_source(GLcontext *ctx, int emit)
+{
+       const int i = emit - NOUVEAU_STATE_LIGHT_SOURCE0;
+       struct nouveau_channel *chan = context_chan(ctx);
+       struct nouveau_grobj *celsius = context_eng3d(ctx);
+       struct gl_light *l = &ctx->Light.Light[i];
+
+       if (l->_Flags & LIGHT_POSITIONAL) {
+               BEGIN_RING(chan, celsius, NV10TCL_LIGHT_POSITION_X(i), 3);
+               OUT_RINGf(chan, l->_Position[0]);
+               OUT_RINGf(chan, l->_Position[1]);
+               OUT_RINGf(chan, l->_Position[2]);
+
+               BEGIN_RING(chan, celsius,
+                          NV10TCL_LIGHT_ATTENUATION_CONSTANT(i), 3);
+               OUT_RINGf(chan, l->ConstantAttenuation);
+               OUT_RINGf(chan, l->LinearAttenuation);
+               OUT_RINGf(chan, l->QuadraticAttenuation);
+
+       } else {
+               BEGIN_RING(chan, celsius, NV10TCL_LIGHT_DIRECTION_X(i), 3);
+               OUT_RINGf(chan, l->_VP_inf_norm[0]);
+               OUT_RINGf(chan, l->_VP_inf_norm[1]);
+               OUT_RINGf(chan, l->_VP_inf_norm[2]);
+
+               BEGIN_RING(chan, celsius, NV10TCL_LIGHT_HALF_VECTOR_X(i), 3);
+               OUT_RINGf(chan, l->_h_inf_norm[0]);
+               OUT_RINGf(chan, l->_h_inf_norm[1]);
+               OUT_RINGf(chan, l->_h_inf_norm[2]);
+       }
+
+       if (l->_Flags & LIGHT_SPOT) {
+               float k[7];
+
+               nv10_get_spot_coeff(l, k);
+
+               BEGIN_RING(chan, celsius, NV10TCL_LIGHT_SPOT_CUTOFF_A(i), 7);
+               OUT_RINGf(chan, k[0]);
+               OUT_RINGf(chan, k[1]);
+               OUT_RINGf(chan, k[2]);
+               OUT_RINGf(chan, k[3]);
+               OUT_RINGf(chan, k[4]);
+               OUT_RINGf(chan, k[5]);
+               OUT_RINGf(chan, k[6]);
+       }
+}
+
+#define USE_COLOR_MATERIAL(attr)                                       \
+       (ctx->Light.ColorMaterialEnabled &&                             \
+        ctx->Light.ColorMaterialBitmask & (1 << MAT_ATTRIB_FRONT_##attr))
+
+void
+nv10_emit_material_ambient(GLcontext *ctx, int emit)
+{
+       struct nouveau_channel *chan = context_chan(ctx);
+       struct nouveau_grobj *celsius = context_eng3d(ctx);
+       float (*mat)[4] = ctx->Light.Material.Attrib;
+       float c_scene[3], c_factor[3];
+       struct gl_light *l;
+
+       if (USE_COLOR_MATERIAL(AMBIENT)) {
+               COPY_3V(c_scene, ctx->Light.Model.Ambient);
+               COPY_3V(c_factor, mat[MAT_ATTRIB_FRONT_EMISSION]);
+
+       } else if (USE_COLOR_MATERIAL(EMISSION)) {
+               SCALE_3V(c_scene, mat[MAT_ATTRIB_FRONT_AMBIENT],
+                        ctx->Light.Model.Ambient);
+               ZERO_3V(c_factor);
+
+       } else {
+               COPY_3V(c_scene, ctx->Light._BaseColor[0]);
+               ZERO_3V(c_factor);
+       }
+
+       BEGIN_RING(chan, celsius, NV10TCL_LIGHT_MODEL_AMBIENT_R, 3);
+       OUT_RINGf(chan, c_scene[0]);
+       OUT_RINGf(chan, c_scene[1]);
+       OUT_RINGf(chan, c_scene[2]);
+
+       if (ctx->Light.ColorMaterialEnabled) {
+               BEGIN_RING(chan, celsius, NV10TCL_MATERIAL_FACTOR_R, 3);
+               OUT_RINGf(chan, c_factor[0]);
+               OUT_RINGf(chan, c_factor[1]);
+               OUT_RINGf(chan, c_factor[2]);
+       }
+
+       foreach(l, &ctx->Light.EnabledList) {
+               const int i = l - ctx->Light.Light;
+               float *c_light = (USE_COLOR_MATERIAL(AMBIENT) ?
+                                 l->Ambient :
+                                 l->_MatAmbient[0]);
+
+               BEGIN_RING(chan, celsius, NV10TCL_LIGHT_AMBIENT_R(i), 3);
+               OUT_RINGf(chan, c_light[0]);
+               OUT_RINGf(chan, c_light[1]);
+               OUT_RINGf(chan, c_light[2]);
+       }
+}
+
+void
+nv10_emit_material_diffuse(GLcontext *ctx, int emit)
+{
+       struct nouveau_channel *chan = context_chan(ctx);
+       struct nouveau_grobj *celsius = context_eng3d(ctx);
+       GLfloat (*mat)[4] = ctx->Light.Material.Attrib;
+       struct gl_light *l;
+
+       BEGIN_RING(chan, celsius, NV10TCL_MATERIAL_FACTOR_A, 1);
+       OUT_RINGf(chan, mat[MAT_ATTRIB_FRONT_DIFFUSE][3]);
+
+       foreach(l, &ctx->Light.EnabledList) {
+               const int i = l - ctx->Light.Light;
+               float *c_light = (USE_COLOR_MATERIAL(DIFFUSE) ?
+                                 l->Diffuse :
+                                 l->_MatDiffuse[0]);
+
+               BEGIN_RING(chan, celsius, NV10TCL_LIGHT_DIFFUSE_R(i), 3);
+               OUT_RINGf(chan, c_light[0]);
+               OUT_RINGf(chan, c_light[1]);
+               OUT_RINGf(chan, c_light[2]);
+       }
+}
+
+void
+nv10_emit_material_specular(GLcontext *ctx, int emit)
+{
+       struct nouveau_channel *chan = context_chan(ctx);
+       struct nouveau_grobj *celsius = context_eng3d(ctx);
+       struct gl_light *l;
+
+       foreach(l, &ctx->Light.EnabledList) {
+               const int i = l - ctx->Light.Light;
+               float *c_light = (USE_COLOR_MATERIAL(SPECULAR) ?
+                                 l->Specular :
+                                 l->_MatSpecular[0]);
+
+               BEGIN_RING(chan, celsius, NV10TCL_LIGHT_SPECULAR_R(i), 3);
+               OUT_RINGf(chan, c_light[0]);
+               OUT_RINGf(chan, c_light[1]);
+               OUT_RINGf(chan, c_light[2]);
+       }
+}
+
+static const float nv10_shininess_param[6][16] = {
+       { 0.70, 0.00, 0.06, 0.06, 0.05, 0.04, 0.02, 0.00,
+         -0.06, -0.13, -0.24, -0.36, -0.51, -0.66, -0.82, -1.00 },
+       { 0.01, 1.00, -2.29, -2.77, -2.96, -3.06, -3.12, -3.18,
+         -3.24, -3.29, -3.36, -3.43, -3.51, -3.75, -4.33, -5.11 },
+       { 0.02, 0.00, 2.28, 2.75, 2.94, 3.04, 3.1, 3.15,
+         3.18, 3.22, 3.27, 3.32, 3.39, 3.48, 3.84, 5.11 },
+       { 0.70, 0.00, 0.05, 0.06, 0.06, 0.06, 0.05, 0.04,
+         0.02, 0.01, -0.03, -0.12, -0.25, -0.43, -0.68, -0.99 },
+       { 0.01, 1.00, -1.61, -2.35, -2.67, -2.84, -2.96, -3.05,
+         -3.08, -3.14, -3.2, -3.26, -3.32, -3.42, -3.54, -4.21 },
+       { 0.01, 0.00, 2.25, 2.73, 2.92, 3.03, 3.09, 3.15,
+         3.16, 3.21, 3.25, 3.29, 3.35, 3.43, 3.56, 4.22 },
+};
+
+void
+nv10_get_shininess_coeff(float s, float k[6])
+{
+       int i;
+
+       for (i = 0; i < 6; i++)
+               k[i] = get_shine(nv10_shininess_param[i], s);
+}
+
+void
+nv10_emit_material_shininess(GLcontext *ctx, int emit)
+{
+       struct nouveau_channel *chan = context_chan(ctx);
+       struct nouveau_grobj *celsius = context_eng3d(ctx);
+       float (*mat)[4] = ctx->Light.Material.Attrib;
+       float k[6];
+
+       nv10_get_shininess_coeff(
+               CLAMP(mat[MAT_ATTRIB_FRONT_SHININESS][0], 0, 1024),
+               k);
+
+       BEGIN_RING(chan, celsius, NV10TCL_MATERIAL_SHININESS(0), 6);
+       OUT_RINGf(chan, k[0]);
+       OUT_RINGf(chan, k[1]);
+       OUT_RINGf(chan, k[2]);
+       OUT_RINGf(chan, k[3]);
+       OUT_RINGf(chan, k[4]);
+       OUT_RINGf(chan, k[5]);
+}
+
+void
+nv10_emit_modelview(GLcontext *ctx, int emit)
+{
+       struct nouveau_context *nctx = to_nouveau_context(ctx);
+       struct nouveau_channel *chan = context_chan(ctx);
+       struct nouveau_grobj *celsius = context_eng3d(ctx);
+       GLmatrix *m = ctx->ModelviewMatrixStack.Top;
+
+       if (nctx->fallback != HWTNL)
+               return;
+
+       if (ctx->Light._NeedEyeCoords || ctx->Fog.Enabled) {
+               BEGIN_RING(chan, celsius, NV10TCL_MODELVIEW0_MATRIX(0), 16);
+               OUT_RINGm(chan, m->m);
+       }
+
+       if (ctx->Light.Enabled) {
+               int i, j;
+
+               BEGIN_RING(chan, celsius,
+                          NV10TCL_INVERSE_MODELVIEW0_MATRIX(0), 12);
+               for (i = 0; i < 3; i++)
+                       for (j = 0; j < 4; j++)
+                               OUT_RINGf(chan, m->inv[4*i + j]);
+       }
+}
+
+void
+nv10_emit_point_parameter(GLcontext *ctx, int emit)
+{
+}
+
+void
+nv10_emit_projection(GLcontext *ctx, int emit)
+{
+       struct nouveau_context *nctx = to_nouveau_context(ctx);
+       struct nouveau_channel *chan = context_chan(ctx);
+       struct nouveau_grobj *celsius = context_eng3d(ctx);
+       GLmatrix m;
+
+       _math_matrix_ctr(&m);
+       get_viewport_scale(ctx, m.m);
+
+       if (nctx->fallback == HWTNL)
+               _math_matrix_mul_matrix(&m, &m, &ctx->_ModelProjectMatrix);
+
+       BEGIN_RING(chan, celsius, NV10TCL_PROJECTION_MATRIX(0), 16);
+       OUT_RINGm(chan, m.m);
+
+       _math_matrix_dtr(&m);
+}
diff --git a/src/mesa/drivers/dri/nouveau/nv20_context.c b/src/mesa/drivers/dri/nouveau/nv20_context.c
new file mode 100644 (file)
index 0000000..698b834
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2009 Francisco Jerez.
+ * 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.
+ *
+ */
+
+#include "nouveau_driver.h"
+#include "nouveau_context.h"
+#include "nv20_driver.h"
+
+GLcontext *
+nv20_context_create(struct nouveau_screen *screen, const GLvisual *visual,
+                   GLcontext *share_ctx)
+{
+       struct nouveau_context *nctx;
+       GLcontext *ctx;
+
+       nctx = CALLOC_STRUCT(nouveau_context);
+       if (!nctx)
+               return NULL;
+
+       ctx = &nctx->base;
+       nouveau_context_init(ctx, screen, visual, share_ctx);
+
+       ctx->Const.MaxTextureCoordUnits = NV20_TEXTURE_UNITS;
+       ctx->Const.MaxTextureImageUnits = NV20_TEXTURE_UNITS;
+       ctx->Const.MaxTextureUnits = NV20_TEXTURE_UNITS;
+       ctx->Const.MaxTextureMaxAnisotropy = 8;
+       ctx->Const.MaxTextureLodBias = 15;
+
+       nv20_render_init(ctx);
+
+       return ctx;
+}
+
+void
+nv20_context_destroy(GLcontext *ctx)
+{
+       nv20_render_destroy(ctx);
+       FREE(ctx);
+}
diff --git a/src/mesa/drivers/dri/nouveau/nv20_driver.h b/src/mesa/drivers/dri/nouveau/nv20_driver.h
new file mode 100644 (file)
index 0000000..2de18ee
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2009 Francisco Jerez.
+ * 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.
+ *
+ */
+
+#ifndef __NV20_DRIVER_H__
+#define __NV20_DRIVER_H__
+
+enum {
+       NOUVEAU_STATE_TEX_SHADER = NUM_NOUVEAU_STATE,
+       NUM_NV20_STATE
+};
+
+#define NV20_TEXTURE_UNITS 4
+
+/* nv20_screen.c */
+GLboolean
+nv20_screen_init(struct nouveau_screen *screen);
+
+/* nv20_context.c */
+GLcontext *
+nv20_context_create(struct nouveau_screen *screen, const GLvisual *visual,
+                   GLcontext *share_ctx);
+
+void
+nv20_context_destroy(GLcontext *ctx);
+
+/* nv20_render.c */
+void
+nv20_render_init(GLcontext *ctx);
+
+void
+nv20_render_destroy(GLcontext *ctx);
+
+/* nv20_state_fb.c */
+void
+nv20_emit_framebuffer(GLcontext *ctx, int emit);
+
+void
+nv20_emit_viewport(GLcontext *ctx, int emit);
+
+/* nv20_state_polygon.c */
+void
+nv20_emit_point_mode(GLcontext *ctx, int emit);
+
+/* nv20_state_raster.c */
+void
+nv20_emit_logic_opcode(GLcontext *ctx, int emit);
+
+/* nv20_state_tex.c */
+void
+nv20_emit_tex_obj(GLcontext *ctx, int emit);
+
+void
+nv20_emit_tex_shader(GLcontext *ctx, int emit);
+
+/* nv20_state_tnl.c */
+void
+nv20_emit_clip_plane(GLcontext *ctx, int emit);
+
+void
+nv20_emit_color_material(GLcontext *ctx, int emit);
+
+void
+nv20_emit_fog(GLcontext *ctx, int emit);
+
+void
+nv20_emit_light_model(GLcontext *ctx, int emit);
+
+void
+nv20_emit_light_source(GLcontext *ctx, int emit);
+
+void
+nv20_emit_material_ambient(GLcontext *ctx, int emit);
+
+void
+nv20_emit_material_diffuse(GLcontext *ctx, int emit);
+
+void
+nv20_emit_material_specular(GLcontext *ctx, int emit);
+
+void
+nv20_emit_material_shininess(GLcontext *ctx, int emit);
+
+void
+nv20_emit_modelview(GLcontext *ctx, int emit);
+
+void
+nv20_emit_projection(GLcontext *ctx, int emit);
+
+#endif
diff --git a/src/mesa/drivers/dri/nouveau/nv20_render.c b/src/mesa/drivers/dri/nouveau/nv20_render.c
new file mode 100644 (file)
index 0000000..a696ac1
--- /dev/null
@@ -0,0 +1,225 @@
+/*
+ * Copyright (C) 2009-2010 Francisco Jerez.
+ * 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.
+ *
+ */
+
+#include "nouveau_driver.h"
+#include "nouveau_context.h"
+#include "nouveau_class.h"
+#include "nv20_driver.h"
+
+#define NUM_VERTEX_ATTRS 16
+
+static void
+nv20_emit_material(GLcontext *ctx, struct nouveau_array_state *a,
+                  const void *v);
+
+/* Vertex attribute format. */
+static struct nouveau_attr_info nv20_vertex_attrs[VERT_ATTRIB_MAX] = {
+       [VERT_ATTRIB_POS] = {
+               .vbo_index = 0,
+               .imm_method = NV20TCL_VERTEX_POS_4F_X,
+               .imm_fields = 4,
+       },
+       [VERT_ATTRIB_NORMAL] = {
+               .vbo_index = 2,
+               .imm_method = NV20TCL_VERTEX_NOR_3F_X,
+               .imm_fields = 3,
+       },
+       [VERT_ATTRIB_COLOR0] = {
+               .vbo_index = 3,
+               .imm_method = NV20TCL_VERTEX_COL_4F_X,
+               .imm_fields = 4,
+       },
+       [VERT_ATTRIB_COLOR1] = {
+               .vbo_index = 4,
+               .imm_method = NV20TCL_VERTEX_COL2_3F_X,
+               .imm_fields = 3,
+       },
+       [VERT_ATTRIB_FOG] = {
+               .vbo_index = 5,
+               .imm_method = NV20TCL_VERTEX_FOG_1F,
+               .imm_fields = 1,
+       },
+       [VERT_ATTRIB_TEX0] = {
+               .vbo_index = 9,
+               .imm_method = NV20TCL_VERTEX_TX0_4F_S,
+               .imm_fields = 4,
+       },
+       [VERT_ATTRIB_TEX1] = {
+               .vbo_index = 10,
+               .imm_method = NV20TCL_VERTEX_TX1_4F_S,
+               .imm_fields = 4,
+       },
+       [VERT_ATTRIB_TEX2] = {
+               .vbo_index = 11,
+               .imm_method = NV20TCL_VERTEX_TX2_4F_S,
+               .imm_fields = 4,
+       },
+       [VERT_ATTRIB_TEX3] = {
+               .vbo_index = 12,
+               .imm_method = NV20TCL_VERTEX_TX3_4F_S,
+               .imm_fields = 4,
+       },
+       [VERT_ATTRIB_GENERIC0] = {
+               .emit = nv20_emit_material,
+       },
+       [VERT_ATTRIB_GENERIC1] = {
+               .emit = nv20_emit_material,
+       },
+       [VERT_ATTRIB_GENERIC2] = {
+               .emit = nv20_emit_material,
+       },
+       [VERT_ATTRIB_GENERIC3] = {
+               .emit = nv20_emit_material,
+       },
+       [VERT_ATTRIB_GENERIC4] = {
+               .emit = nv20_emit_material,
+       },
+       [VERT_ATTRIB_GENERIC5] = {
+               .emit = nv20_emit_material,
+       },
+       [VERT_ATTRIB_GENERIC6] = {
+               .emit = nv20_emit_material,
+       },
+       [VERT_ATTRIB_GENERIC7] = {
+               .emit = nv20_emit_material,
+       },
+       [VERT_ATTRIB_GENERIC8] = {
+               .emit = nv20_emit_material,
+       },
+       [VERT_ATTRIB_GENERIC9] = {
+               .emit = nv20_emit_material,
+       },
+};
+
+static int
+get_hw_format(int type)
+{
+       switch (type) {
+       case GL_FLOAT:
+               return NV20TCL_VTXFMT_TYPE_FLOAT;
+       case GL_UNSIGNED_SHORT:
+               return NV20TCL_VTXFMT_TYPE_USHORT;
+       case GL_UNSIGNED_BYTE:
+               return NV20TCL_VTXFMT_TYPE_UBYTE;
+       default:
+               assert(0);
+       }
+}
+
+static void
+nv20_render_set_format(GLcontext *ctx)
+{
+       struct nouveau_render_state *render = to_render_state(ctx);
+       struct nouveau_channel *chan = context_chan(ctx);
+       struct nouveau_grobj *kelvin = context_eng3d(ctx);
+       int i, hw_format;
+
+       for (i = 0; i < NUM_VERTEX_ATTRS; i++) {
+               int attr = render->map[i];
+
+               if (attr >= 0) {
+                       struct nouveau_array_state *a = &render->attrs[attr];
+
+                       hw_format = a->stride << 8 |
+                               a->fields << 4 |
+                               get_hw_format(a->type);
+
+               } else {
+                       /* Unused attribute. */
+                       hw_format = NV10TCL_VTXFMT_TYPE_FLOAT;
+               }
+
+               BEGIN_RING(chan, kelvin, NV20TCL_VTXFMT(i), 1);
+               OUT_RING(chan, hw_format);
+       }
+}
+
+static void
+nv20_render_bind_vertices(GLcontext *ctx)
+{
+       struct nouveau_render_state *render = to_render_state(ctx);
+       struct nouveau_bo_context *bctx = context_bctx(ctx, VERTEX);
+       struct nouveau_channel *chan = context_chan(ctx);
+       struct nouveau_grobj *kelvin = context_eng3d(ctx);
+       int i;
+
+       for (i = 0; i < NUM_VERTEX_ATTRS; i++) {
+               int attr = render->map[i];
+
+               if (attr >= 0) {
+                       struct nouveau_array_state *a = &render->attrs[attr];
+
+                       nouveau_bo_mark(bctx, kelvin,
+                                       NV20TCL_VTXBUF_ADDRESS(i),
+                                       a->bo, a->offset, 0,
+                                       0, NV20TCL_VTXBUF_ADDRESS_DMA1,
+                                       NOUVEAU_BO_LOW | NOUVEAU_BO_OR |
+                                       NOUVEAU_BO_GART | NOUVEAU_BO_RD);
+               }
+       }
+
+       BEGIN_RING(chan, kelvin, NV20TCL_VTX_CACHE_INVALIDATE, 1);
+       OUT_RING(chan, 0);
+}
+
+/* Vertex array rendering defs. */
+#define RENDER_LOCALS(ctx)                                     \
+       struct nouveau_grobj *kelvin = context_eng3d(ctx)
+
+#define BATCH_BEGIN(prim)                                      \
+       BEGIN_RING(chan, kelvin, NV20TCL_VERTEX_BEGIN_END, 1);  \
+       OUT_RING(chan, prim);
+#define BATCH_END()                                            \
+       BEGIN_RING(chan, kelvin, NV20TCL_VERTEX_BEGIN_END, 1);  \
+       OUT_RING(chan, 0);
+
+#define MAX_PACKET 0x400
+
+#define MAX_OUT_L 0x100
+#define BATCH_PACKET_L(n)                                              \
+       BEGIN_RING_NI(chan, kelvin, NV20TCL_VB_VERTEX_BATCH, n);
+#define BATCH_OUT_L(i, n)                      \
+       OUT_RING(chan, ((n) - 1) << 24 | (i));
+
+#define MAX_OUT_I16 0x2
+#define BATCH_PACKET_I16(n)                                    \
+       BEGIN_RING_NI(chan, kelvin, NV20TCL_VB_ELEMENT_U16, n);
+#define BATCH_OUT_I16(i0, i1)                  \
+       OUT_RING(chan, (i1) << 16 | (i0));
+
+#define MAX_OUT_I32 0x1
+#define BATCH_PACKET_I32(n)                                    \
+       BEGIN_RING_NI(chan, kelvin, NV20TCL_VB_ELEMENT_U32, n);
+#define BATCH_OUT_I32(i)                       \
+       OUT_RING(chan, i);
+
+#define IMM_PACKET(m, n)                       \
+       BEGIN_RING(chan, kelvin, m, n);
+#define IMM_OUT(x)                             \
+       OUT_RINGf(chan, x);
+
+#define TAG(x) nv20_##x
+#include "nouveau_render_t.c"
diff --git a/src/mesa/drivers/dri/nouveau/nv20_screen.c b/src/mesa/drivers/dri/nouveau/nv20_screen.c
new file mode 100644 (file)
index 0000000..1d29fc9
--- /dev/null
@@ -0,0 +1,483 @@
+/*
+ * Copyright (C) 2009 Francisco Jerez.
+ * 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.
+ *
+ */
+
+#include "nouveau_driver.h"
+#include "nouveau_screen.h"
+#include "nouveau_class.h"
+#include "nv04_driver.h"
+#include "nv10_driver.h"
+#include "nv20_driver.h"
+
+static const struct nouveau_driver nv20_driver;
+
+static void
+nv20_hwctx_init(struct nouveau_screen *screen)
+{
+       struct nouveau_channel *chan = screen->chan;
+       struct nouveau_grobj *kelvin = screen->eng3d;
+       const unsigned chipset = screen->device->chipset;
+       int i;
+
+       BEGIN_RING(chan, kelvin, NV20TCL_DMA_NOTIFY, 1);
+       OUT_RING  (chan, screen->ntfy->handle);
+       BEGIN_RING(chan, kelvin, NV20TCL_DMA_TEXTURE0, 2);
+       OUT_RING  (chan, chan->vram->handle);
+       OUT_RING  (chan, chan->gart->handle);
+       BEGIN_RING(chan, kelvin, NV20TCL_DMA_COLOR, 2);
+       OUT_RING  (chan, chan->vram->handle);
+       OUT_RING  (chan, chan->vram->handle);
+       BEGIN_RING(chan, kelvin, NV20TCL_DMA_VTXBUF0, 2);
+       OUT_RING(chan, chan->vram->handle);
+       OUT_RING(chan, chan->gart->handle);
+
+       BEGIN_RING(chan, kelvin, NV20TCL_DMA_QUERY, 1);
+       OUT_RING  (chan, 0);
+
+       BEGIN_RING(chan, kelvin, NV20TCL_RT_HORIZ, 2);
+       OUT_RING  (chan, 0);
+       OUT_RING  (chan, 0);
+
+       BEGIN_RING(chan, kelvin, NV20TCL_VIEWPORT_CLIP_HORIZ(0), 1);
+       OUT_RING  (chan, 0xfff << 16 | 0x0);
+       BEGIN_RING(chan, kelvin, NV20TCL_VIEWPORT_CLIP_VERT(0), 1);
+       OUT_RING  (chan, 0xfff << 16 | 0x0);
+
+       for (i = 1; i < NV20TCL_VIEWPORT_CLIP_HORIZ__SIZE; i++) {
+               BEGIN_RING(chan, kelvin, NV20TCL_VIEWPORT_CLIP_HORIZ(i), 1);
+               OUT_RING  (chan, 0);
+               BEGIN_RING(chan, kelvin, NV20TCL_VIEWPORT_CLIP_VERT(i), 1);
+               OUT_RING  (chan, 0);
+       }
+
+       BEGIN_RING(chan, kelvin, NV20TCL_VIEWPORT_CLIP_MODE, 1);
+       OUT_RING  (chan, 0);
+
+       BEGIN_RING(chan, kelvin, 0x17e0, 3);
+       OUT_RINGf (chan, 0.0);
+       OUT_RINGf (chan, 0.0);
+       OUT_RINGf (chan, 1.0);
+
+       if (chipset >= 0x25) {
+               BEGIN_RING(chan, kelvin, NV20TCL_TX_RCOMP, 1);
+               OUT_RING  (chan, NV20TCL_TX_RCOMP_LEQUAL | 0xdb0);
+       } else {
+               BEGIN_RING(chan, kelvin, 0x1e68, 1);
+               OUT_RING  (chan, 0x4b800000); /* 16777216.000000 */
+               BEGIN_RING(chan, kelvin, NV20TCL_TX_RCOMP, 1);
+               OUT_RING  (chan, NV20TCL_TX_RCOMP_LEQUAL);
+       }
+
+       BEGIN_RING(chan, kelvin, 0x290, 1);
+       OUT_RING  (chan, 0x10 << 16 | 1);
+       BEGIN_RING(chan, kelvin, 0x9fc, 1);
+       OUT_RING  (chan, 0);
+       BEGIN_RING(chan, kelvin, 0x1d80, 1);
+       OUT_RING  (chan, 1);
+       BEGIN_RING(chan, kelvin, 0x9f8, 1);
+       OUT_RING  (chan, 4);
+       BEGIN_RING(chan, kelvin, 0x17ec, 3);
+       OUT_RINGf (chan, 0.0);
+       OUT_RINGf (chan, 1.0);
+       OUT_RINGf (chan, 0.0);
+
+       if (chipset >= 0x25) {
+               BEGIN_RING(chan, kelvin, 0x1d88, 1);
+               OUT_RING  (chan, 3);
+
+               BEGIN_RING(chan, kelvin, NV25TCL_DMA_IN_MEMORY9, 1);
+               OUT_RING  (chan, chan->vram->handle);
+               BEGIN_RING(chan, kelvin, NV25TCL_DMA_IN_MEMORY8, 1);
+               OUT_RING  (chan, chan->vram->handle);
+       }
+
+       BEGIN_RING(chan, kelvin, NV20TCL_DMA_FENCE, 1);
+       OUT_RING  (chan, 0);
+
+       BEGIN_RING(chan, kelvin, 0x1e98, 1);
+       OUT_RING  (chan, 0);
+
+       BEGIN_RING(chan, kelvin, NV20TCL_NOTIFY, 1);
+       OUT_RING  (chan, 0);
+
+       BEGIN_RING(chan, kelvin, 0x120, 3);
+       OUT_RING  (chan, 0);
+       OUT_RING  (chan, 1);
+       OUT_RING  (chan, 2);
+
+       if (chipset >= 0x25) {
+               BEGIN_RING(chan, kelvin, 0x022c, 2);
+               OUT_RING  (chan, 0x280);
+               OUT_RING  (chan, 0x07d28000);
+
+               BEGIN_RING(chan, kelvin, 0x1da4, 1);
+               OUT_RING  (chan, 0);
+       }
+
+       BEGIN_RING(chan, kelvin, NV20TCL_RT_HORIZ, 2);
+       OUT_RING  (chan, 0 << 16 | 0);
+       OUT_RING  (chan, 0 << 16 | 0);
+
+       BEGIN_RING(chan, kelvin, NV20TCL_ALPHA_FUNC_ENABLE, 1);
+       OUT_RING  (chan, 0);
+       BEGIN_RING(chan, kelvin, NV20TCL_ALPHA_FUNC_FUNC, 2);
+       OUT_RING  (chan, NV20TCL_ALPHA_FUNC_FUNC_ALWAYS);
+       OUT_RING  (chan, 0);
+
+       for (i = 0; i < NV20TCL_TX_ENABLE__SIZE; i++) {
+               BEGIN_RING(chan, kelvin, NV20TCL_TX_ENABLE(i), 1);
+               OUT_RING  (chan, 0);
+       }
+
+       BEGIN_RING(chan, kelvin, NV20TCL_TX_SHADER_OP, 1);
+       OUT_RING  (chan, 0);
+       BEGIN_RING(chan, kelvin, NV20TCL_TX_SHADER_CULL_MODE, 1);
+       OUT_RING  (chan, 0);
+
+       BEGIN_RING(chan, kelvin, NV20TCL_RC_IN_ALPHA(0), 4);
+       OUT_RING  (chan, 0x30d410d0);
+       OUT_RING  (chan, 0);
+       OUT_RING  (chan, 0);
+       OUT_RING  (chan, 0);
+       BEGIN_RING(chan, kelvin, NV20TCL_RC_OUT_RGB(0), 4);
+       OUT_RING  (chan, 0x00000c00);
+       OUT_RING  (chan, 0);
+       OUT_RING  (chan, 0);
+       OUT_RING  (chan, 0);
+       BEGIN_RING(chan, kelvin, NV20TCL_RC_ENABLE, 1);
+       OUT_RING  (chan, 0x00011101);
+       BEGIN_RING(chan, kelvin, NV20TCL_RC_FINAL0, 2);
+       OUT_RING  (chan, 0x130e0300);
+       OUT_RING  (chan, 0x0c091c80);
+       BEGIN_RING(chan, kelvin, NV20TCL_RC_OUT_ALPHA(0), 4);
+       OUT_RING  (chan, 0x00000c00);
+       OUT_RING  (chan, 0);
+       OUT_RING  (chan, 0);
+       OUT_RING  (chan, 0);
+       BEGIN_RING(chan, kelvin, NV20TCL_RC_IN_RGB(0), 4);
+       OUT_RING  (chan, 0x20c400c0);
+       OUT_RING  (chan, 0);
+       OUT_RING  (chan, 0);
+       OUT_RING  (chan, 0);
+       BEGIN_RING(chan, kelvin, NV20TCL_RC_COLOR0, 2);
+       OUT_RING  (chan, 0);
+       OUT_RING  (chan, 0);
+       BEGIN_RING(chan, kelvin, NV20TCL_RC_CONSTANT_COLOR0(0), 4);
+       OUT_RING  (chan, 0x035125a0);
+       OUT_RING  (chan, 0);
+       OUT_RING  (chan, 0x40002000);
+       OUT_RING  (chan, 0);
+
+       BEGIN_RING(chan, kelvin, NV20TCL_MULTISAMPLE_CONTROL, 1);
+       OUT_RING  (chan, 0xffff0000);
+       BEGIN_RING(chan, kelvin, NV20TCL_BLEND_FUNC_ENABLE, 1);
+       OUT_RING  (chan, 0);
+       BEGIN_RING(chan, kelvin, NV20TCL_DITHER_ENABLE, 1);
+       OUT_RING  (chan, 0);
+       BEGIN_RING(chan, kelvin, NV20TCL_STENCIL_ENABLE, 1);
+       OUT_RING  (chan, 0);
+       BEGIN_RING(chan, kelvin, NV20TCL_BLEND_FUNC_SRC, 4);
+       OUT_RING  (chan, NV20TCL_BLEND_FUNC_SRC_ONE);
+       OUT_RING  (chan, NV20TCL_BLEND_FUNC_DST_ZERO);
+       OUT_RING  (chan, 0);
+       OUT_RING  (chan, NV20TCL_BLEND_EQUATION_FUNC_ADD);
+       BEGIN_RING(chan, kelvin, NV20TCL_STENCIL_MASK, 7);
+       OUT_RING  (chan, 0xff);
+       OUT_RING  (chan, NV20TCL_STENCIL_FUNC_FUNC_ALWAYS);
+       OUT_RING  (chan, 0);
+       OUT_RING  (chan, 0xff);
+       OUT_RING  (chan, NV20TCL_STENCIL_OP_FAIL_KEEP);
+       OUT_RING  (chan, NV20TCL_STENCIL_OP_ZFAIL_KEEP);
+       OUT_RING  (chan, NV20TCL_STENCIL_OP_ZPASS_KEEP);
+
+       BEGIN_RING(chan, kelvin, NV20TCL_COLOR_LOGIC_OP_ENABLE, 2);
+       OUT_RING  (chan, 0);
+       OUT_RING  (chan, NV20TCL_COLOR_LOGIC_OP_OP_COPY);
+       BEGIN_RING(chan, kelvin, 0x17cc, 1);
+       OUT_RING  (chan, 0);
+       if (chipset >= 0x25) {
+               BEGIN_RING(chan, kelvin, 0x1d84, 1);
+               OUT_RING  (chan, 1);
+       }
+       BEGIN_RING(chan, kelvin, NV20TCL_LIGHTING_ENABLE, 1);
+       OUT_RING  (chan, 0);
+       BEGIN_RING(chan, kelvin, NV20TCL_LIGHT_MODEL, 1);
+       OUT_RING  (chan, NV20TCL_LIGHT_MODEL_VIEWER_NONLOCAL);
+       BEGIN_RING(chan, kelvin, NV20TCL_SEPARATE_SPECULAR_ENABLE, 1);
+       OUT_RING  (chan, 0);
+       BEGIN_RING(chan, kelvin, NV20TCL_LIGHT_MODEL_TWO_SIDE_ENABLE, 1);
+       OUT_RING  (chan, 0);
+       BEGIN_RING(chan, kelvin, NV20TCL_ENABLED_LIGHTS, 1);
+       OUT_RING  (chan, 0);
+       BEGIN_RING(chan, kelvin, NV20TCL_NORMALIZE_ENABLE, 1);
+       OUT_RING  (chan, 0);
+       BEGIN_RING(chan, kelvin, NV20TCL_POLYGON_STIPPLE_PATTERN(0),
+                  NV20TCL_POLYGON_STIPPLE_PATTERN__SIZE);
+       for (i = 0; i < NV20TCL_POLYGON_STIPPLE_PATTERN__SIZE; i++) {
+               OUT_RING(chan, 0xffffffff);
+       }
+
+       BEGIN_RING(chan, kelvin, NV20TCL_POLYGON_OFFSET_POINT_ENABLE, 3);
+       OUT_RING  (chan, 0);
+       OUT_RING  (chan, 0);
+       OUT_RING  (chan, 0);
+       BEGIN_RING(chan, kelvin, NV20TCL_DEPTH_FUNC, 1);
+       OUT_RING  (chan, NV20TCL_DEPTH_FUNC_LESS);
+       BEGIN_RING(chan, kelvin, NV20TCL_DEPTH_WRITE_ENABLE, 1);
+       OUT_RING  (chan, 0);
+       BEGIN_RING(chan, kelvin, NV20TCL_DEPTH_TEST_ENABLE, 1);
+       OUT_RING  (chan, 0);
+       BEGIN_RING(chan, kelvin, NV20TCL_POLYGON_OFFSET_FACTOR, 2);
+       OUT_RINGf (chan, 0.0);
+       OUT_RINGf (chan, 0.0);
+       BEGIN_RING(chan, kelvin, NV20TCL_DEPTH_UNK17D8, 1);
+       OUT_RING  (chan, 1);
+       if (chipset < 0x25) {
+               BEGIN_RING(chan, kelvin, 0x1d84, 1);
+               OUT_RING  (chan, 3);
+       }
+       BEGIN_RING(chan, kelvin, NV20TCL_POINT_SIZE, 1);
+       if (chipset >= 0x25)
+               OUT_RINGf (chan, 1.0);
+       else
+               OUT_RING  (chan, 8);
+
+       if (chipset >= 0x25) {
+               BEGIN_RING(chan, kelvin, NV20TCL_POINT_PARAMETERS_ENABLE, 1);
+               OUT_RING  (chan, 0);
+               BEGIN_RING(chan, kelvin, 0x0a1c, 1);
+               OUT_RING  (chan, 0x800);
+       } else {
+               BEGIN_RING(chan, kelvin, NV20TCL_POINT_PARAMETERS_ENABLE, 2);
+               OUT_RING  (chan, 0);
+               OUT_RING  (chan, 0);
+       }
+
+       BEGIN_RING(chan, kelvin, NV20TCL_LINE_WIDTH, 1);
+       OUT_RING  (chan, 8);
+       BEGIN_RING(chan, kelvin, NV20TCL_LINE_SMOOTH_ENABLE, 1);
+       OUT_RING  (chan, 0);
+       BEGIN_RING(chan, kelvin, NV20TCL_POLYGON_MODE_FRONT, 2);
+       OUT_RING  (chan, NV20TCL_POLYGON_MODE_FRONT_FILL);
+       OUT_RING  (chan, NV20TCL_POLYGON_MODE_BACK_FILL);
+       BEGIN_RING(chan, kelvin, NV20TCL_CULL_FACE, 2);
+       OUT_RING  (chan, NV20TCL_CULL_FACE_BACK);
+       OUT_RING  (chan, NV20TCL_FRONT_FACE_CCW);
+       BEGIN_RING(chan, kelvin, NV20TCL_POLYGON_SMOOTH_ENABLE, 1);
+       OUT_RING  (chan, 0);
+       BEGIN_RING(chan, kelvin, NV20TCL_CULL_FACE_ENABLE, 1);
+       OUT_RING  (chan, 0);
+       BEGIN_RING(chan, kelvin, NV20TCL_SHADE_MODEL, 1);
+       OUT_RING  (chan, NV20TCL_SHADE_MODEL_SMOOTH);
+       BEGIN_RING(chan, kelvin, NV20TCL_POLYGON_STIPPLE_ENABLE, 1);
+       OUT_RING  (chan, 0);
+
+       BEGIN_RING(chan, kelvin, NV20TCL_TX_GEN_S(0),
+                  4 * NV20TCL_TX_GEN_S__SIZE);
+       for (i=0; i < 4 * NV20TCL_TX_GEN_S__SIZE; i++)
+               OUT_RING(chan, 0);
+
+       BEGIN_RING(chan, kelvin, NV20TCL_FOG_EQUATION_CONSTANT, 3);
+       OUT_RINGf (chan, 1.5);
+       OUT_RINGf (chan, -0.090168);
+       OUT_RINGf (chan, 0.0);
+       BEGIN_RING(chan, kelvin, NV20TCL_FOG_MODE, 2);
+       OUT_RING  (chan, NV20TCL_FOG_MODE_EXP_SIGNED);
+       OUT_RING  (chan, NV20TCL_FOG_COORD_FOG);
+       BEGIN_RING(chan, kelvin, NV20TCL_FOG_ENABLE, 2);
+       OUT_RING  (chan, 0);
+       OUT_RING  (chan, 0);
+
+       BEGIN_RING(chan, kelvin, NV20TCL_ENGINE, 1);
+       OUT_RING  (chan, NV20TCL_ENGINE_FIXED);
+
+       for (i = 0; i < NV20TCL_TX_MATRIX_ENABLE__SIZE; i++) {
+               BEGIN_RING(chan, kelvin, NV20TCL_TX_MATRIX_ENABLE(i), 1);
+               OUT_RING  (chan, 0);
+       }
+
+       BEGIN_RING(chan, kelvin, NV20TCL_VTX_ATTR_4F_X(1), 4 * 15);
+       OUT_RINGf(chan, 1.0);
+       OUT_RINGf(chan, 0.0);
+       OUT_RINGf(chan, 0.0);
+       OUT_RINGf(chan, 1.0);
+       OUT_RINGf(chan, 0.0);
+       OUT_RINGf(chan, 0.0);
+       OUT_RINGf(chan, 1.0);
+       OUT_RINGf(chan, 1.0);
+       OUT_RINGf(chan, 1.0);
+       OUT_RINGf(chan, 1.0);
+       OUT_RINGf(chan, 1.0);
+       OUT_RINGf(chan, 1.0);
+       for (i = 0; i < 12; i++) {
+               OUT_RINGf(chan, 0.0);
+               OUT_RINGf(chan, 0.0);
+               OUT_RINGf(chan, 0.0);
+               OUT_RINGf(chan, 1.0);
+       }
+
+       BEGIN_RING(chan, kelvin, NV20TCL_EDGEFLAG_ENABLE, 1);
+       OUT_RING  (chan, 1);
+       BEGIN_RING(chan, kelvin, NV20TCL_COLOR_MASK, 1);
+       OUT_RING (chan, 0x00010101);
+       BEGIN_RING(chan, kelvin, NV20TCL_CLEAR_VALUE, 1);
+       OUT_RING (chan, 0);
+
+       BEGIN_RING(chan, kelvin, NV20TCL_DEPTH_RANGE_NEAR, 2);
+       OUT_RINGf (chan, 0.0);
+       OUT_RINGf (chan, 16777216.0);
+
+       BEGIN_RING(chan, kelvin, NV20TCL_VIEWPORT_TRANSLATE_X, 4);
+       OUT_RINGf (chan, 0.0);
+       OUT_RINGf (chan, 0.0);
+       OUT_RINGf (chan, 0.0);
+       OUT_RINGf (chan, 16777215.0);
+
+       BEGIN_RING(chan, kelvin, NV20TCL_VIEWPORT_SCALE_X, 4);
+       OUT_RINGf (chan, 0.0);
+       OUT_RINGf (chan, 0.0);
+       OUT_RINGf (chan, 16777215.0 * 0.5);
+       OUT_RINGf (chan, 65535.0);
+
+       FIRE_RING(chan);
+}
+
+GLboolean
+nv20_screen_init(struct nouveau_screen *screen)
+{
+       unsigned chipset = screen->device->chipset;
+       unsigned kelvin_class;
+       int ret;
+
+       screen->driver = &nv20_driver;
+
+       /* 2D engine */
+       ret = nv04_surface_init(screen);
+       if (!ret)
+               return GL_FALSE;
+
+       /* 3D engine. */
+       if (chipset >= 0x25)
+               kelvin_class = NV25TCL;
+       else
+               kelvin_class = NV20TCL;
+
+       ret = nouveau_grobj_alloc(screen->chan, 0xbeef0001, kelvin_class,
+                                 &screen->eng3d);
+       if (ret)
+               return GL_FALSE;
+
+       nv20_hwctx_init(screen);
+
+       return GL_TRUE;
+}
+
+static void
+nv20_screen_destroy(struct nouveau_screen *screen)
+{
+       if (screen->eng3d)
+               nouveau_grobj_free(&screen->eng3d);
+
+       nv04_surface_takedown(screen);
+}
+
+static const struct nouveau_driver nv20_driver = {
+       .screen_destroy = nv20_screen_destroy,
+       .context_create = nv20_context_create,
+       .context_destroy = nv20_context_destroy,
+       .surface_copy = nv04_surface_copy,
+       .surface_fill = nv04_surface_fill,
+       .emit = (nouveau_state_func[]) {
+               nv10_emit_alpha_func,
+               nv10_emit_blend_color,
+               nv10_emit_blend_equation,
+               nv10_emit_blend_func,
+               nv20_emit_clip_plane,
+               nv20_emit_clip_plane,
+               nv20_emit_clip_plane,
+               nv20_emit_clip_plane,
+               nv20_emit_clip_plane,
+               nv20_emit_clip_plane,
+               nv10_emit_color_mask,
+               nv20_emit_color_material,
+               nv10_emit_cull_face,
+               nv10_emit_front_face,
+               nv10_emit_depth,
+               nv10_emit_dither,
+               nv10_emit_frag,
+               nv20_emit_framebuffer,
+               nv20_emit_fog,
+               nv10_emit_index_mask,
+               nv10_emit_light_enable,
+               nv20_emit_light_model,
+               nv20_emit_light_source,
+               nv20_emit_light_source,
+               nv20_emit_light_source,
+               nv20_emit_light_source,
+               nv20_emit_light_source,
+               nv20_emit_light_source,
+               nv20_emit_light_source,
+               nv20_emit_light_source,
+               nv10_emit_line_stipple,
+               nv10_emit_line_mode,
+               nv20_emit_logic_opcode,
+               nv20_emit_material_ambient,
+               nv20_emit_material_ambient,
+               nv20_emit_material_diffuse,
+               nv20_emit_material_diffuse,
+               nv20_emit_material_specular,
+               nv20_emit_material_specular,
+               nv20_emit_material_shininess,
+               nv20_emit_material_shininess,
+               nv20_emit_modelview,
+               nv20_emit_point_mode,
+               nv10_emit_point_parameter,
+               nv10_emit_polygon_mode,
+               nv10_emit_polygon_offset,
+               nv10_emit_polygon_stipple,
+               nv20_emit_projection,
+               nv10_emit_render_mode,
+               nv10_emit_scissor,
+               nv10_emit_shade_model,
+               nv10_emit_stencil_func,
+               nv10_emit_stencil_mask,
+               nv10_emit_stencil_op,
+               nv10_emit_tex_env,
+               nv10_emit_tex_env,
+               nv10_emit_tex_env,
+               nv10_emit_tex_env,
+               nv10_emit_tex_gen,
+               nv10_emit_tex_gen,
+               nv10_emit_tex_gen,
+               nv10_emit_tex_gen,
+               nv20_emit_tex_obj,
+               nv20_emit_tex_obj,
+               nv20_emit_tex_obj,
+               nv20_emit_tex_obj,
+               nv20_emit_viewport,
+               nv20_emit_tex_shader
+       },
+       .num_emit = NUM_NV20_STATE,
+};
diff --git a/src/mesa/drivers/dri/nouveau/nv20_state_fb.c b/src/mesa/drivers/dri/nouveau/nv20_state_fb.c
new file mode 100644 (file)
index 0000000..869acd6
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2009 Francisco Jerez.
+ * 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.
+ *
+ */
+
+#include "nouveau_driver.h"
+#include "nouveau_context.h"
+#include "nouveau_fbo.h"
+#include "nouveau_gldefs.h"
+#include "nouveau_util.h"
+#include "nouveau_class.h"
+#include "nv20_driver.h"
+
+static inline unsigned
+get_rt_format(gl_format format)
+{
+       switch (format) {
+       case MESA_FORMAT_XRGB8888:
+               return 0x05;
+       case MESA_FORMAT_ARGB8888:
+               return 0x08;
+       case MESA_FORMAT_RGB565:
+               return 0x03;
+       case MESA_FORMAT_Z16:
+               return 0x10;
+       case MESA_FORMAT_Z24_S8:
+               return 0x20;
+       default:
+               assert(0);
+       }
+}
+
+void
+nv20_emit_framebuffer(GLcontext *ctx, int emit)
+{
+       struct nouveau_channel *chan = context_chan(ctx);
+       struct nouveau_grobj *kelvin = context_eng3d(ctx);
+       struct nouveau_bo_context *bctx = context_bctx(ctx, FRAMEBUFFER);
+       struct gl_framebuffer *fb = ctx->DrawBuffer;
+       struct nouveau_surface *s;
+       unsigned rt_format = NV20TCL_RT_FORMAT_TYPE_LINEAR;
+       unsigned rt_pitch = 0, zeta_pitch = 0;
+       unsigned bo_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR;
+
+       if (fb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT)
+               return;
+
+       /* Render target */
+       if (fb->_NumColorDrawBuffers) {
+               s = &to_nouveau_renderbuffer(
+                       fb->_ColorDrawBuffers[0])->surface;
+
+               rt_format |= get_rt_format(s->format);
+               zeta_pitch = rt_pitch = s->pitch;
+
+               nouveau_bo_markl(bctx, kelvin, NV20TCL_COLOR_OFFSET,
+                                s->bo, 0, bo_flags);
+       }
+
+       /* depth/stencil */
+       if (fb->_DepthBuffer) {
+               s = &to_nouveau_renderbuffer(
+                       fb->_DepthBuffer->Wrapped)->surface;
+
+               rt_format |= get_rt_format(s->format);
+               zeta_pitch = s->pitch;
+
+               nouveau_bo_markl(bctx, kelvin, NV20TCL_ZETA_OFFSET,
+                                s->bo, 0, bo_flags);
+       }
+
+       BEGIN_RING(chan, kelvin, NV20TCL_RT_FORMAT, 2);
+       OUT_RING(chan, rt_format);
+       OUT_RING(chan, zeta_pitch << 16 | rt_pitch);
+
+       /* Recompute the viewport/scissor state. */
+       context_dirty(ctx, VIEWPORT);
+       context_dirty(ctx, SCISSOR);
+}
+
+void
+nv20_emit_viewport(GLcontext *ctx, int emit)
+{
+       struct nouveau_channel *chan = context_chan(ctx);
+       struct nouveau_grobj *kelvin = context_eng3d(ctx);
+       struct gl_framebuffer *fb = ctx->DrawBuffer;
+       float a[4] = {};
+       int i;
+
+       get_viewport_translate(ctx, a);
+
+       BEGIN_RING(chan, kelvin, NV20TCL_VIEWPORT_TRANSLATE_X, 4);
+       for (i = 0; i < 4; i++)
+               OUT_RINGf(chan, a[i]);
+
+       BEGIN_RING(chan, kelvin, NV20TCL_VIEWPORT_CLIP_HORIZ(0), 1);
+       OUT_RING(chan, (fb->Width - 1) << 16);
+       BEGIN_RING(chan, kelvin, NV20TCL_VIEWPORT_CLIP_VERT(0), 1);
+       OUT_RING(chan, (fb->Height - 1) << 16);
+
+       context_dirty(ctx, PROJECTION);
+}
diff --git a/src/mesa/drivers/dri/nouveau/nv20_state_polygon.c b/src/mesa/drivers/dri/nouveau/nv20_state_polygon.c
new file mode 100644 (file)
index 0000000..3a320e2
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2009 Francisco Jerez.
+ * 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.
+ *
+ */
+
+#include "nouveau_driver.h"
+#include "nouveau_context.h"
+#include "nouveau_gldefs.h"
+#include "nouveau_class.h"
+#include "nv20_driver.h"
+
+void
+nv20_emit_point_mode(GLcontext *ctx, int emit)
+{
+       struct nouveau_channel *chan = context_chan(ctx);
+       struct nouveau_grobj *kelvin = context_eng3d(ctx);
+
+       BEGIN_RING(chan, kelvin, NV20TCL_POINT_SIZE, 1);
+       if (context_chipset(ctx) >= 0x25)
+               OUT_RINGf(chan, ctx->Point.Size);
+       else
+               OUT_RING(chan, (uint32_t)(ctx->Point.Size * 8));
+}
diff --git a/src/mesa/drivers/dri/nouveau/nv20_state_raster.c b/src/mesa/drivers/dri/nouveau/nv20_state_raster.c
new file mode 100644 (file)
index 0000000..b43b29b
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2009 Francisco Jerez.
+ * 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.
+ *
+ */
+
+#include "nouveau_driver.h"
+#include "nouveau_context.h"
+#include "nouveau_gldefs.h"
+#include "nouveau_class.h"
+#include "nv20_driver.h"
+
+void
+nv20_emit_logic_opcode(GLcontext *ctx, int emit)
+{
+       struct nouveau_channel *chan = context_chan(ctx);
+       struct nouveau_grobj *kelvin = context_eng3d(ctx);
+
+       BEGIN_RING(chan, kelvin, NV20TCL_COLOR_LOGIC_OP_ENABLE, 2);
+       OUT_RING(chan, ctx->Color.ColorLogicOpEnabled ? 1 : 0);
+       OUT_RING(chan, nvgl_logicop_func(ctx->Color.LogicOp));
+}
diff --git a/src/mesa/drivers/dri/nouveau/nv20_state_tex.c b/src/mesa/drivers/dri/nouveau/nv20_state_tex.c
new file mode 100644 (file)
index 0000000..d01e91f
--- /dev/null
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2009 Francisco Jerez.
+ * 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.
+ *
+ */
+
+#include "nouveau_driver.h"
+#include "nouveau_context.h"
+#include "nouveau_gldefs.h"
+#include "nouveau_texture.h"
+#include "nouveau_class.h"
+#include "nouveau_util.h"
+#include "nv20_driver.h"
+
+static uint32_t
+get_tex_format(struct gl_texture_image *ti)
+{
+       switch (ti->TexFormat) {
+       case MESA_FORMAT_ARGB8888:
+               return NV20TCL_TX_FORMAT_FORMAT_A8R8G8B8;
+
+       case MESA_FORMAT_ARGB1555:
+               return NV20TCL_TX_FORMAT_FORMAT_A1R5G5B5;
+
+       case MESA_FORMAT_ARGB4444:
+               return NV20TCL_TX_FORMAT_FORMAT_A4R4G4B4;
+
+       case MESA_FORMAT_RGB565:
+               return NV20TCL_TX_FORMAT_FORMAT_R5G6B5;
+
+       case MESA_FORMAT_A8:
+               return NV20TCL_TX_FORMAT_FORMAT_A8;
+
+       case MESA_FORMAT_L8:
+               return NV20TCL_TX_FORMAT_FORMAT_L8;
+
+       case MESA_FORMAT_CI8:
+               return NV20TCL_TX_FORMAT_FORMAT_INDEX8;
+
+       default:
+               assert(0);
+       }
+}
+
+void
+nv20_emit_tex_obj(GLcontext *ctx, int emit)
+{
+       const int i = emit - NOUVEAU_STATE_TEX_OBJ0;
+       struct nouveau_channel *chan = context_chan(ctx);
+       struct nouveau_grobj *kelvin = context_eng3d(ctx);
+       struct nouveau_bo_context *bctx = context_bctx_i(ctx, TEXTURE, i);
+       const int bo_flags = NOUVEAU_BO_RD | NOUVEAU_BO_GART | NOUVEAU_BO_VRAM;
+       struct gl_texture_object *t;
+       struct nouveau_surface *s;
+       struct gl_texture_image *ti;
+       uint32_t tx_format, tx_filter, tx_wrap, tx_enable;
+
+       if (!ctx->Texture.Unit[i]._ReallyEnabled) {
+               BEGIN_RING(chan, kelvin, NV20TCL_TX_ENABLE(i), 1);
+               OUT_RING(chan, 0);
+
+               context_dirty(ctx, TEX_SHADER);
+               return;
+       }
+
+       t = ctx->Texture.Unit[i]._Current;
+       s = &to_nouveau_texture(t)->surfaces[t->BaseLevel];
+       ti = t->Image[0][t->BaseLevel];
+
+       nouveau_texture_validate(ctx, t);
+
+       /* Recompute the texturing registers. */
+       tx_format = ti->DepthLog2 << 28
+               | ti->HeightLog2 << 24
+               | ti->WidthLog2 << 20
+               | get_tex_format(ti)
+               | NV20TCL_TX_FORMAT_DIMS_2D
+               | NV20TCL_TX_FORMAT_NO_BORDER
+               | 1 << 16;
+
+       tx_wrap = nvgl_wrap_mode(t->WrapR) << 16
+               | nvgl_wrap_mode(t->WrapT) << 8
+               | nvgl_wrap_mode(t->WrapS) << 0;
+
+       tx_filter = nvgl_filter_mode(t->MagFilter) << 24
+               | nvgl_filter_mode(t->MinFilter) << 16;
+
+       tx_enable = NV20TCL_TX_ENABLE_ENABLE
+               | log2i(t->MaxAnisotropy) << 4;
+
+       if (t->MinFilter != GL_NEAREST &&
+           t->MinFilter != GL_LINEAR) {
+               int lod_min = t->MinLod;
+               int lod_max = MIN2(t->MaxLod, t->_MaxLambda);
+               int lod_bias = t->LodBias
+                       + ctx->Texture.Unit[i].LodBias;
+
+               lod_max = CLAMP(lod_max, 0, 15);
+               lod_min = CLAMP(lod_min, 0, 15);
+               lod_bias = CLAMP(lod_bias, 0, 15);
+
+               tx_format |= NV20TCL_TX_FORMAT_MIPMAP;
+               tx_filter |= lod_bias << 8;
+               tx_enable |= lod_min << 26
+                       | lod_max << 14;
+       }
+
+       /* Write it to the hardware. */
+       nouveau_bo_mark(bctx, kelvin, NV20TCL_TX_FORMAT(i),
+                       s->bo, tx_format, 0,
+                       NV20TCL_TX_FORMAT_DMA0,
+                       NV20TCL_TX_FORMAT_DMA1,
+                       bo_flags | NOUVEAU_BO_OR);
+
+       nouveau_bo_markl(bctx, kelvin, NV20TCL_TX_OFFSET(i),
+                        s->bo, 0, bo_flags);
+
+       BEGIN_RING(chan, kelvin, NV20TCL_TX_WRAP(i), 1);
+       OUT_RING(chan, tx_wrap);
+
+       BEGIN_RING(chan, kelvin, NV20TCL_TX_FILTER(i), 1);
+       OUT_RING(chan, tx_filter);
+
+       BEGIN_RING(chan, kelvin, NV20TCL_TX_ENABLE(i), 1);
+       OUT_RING(chan, tx_enable);
+
+       context_dirty(ctx, TEX_SHADER);
+}
+
+void
+nv20_emit_tex_shader(GLcontext *ctx, int emit)
+{
+       struct nouveau_channel *chan = context_chan(ctx);
+       struct nouveau_grobj *kelvin = context_eng3d(ctx);
+       uint32_t tx_shader_op = 0;
+       int i;
+
+       for (i = 0; i < NV20_TEXTURE_UNITS; i++) {
+               if (!ctx->Texture.Unit[i]._ReallyEnabled)
+                       continue;
+
+               tx_shader_op |= NV20TCL_TX_SHADER_OP_TX0_TEXTURE_2D << 5 * i;
+       }
+
+       BEGIN_RING(chan, kelvin, NV20TCL_TX_SHADER_OP, 1);
+       OUT_RING(chan, tx_shader_op);
+}
diff --git a/src/mesa/drivers/dri/nouveau/nv20_state_tnl.c b/src/mesa/drivers/dri/nouveau/nv20_state_tnl.c
new file mode 100644 (file)
index 0000000..0d56606
--- /dev/null
@@ -0,0 +1,396 @@
+/*
+ * Copyright (C) 2009-2010 Francisco Jerez.
+ * 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.
+ *
+ */
+
+#include "nouveau_driver.h"
+#include "nouveau_context.h"
+#include "nouveau_gldefs.h"
+#include "nouveau_util.h"
+#include "nouveau_class.h"
+#include "nv10_driver.h"
+#include "nv20_driver.h"
+
+void
+nv20_emit_clip_plane(GLcontext *ctx, int emit)
+{
+}
+
+static inline unsigned
+get_material_bitmask(unsigned m)
+{
+       unsigned ret = 0;
+
+       if (m & MAT_BIT_FRONT_EMISSION)
+               ret |= NV20TCL_COLOR_MATERIAL_FRONT_EMISSION_COL1;
+       if (m & MAT_BIT_FRONT_AMBIENT)
+               ret |= NV20TCL_COLOR_MATERIAL_FRONT_AMBIENT_COL1;
+       if (m & MAT_BIT_FRONT_DIFFUSE)
+               ret |= NV20TCL_COLOR_MATERIAL_FRONT_DIFFUSE_COL1;
+       if (m & MAT_BIT_FRONT_SPECULAR)
+               ret |= NV20TCL_COLOR_MATERIAL_FRONT_SPECULAR_COL1;
+
+       if (m & MAT_BIT_BACK_EMISSION)
+               ret |= NV20TCL_COLOR_MATERIAL_BACK_EMISSION_COL1;
+       if (m & MAT_BIT_BACK_AMBIENT)
+               ret |= NV20TCL_COLOR_MATERIAL_BACK_AMBIENT_COL1;
+       if (m & MAT_BIT_BACK_DIFFUSE)
+               ret |= NV20TCL_COLOR_MATERIAL_BACK_DIFFUSE_COL1;
+       if (m & MAT_BIT_BACK_SPECULAR)
+               ret |= NV20TCL_COLOR_MATERIAL_BACK_SPECULAR_COL1;
+
+       return ret;
+}
+
+void
+nv20_emit_color_material(GLcontext *ctx, int emit)
+{
+       struct nouveau_channel *chan = context_chan(ctx);
+       struct nouveau_grobj *kelvin = context_eng3d(ctx);
+       unsigned mask = get_material_bitmask(ctx->Light.ColorMaterialBitmask);
+
+       BEGIN_RING(chan, kelvin, NV20TCL_COLOR_MATERIAL, 1);
+       OUT_RING(chan, ctx->Light.ColorMaterialEnabled ? mask : 0);
+}
+
+static unsigned
+get_fog_mode_signed(unsigned mode)
+{
+       switch (mode) {
+       case GL_LINEAR:
+               return NV20TCL_FOG_MODE_LINEAR_SIGNED;
+       case GL_EXP:
+               return NV20TCL_FOG_MODE_EXP_SIGNED;
+       case GL_EXP2:
+               return NV20TCL_FOG_MODE_EXP2_SIGNED;
+       default:
+               assert(0);
+       }
+}
+
+static unsigned
+get_fog_mode_unsigned(unsigned mode)
+{
+       switch (mode) {
+       case GL_LINEAR:
+               return NV20TCL_FOG_MODE_LINEAR_UNSIGNED;
+       case GL_EXP:
+               return NV20TCL_FOG_MODE_EXP_UNSIGNED;
+       case GL_EXP2:
+               return NV20TCL_FOG_MODE_EXP2_UNSIGNED;
+       default:
+               assert(0);
+       }
+}
+
+static unsigned
+get_fog_source(unsigned source)
+{
+       switch (source) {
+       case GL_FOG_COORDINATE_EXT:
+               return NV20TCL_FOG_COORD_FOG;
+       case GL_FRAGMENT_DEPTH_EXT:
+               return NV20TCL_FOG_COORD_DIST_ORTHOGONAL_ABS;
+       default:
+               assert(0);
+       }
+}
+
+void
+nv20_emit_fog(GLcontext *ctx, int emit)
+{
+       struct nouveau_context *nctx = to_nouveau_context(ctx);
+       struct nouveau_channel *chan = context_chan(ctx);
+       struct nouveau_grobj *kelvin = context_eng3d(ctx);
+       struct gl_fog_attrib *f = &ctx->Fog;
+       unsigned source = nctx->fallback == HWTNL ?
+               f->FogCoordinateSource : GL_FOG_COORDINATE_EXT;
+       float k[3];
+
+       nv10_get_fog_coeff(ctx, k);
+
+       BEGIN_RING(chan, kelvin, NV20TCL_FOG_MODE, 4);
+       OUT_RING(chan, (source == GL_FOG_COORDINATE_EXT ?
+                       get_fog_mode_signed(f->Mode) :
+                       get_fog_mode_unsigned(f->Mode)));
+       OUT_RING(chan, get_fog_source(source));
+       OUT_RING(chan, f->Enabled ? 1 : 0);
+       OUT_RING(chan, pack_rgba_f(MESA_FORMAT_RGBA8888_REV, f->Color));
+
+       BEGIN_RING(chan, kelvin, NV20TCL_FOG_EQUATION_CONSTANT, 3);
+       OUT_RINGf(chan, k[0]);
+       OUT_RINGf(chan, k[1]);
+       OUT_RINGf(chan, k[2]);
+}
+
+void
+nv20_emit_light_model(GLcontext *ctx, int emit)
+{
+       struct nouveau_channel *chan = context_chan(ctx);
+       struct nouveau_grobj *kelvin = context_eng3d(ctx);
+       struct gl_lightmodel *m = &ctx->Light.Model;
+
+       BEGIN_RING(chan, kelvin, NV20TCL_SEPARATE_SPECULAR_ENABLE, 1);
+       OUT_RING(chan, m->ColorControl == GL_SEPARATE_SPECULAR_COLOR ? 1 : 0);
+
+       BEGIN_RING(chan, kelvin, NV20TCL_LIGHT_MODEL, 1);
+       OUT_RING(chan, ((m->LocalViewer ?
+                        NV20TCL_LIGHT_MODEL_VIEWER_LOCAL :
+                        NV20TCL_LIGHT_MODEL_VIEWER_NONLOCAL) |
+                       (m->ColorControl == GL_SEPARATE_SPECULAR_COLOR ?
+                        NV20TCL_LIGHT_MODEL_SEPARATE_SPECULAR :
+                        0)));
+
+       BEGIN_RING(chan, kelvin, NV20TCL_LIGHT_MODEL_TWO_SIDE_ENABLE, 1);
+       OUT_RING(chan, ctx->Light.Model.TwoSide ? 1 : 0);
+}
+
+void
+nv20_emit_light_source(GLcontext *ctx, int emit)
+{
+       const int i = emit - NOUVEAU_STATE_LIGHT_SOURCE0;
+       struct nouveau_channel *chan = context_chan(ctx);
+       struct nouveau_grobj *kelvin = context_eng3d(ctx);
+       struct gl_light *l = &ctx->Light.Light[i];
+
+       if (l->_Flags & LIGHT_POSITIONAL) {
+               BEGIN_RING(chan, kelvin, NV20TCL_LIGHT_POSITION_X(i), 3);
+               OUT_RINGf(chan, l->_Position[0]);
+               OUT_RINGf(chan, l->_Position[1]);
+               OUT_RINGf(chan, l->_Position[2]);
+
+               BEGIN_RING(chan, kelvin, NV20TCL_LIGHT_ATTENUATION_CONSTANT(i), 3);
+               OUT_RINGf(chan, l->ConstantAttenuation);
+               OUT_RINGf(chan, l->LinearAttenuation);
+               OUT_RINGf(chan, l->QuadraticAttenuation);
+
+       } else {
+               BEGIN_RING(chan, kelvin, NV20TCL_LIGHT_DIRECTION_X(i), 3);
+               OUT_RINGf(chan, l->_VP_inf_norm[0]);
+               OUT_RINGf(chan, l->_VP_inf_norm[1]);
+               OUT_RINGf(chan, l->_VP_inf_norm[2]);
+
+               BEGIN_RING(chan, kelvin, NV20TCL_LIGHT_HALF_VECTOR_X(i), 3);
+               OUT_RINGf(chan, l->_h_inf_norm[0]);
+               OUT_RINGf(chan, l->_h_inf_norm[1]);
+               OUT_RINGf(chan, l->_h_inf_norm[2]);
+       }
+
+       if (l->_Flags & LIGHT_SPOT) {
+               float k[7];
+
+               nv10_get_spot_coeff(l, k);
+
+               BEGIN_RING(chan, kelvin, NV20TCL_LIGHT_SPOT_CUTOFF_A(i), 7);
+               OUT_RINGf(chan, k[0]);
+               OUT_RINGf(chan, k[1]);
+               OUT_RINGf(chan, k[2]);
+               OUT_RINGf(chan, k[3]);
+               OUT_RINGf(chan, k[4]);
+               OUT_RINGf(chan, k[5]);
+               OUT_RINGf(chan, k[6]);
+       }
+}
+
+#define USE_COLOR_MATERIAL(attr, side)                                 \
+       (ctx->Light.ColorMaterialEnabled &&                             \
+        ctx->Light.ColorMaterialBitmask & (1 << MAT_ATTRIB_##attr(side)))
+
+void
+nv20_emit_material_ambient(GLcontext *ctx, int emit)
+{
+       const int side = emit - NOUVEAU_STATE_MATERIAL_FRONT_AMBIENT;
+       struct nouveau_channel *chan = context_chan(ctx);
+       struct nouveau_grobj *kelvin = context_eng3d(ctx);
+       float (*mat)[4] = ctx->Light.Material.Attrib;
+       uint32_t m_scene[] = { NV20TCL_LIGHT_MODEL_FRONT_AMBIENT_R,
+                              NV20TCL_LIGHT_MODEL_BACK_AMBIENT_R };
+       uint32_t m_factor[] = { NV20TCL_MATERIAL_FACTOR_FRONT_R,
+                             NV20TCL_MATERIAL_FACTOR_BACK_R };
+       float c_scene[3], c_factor[3];
+       struct gl_light *l;
+
+       if (USE_COLOR_MATERIAL(AMBIENT, side)) {
+               COPY_3V(c_scene, mat[MAT_ATTRIB_EMISSION(side)]);
+               COPY_3V(c_factor, ctx->Light.Model.Ambient);
+
+       } else if (USE_COLOR_MATERIAL(EMISSION, side)) {
+               SCALE_3V(c_scene, mat[MAT_ATTRIB_AMBIENT(side)],
+                        ctx->Light.Model.Ambient);
+               ASSIGN_3V(c_factor, 1, 1, 1);
+
+       } else {
+               COPY_3V(c_scene, ctx->Light._BaseColor[side]);
+               ZERO_3V(c_factor);
+       }
+
+       BEGIN_RING(chan, kelvin, m_scene[side], 3);
+       OUT_RINGf(chan, c_scene[0]);
+       OUT_RINGf(chan, c_scene[1]);
+       OUT_RINGf(chan, c_scene[2]);
+
+       if (ctx->Light.ColorMaterialEnabled) {
+               BEGIN_RING(chan, kelvin, m_factor[side], 3);
+               OUT_RINGf(chan, c_factor[0]);
+               OUT_RINGf(chan, c_factor[1]);
+               OUT_RINGf(chan, c_factor[2]);
+       }
+
+       foreach(l, &ctx->Light.EnabledList) {
+               const int i = l - ctx->Light.Light;
+               uint32_t m_light[] = { NV20TCL_LIGHT_FRONT_AMBIENT_R(i),
+                                     NV20TCL_LIGHT_BACK_AMBIENT_R(i) };
+               float *c_light = (USE_COLOR_MATERIAL(AMBIENT, side) ?
+                                 l->Ambient :
+                                 l->_MatAmbient[side]);
+
+               BEGIN_RING(chan, kelvin, m_light[side], 3);
+               OUT_RINGf(chan, c_light[0]);
+               OUT_RINGf(chan, c_light[1]);
+               OUT_RINGf(chan, c_light[2]);
+       }
+}
+
+void
+nv20_emit_material_diffuse(GLcontext *ctx, int emit)
+{
+       const int side = emit - NOUVEAU_STATE_MATERIAL_FRONT_DIFFUSE;
+       struct nouveau_channel *chan = context_chan(ctx);
+       struct nouveau_grobj *kelvin = context_eng3d(ctx);
+       GLfloat (*mat)[4] = ctx->Light.Material.Attrib;
+       uint32_t m_factor[] = { NV20TCL_MATERIAL_FACTOR_FRONT_A,
+                               NV20TCL_MATERIAL_FACTOR_BACK_A };
+       struct gl_light *l;
+
+       BEGIN_RING(chan, kelvin, m_factor[side], 1);
+       OUT_RINGf(chan, mat[MAT_ATTRIB_DIFFUSE(side)][3]);
+
+       foreach(l, &ctx->Light.EnabledList) {
+               const int i = l - ctx->Light.Light;
+               uint32_t m_light[] = { NV20TCL_LIGHT_FRONT_DIFFUSE_R(i),
+                                      NV20TCL_LIGHT_BACK_DIFFUSE_R(i) };
+               float *c_light = (USE_COLOR_MATERIAL(DIFFUSE, side) ?
+                                 l->Diffuse :
+                                 l->_MatDiffuse[side]);
+
+               BEGIN_RING(chan, kelvin, m_light[side], 3);
+               OUT_RINGf(chan, c_light[0]);
+               OUT_RINGf(chan, c_light[1]);
+               OUT_RINGf(chan, c_light[2]);
+       }
+}
+
+void
+nv20_emit_material_specular(GLcontext *ctx, int emit)
+{
+       const int side = emit - NOUVEAU_STATE_MATERIAL_FRONT_SPECULAR;
+       struct nouveau_channel *chan = context_chan(ctx);
+       struct nouveau_grobj *kelvin = context_eng3d(ctx);
+       struct gl_light *l;
+
+       foreach(l, &ctx->Light.EnabledList) {
+               const int i = l - ctx->Light.Light;
+               uint32_t m_light[] = { NV20TCL_LIGHT_FRONT_SPECULAR_R(i),
+                                      NV20TCL_LIGHT_BACK_SPECULAR_R(i) };
+               float *c_light = (USE_COLOR_MATERIAL(SPECULAR, side) ?
+                                 l->Specular :
+                                 l->_MatSpecular[side]);
+
+               BEGIN_RING(chan, kelvin, m_light[side], 3);
+               OUT_RINGf(chan, c_light[0]);
+               OUT_RINGf(chan, c_light[1]);
+               OUT_RINGf(chan, c_light[2]);
+       }
+}
+
+void
+nv20_emit_material_shininess(GLcontext *ctx, int emit)
+{
+       const int side = emit - NOUVEAU_STATE_MATERIAL_FRONT_SHININESS;
+       struct nouveau_channel *chan = context_chan(ctx);
+       struct nouveau_grobj *kelvin = context_eng3d(ctx);
+       float (*mat)[4] = ctx->Light.Material.Attrib;
+       uint32_t mthd[] = { NV20TCL_FRONT_MATERIAL_SHININESS(0),
+                           NV20TCL_BACK_MATERIAL_SHININESS(0) };
+       float k[6];
+
+       nv10_get_shininess_coeff(
+               CLAMP(mat[MAT_ATTRIB_SHININESS(side)][0], 0, 1024),
+               k);
+
+       BEGIN_RING(chan, kelvin, mthd[side], 6);
+       OUT_RINGf(chan, k[0]);
+       OUT_RINGf(chan, k[1]);
+       OUT_RINGf(chan, k[2]);
+       OUT_RINGf(chan, k[3]);
+       OUT_RINGf(chan, k[4]);
+       OUT_RINGf(chan, k[5]);
+}
+
+void
+nv20_emit_modelview(GLcontext *ctx, int emit)
+{
+       struct nouveau_context *nctx = to_nouveau_context(ctx);
+       struct nouveau_channel *chan = context_chan(ctx);
+       struct nouveau_grobj *kelvin = context_eng3d(ctx);
+       GLmatrix *m = ctx->ModelviewMatrixStack.Top;
+
+       if (nctx->fallback != HWTNL)
+               return;
+
+       if (ctx->Light._NeedEyeCoords || ctx->Fog.Enabled) {
+               BEGIN_RING(chan, kelvin, NV20TCL_MODELVIEW0_MATRIX(0), 16);
+               OUT_RINGm(chan, m->m);
+       }
+
+       if (ctx->Light.Enabled) {
+               int i, j;
+
+               BEGIN_RING(chan, kelvin,
+                          NV20TCL_INVERSE_MODELVIEW0_MATRIX(0), 12);
+               for (i = 0; i < 3; i++)
+                       for (j = 0; j < 4; j++)
+                               OUT_RINGf(chan, m->inv[4*i + j]);
+       }
+}
+
+void
+nv20_emit_projection(GLcontext *ctx, int emit)
+{
+       struct nouveau_context *nctx = to_nouveau_context(ctx);
+       struct nouveau_channel *chan = context_chan(ctx);
+       struct nouveau_grobj *kelvin = context_eng3d(ctx);
+       GLmatrix m;
+
+       _math_matrix_ctr(&m);
+       get_viewport_scale(ctx, m.m);
+
+       if (nctx->fallback == HWTNL)
+               _math_matrix_mul_matrix(&m, &m, &ctx->_ModelProjectMatrix);
+
+       BEGIN_RING(chan, kelvin, NV20TCL_PROJECTION_MATRIX(0), 16);
+       OUT_RINGm(chan, m.m);
+
+       _math_matrix_dtr(&m);
+}