Initial revision
authorStephane Marchesin <marchesin@icps.u-strasbg.fr>
Thu, 23 Feb 2006 12:55:56 +0000 (12:55 +0000)
committerStephane Marchesin <marchesin@icps.u-strasbg.fr>
Thu, 23 Feb 2006 12:55:56 +0000 (12:55 +0000)
22 files changed:
src/mesa/drivers/dri/nouveau/Makefile [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_fifo.c [new file with mode: 0644]
src/mesa/drivers/dri/nouveau/nouveau_fifo.h [new file with mode: 0644]
src/mesa/drivers/dri/nouveau/nouveau_ioctl.c [new file with mode: 0644]
src/mesa/drivers/dri/nouveau/nouveau_ioctl.h [new file with mode: 0644]
src/mesa/drivers/dri/nouveau/nouveau_lock.c [new file with mode: 0644]
src/mesa/drivers/dri/nouveau/nouveau_lock.h [new file with mode: 0644]
src/mesa/drivers/dri/nouveau/nouveau_msg.h [new file with mode: 0644]
src/mesa/drivers/dri/nouveau/nouveau_reg.h [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_span.h [new file with mode: 0644]
src/mesa/drivers/dri/nouveau/nouveau_tex.c [new file with mode: 0644]
src/mesa/drivers/dri/nouveau/nouveau_tex.h [new file with mode: 0644]
src/mesa/drivers/dri/nouveau/nouveau_tris.c [new file with mode: 0644]
src/mesa/drivers/dri/nouveau/nouveau_tris.h [new file with mode: 0644]
src/mesa/drivers/dri/nouveau/nv40_tris.c [new file with mode: 0644]
src/mesa/drivers/dri/nouveau/nv40_tris.h [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..02632c4
--- /dev/null
@@ -0,0 +1,30 @@
+# src/mesa/drivers/dri/nouveau/Makefile
+
+TOP = ../../../../..
+include $(TOP)/configs/current
+
+LIBNAME = nouveau_dri.so
+
+MINIGLX_SOURCES = 
+
+DRIVER_SOURCES = \
+       nouveau_context.c        \
+       nouveau_driver.c         \
+       nouveau_fifo.c           \
+       nouveau_ioctl.c          \
+       nouveau_lock.c           \
+       nouveau_span.c           \
+       nouveau_tex.c            \
+       nouveau_tris.c           \
+       nv40_tris.c
+
+C_SOURCES = \
+       $(COMMON_SOURCES) \
+       $(DRIVER_SOURCES) 
+
+ASM_SOURCES = 
+
+
+include ../Makefile.template
+
+symlinks:
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..1a8dc6a
--- /dev/null
@@ -0,0 +1,209 @@
+/**************************************************************************
+
+Copyright 2006 Stephane Marchesin
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+#include "glheader.h"
+#include "context.h"
+#include "simple_list.h"
+#include "imports.h"
+#include "matrix.h"
+#include "swrast/swrast.h"
+#include "swrast_setup/swrast_setup.h"
+#include "array_cache/acache.h"
+
+#include "tnl/tnl.h"
+#include "tnl/t_pipeline.h"
+
+#include "drivers/common/driverfuncs.h"
+
+#include "nouveau_context.h"
+#include "nouveau_ioctl.h"
+#include "nouveau_driver.h"
+//#include "nouveau_state.h"
+#include "nouveau_span.h"
+#include "nouveau_tex.h"
+#include "nv40_tris.h"
+
+#include "vblank.h"
+#include "utils.h"
+#include "texmem.h"
+#include "xmlpool.h" /* for symbolic values of enum-type options */
+
+#ifndef NOUVEAU_DEBUG
+int NOUVEAU_DEBUG = 0;
+#endif
+
+static const struct dri_debug_control debug_control[] =
+{
+       { NULL,    0 }
+};
+
+/* Create the device specific context.
+ */
+GLboolean nouveauCreateContext( const __GLcontextModes *glVisual,
+               __DRIcontextPrivate *driContextPriv,
+               void *sharedContextPrivate )
+{
+       GLcontext *ctx, *shareCtx;
+       __DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv;
+       struct dd_function_table functions;
+       nouveauContextPtr nmesa;
+       nouveauScreenPtr screen;
+       int i;
+
+       /* Allocate the context */
+       nmesa = (nouveauContextPtr) CALLOC( sizeof(*nmesa) );
+       if ( !nmesa )
+               return GL_FALSE;
+
+       /* Init default driver functions then plug in our Radeon-specific functions
+        * (the texture functions are especially important)
+        */
+       _mesa_init_driver_functions( &functions );
+       nouveauDriverInitFunctions( &functions );
+       nouveauIoctlInitFunctions( &functions );
+       nouveauTexInitFunctions( &functions );
+
+       /* Allocate the Mesa context */
+       if (sharedContextPrivate)
+               shareCtx = ((nouveauContextPtr) sharedContextPrivate)->glCtx;
+       else 
+               shareCtx = NULL;
+       nmesa->glCtx = _mesa_create_context(glVisual, shareCtx,
+                       &functions, (void *) nmesa);
+       if (!nmesa->glCtx) {
+               FREE(nmesa);
+               return GL_FALSE;
+       }
+       driContextPriv->driverPrivate = nmesa;
+       ctx = nmesa->glCtx;
+
+       nmesa->driContext = driContextPriv;
+       nmesa->driScreen = sPriv;
+       nmesa->driDrawable = NULL;
+       nmesa->hHWContext = driContextPriv->hHWContext;
+       nmesa->driHwLock = &sPriv->pSAREA->lock;
+       nmesa->driFd = sPriv->fd;
+
+       nmesa->screen = (nouveauScreenPtr)(sPriv->private);
+       screen=nmesa->screen;
+
+       /* Parse configuration files */
+       driParseConfigFiles (&nmesa->optionCache, &screen->optionCache,
+                       screen->driScreen->myNum, "nouveau");
+
+       nmesa->sarea = (drm_nouveau_sarea_t *)((char *)sPriv->pSAREA +
+                       screen->sarea_priv_offset);
+
+
+       nmesa->current_primitive = -1;
+
+       /* Initialize the swrast */
+       _swrast_CreateContext( ctx );
+       _ac_CreateContext( ctx );
+       _tnl_CreateContext( ctx );
+       _swsetup_CreateContext( ctx );
+
+       switch(nmesa->screen->card_type)
+       {
+               case NV_03:
+               case NV_04:
+               case NV_05:
+               case NV_10:
+               case NV_20:
+               case NV_30:
+               default:
+                       break;
+               case NV_40:
+               case G_70:
+                       nv40TriInitFunctions( ctx );
+                       break;
+       }
+       nouveauDDInitStateFuncs( ctx );
+       nouveauSpanInitFunctions( ctx );
+       nouveauDDInitState( nmesa );
+
+       driContextPriv->driverPrivate = (void *)nmesa;
+
+       NOUVEAU_DEBUG = driParseDebugString( getenv( "NOUVEAU_DEBUG" ),
+                       debug_control );
+
+       if (driQueryOptionb(&nmesa->optionCache, "no_rast")) {
+               fprintf(stderr, "disabling 3D acceleration\n");
+               FALLBACK(nmesa, NOUVEAU_FALLBACK_DISABLE, 1);
+       }
+
+       return GL_TRUE;
+}
+
+/* Destroy the device specific context. */
+void nouveauDestroyContext( __DRIcontextPrivate *driContextPriv  )
+{
+       nouveauContextPtr nmesa = (nouveauContextPtr) driContextPriv->driverPrivate;
+
+       assert(nmesa);
+       if ( nmesa ) {
+               /* free the option cache */
+               driDestroyOptionCache (&nmesa->optionCache);
+
+               FREE( nmesa );
+       }
+
+}
+
+
+/* Force the context `c' to be the current context and associate with it
+ * buffer `b'.
+ */
+GLboolean nouveauMakeCurrent( __DRIcontextPrivate *driContextPriv,
+               __DRIdrawablePrivate *driDrawPriv,
+               __DRIdrawablePrivate *driReadPriv )
+{
+       if ( driContextPriv ) {
+               GET_CURRENT_CONTEXT(ctx);
+               nouveauContextPtr oldNOUVEAUCtx = ctx ? NOUVEAU_CONTEXT(ctx) : NULL;
+               nouveauContextPtr newNOUVEAUCtx = (nouveauContextPtr) driContextPriv->driverPrivate;
+
+               driDrawableInitVBlank( driDrawPriv, newNOUVEAUCtx->vblank_flags );
+               newNOUVEAUCtx->driDrawable = driDrawPriv;
+
+               _mesa_make_current( newNOUVEAUCtx->glCtx,
+                               (GLframebuffer *) driDrawPriv->driverPrivate,
+                               (GLframebuffer *) driReadPriv->driverPrivate );
+
+       } else {
+               _mesa_make_current( NULL, NULL, NULL );
+       }
+
+       return GL_TRUE;
+}
+
+
+/* Force the context `c' to be unbound from its buffer.
+ */
+GLboolean nouveauUnbindContext( __DRIcontextPrivate *driContextPriv )
+{
+       return GL_TRUE;
+}
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..d287439
--- /dev/null
@@ -0,0 +1,129 @@
+/**************************************************************************
+
+Copyright 2006 Stephane Marchesin
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+
+
+#ifndef __NOUVEAU_CONTEXT_H__
+#define __NOUVEAU_CONTEXT_H__
+
+#include "dri_util.h"
+#include "drm.h"
+#include "nouveau_drm.h"
+
+#include "mtypes.h"
+#include "tnl/t_vertex.h"
+
+#include "nouveau_reg.h"
+#include "nouveau_screen.h"
+
+#include "xmlconfig.h"
+
+typedef struct nouveau_fifo_t{
+       u_int32_t* buffer;
+       u_int32_t current;
+       u_int32_t put;
+       u_int32_t free;
+       u_int32_t max;
+}
+nouveau_fifo;
+
+#define TAG(x) nouveau##x
+#include "tnl_dd/t_dd_vertex.h"
+#undef TAG
+
+
+typedef void (*nouveau_tri_func)( struct nouveau_context*, 
+               nouveauVertex *,
+               nouveauVertex *,
+               nouveauVertex * );
+
+typedef void (*nouveau_line_func)( struct nouveau_context*, 
+               nouveauVertex *,
+               nouveauVertex * );
+
+typedef void (*nouveau_point_func)( struct nouveau_context*,
+               nouveauVertex * );
+
+
+typedef struct nouveau_context {
+       /* Mesa context */
+       GLcontext *glCtx;
+
+       /* The per-context fifo */
+       nouveau_fifo fifo;
+
+       /* The fifo control regs */
+       volatile unsigned char* fifo_mmio;
+
+       /* The read-only regs */
+       volatile unsigned char* mmio;
+
+       /* The drawing fallbacks */
+       nouveau_tri_func* draw_tri;
+       nouveau_line_func* draw_line;
+       nouveau_point_func* draw_point;
+
+       /* Cliprects information */
+       GLuint numClipRects;
+       drm_clip_rect_t *pClipRects;
+
+       /* The rendering context information */
+       GLenum current_primitive; /* the current primitive enum */
+       GLuint render_inputs; /* the current render inputs */
+
+       nouveauScreenRec *screen;
+       drm_nouveau_sarea_t *sarea;
+
+       __DRIcontextPrivate  *driContext;    /* DRI context */
+       __DRIscreenPrivate   *driScreen;     /* DRI screen */
+       __DRIdrawablePrivate *driDrawable;   /* DRI drawable bound to this ctx */
+
+       drm_context_t hHWContext;
+       drm_hw_lock_t *driHwLock;
+       int driFd;
+
+       /* Configuration cache */
+       driOptionCache optionCache;
+}nouveauContextRec, *nouveauContextPtr;
+
+#define NOUVEAU_CONTEXT(ctx)           ((nouveauContextPtr)(ctx->DriverCtx))
+
+
+extern GLboolean nouveauCreateContext( const __GLcontextModes *glVisual,
+               __DRIcontextPrivate *driContextPriv,
+               void *sharedContextPrivate );
+
+extern void nouveauDestroyContext( __DRIcontextPrivate * );
+
+extern GLboolean nouveauMakeCurrent( __DRIcontextPrivate *driContextPriv,
+               __DRIdrawablePrivate *driDrawPriv,
+               __DRIdrawablePrivate *driReadPriv );
+
+extern GLboolean nouveauUnbindContext( __DRIcontextPrivate *driContextPriv );
+
+
+#endif /* __NOUVEAU_CONTEXT_H__ */
+
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..165fc49
--- /dev/null
@@ -0,0 +1,145 @@
+/**************************************************************************
+
+Copyright 2006 Stephane Marchesin
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+#include "nouveau_context.h"
+#include "nouveau_ioctl.h"
+//#include "nouveau_state.h"
+#include "nouveau_driver.h"
+#include "swrast/swrast.h"
+
+#include "context.h"
+#include "framebuffer.h"
+
+#include "utils.h"
+
+
+/* Return the width and height of the current color buffer */
+static void nouveauGetBufferSize( GLframebuffer *buffer,
+               GLuint *width, GLuint *height )
+{
+       GET_CURRENT_CONTEXT(ctx);
+       nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+
+       LOCK_HARDWARE( nmesa );
+       *width  = nmesa->driDrawable->w;
+       *height = nmesa->driDrawable->h;
+       UNLOCK_HARDWARE( nmesa );
+}
+
+/* glGetString */
+static const GLubyte *nouveauGetString( GLcontext *ctx, GLenum name )
+{
+       nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+       static char buffer[128];
+       const char * card_name = "Unknown";
+       GLuint agp_mode = 0;
+
+       switch ( name ) {
+               case GL_VENDOR:
+                       return (GLubyte *)DRIVER_AUTHOR;
+
+               case GL_RENDERER:
+                       switch(nmesa->screen->card_type)
+                       {
+                               case NV_03:
+                                       card_name="Riva 128";
+                                       break;
+                               case NV_04:
+                                       card_name="TNT";
+                                       break;
+                               case NV_05:
+                                       card_name="TNT2";
+                                       break;
+                               case NV_10:
+                                       card_name="GeForce 1/2/4Mx";
+                                       break;
+                               case NV_20:
+                                       card_name="GeForce 3/4Ti";
+                                       break;
+                               case NV_30:
+                                       card_name="GeForce FX 5x00";
+                                       break;
+                               case NV_40:
+                                       card_name="GeForce FX 6x00";
+                                       break;
+                               case G_70:
+                                       card_name="GeForce FX 7x00";
+                                       break;
+                               default:
+                                       break;
+                       }
+
+                       switch(nmesa->screen->bus_type)
+                       {
+                               case NV_PCI:
+                               case NV_PCIE:
+                               default:
+                                       agp_mode=0;
+                                       break;
+                               case NV_AGP:
+                                       nmesa->screen->agp_mode;
+                                       break;
+                       }
+                       driGetRendererString( buffer, card_name, DRIVER_DATE,
+                                       agp_mode );
+                       return (GLubyte *)buffer;
+               default:
+                       return NULL;
+       }
+}
+
+/* glFlush */
+static void nouveauFlush( GLcontext *ctx )
+{
+       nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+       FIRE_RING( nmesa );
+}
+
+/* glFinish */
+static void nouveauFinish( GLcontext *ctx )
+{
+       nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+       nouveauFlush( ctx );
+       nouveauWaitForIdle( nmesa );
+}
+
+/* glClear */
+static void nouveauClear( GLcontext *ctx, GLbitfield mask, GLboolean all,
+               GLint cx, GLint cy, GLint cw, GLint ch )
+{
+       // XXX we really should do something here...
+}
+
+void nouveauDriverInitFunctions( struct dd_function_table *functions )
+{
+       functions->GetBufferSize        = nouveauGetBufferSize;
+       functions->ResizeBuffers        = _mesa_resize_framebuffer;
+       functions->GetString            = nouveauGetString;
+       functions->Flush                = nouveauFlush;
+       functions->Finish               = nouveauFinish;
+       functions->Clear                = nouveauClear;
+}
+
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_driver.h b/src/mesa/drivers/dri/nouveau/nouveau_driver.h
new file mode 100644 (file)
index 0000000..e1541aa
--- /dev/null
@@ -0,0 +1,39 @@
+/**************************************************************************
+
+Copyright 2006 Stephane Marchesin
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+
+
+#ifndef __NOUVEAU_DRIVER_H__
+#define __NOUVEAU_DRIVER_H__
+
+#define DRIVER_DATE    "20060219"
+#define DRIVER_AUTHOR  "Stephane Marchesin"
+
+extern void nouveauDriverInitFunctions( struct dd_function_table *functions );
+
+
+#endif /* __NOUVEAU_DRIVER_H__ */
+
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_fifo.c b/src/mesa/drivers/dri/nouveau/nouveau_fifo.c
new file mode 100644 (file)
index 0000000..a330d52
--- /dev/null
@@ -0,0 +1,96 @@
+/**************************************************************************
+
+Copyright 2006 Stephane Marchesin
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+
+#include "nouveau_fifo.h"
+#include "vblank.h"
+
+#define RING_SKIPS 8
+
+void WAIT_RING(nouveauContextPtr nmesa,u_int32_t size)
+{
+       u_int32_t fifo_get;
+       while(nmesa->fifo.free < size+1) {
+               fifo_get = NV_FIFO_READ(NV03_FIFO_REGS_DMAGET);
+
+               if(nmesa->fifo.put >= fifo_get) {
+                       nmesa->fifo.free = nmesa->fifo.max - nmesa->fifo.current;
+                       if(nmesa->fifo.free < size+1) {
+                               OUT_RING(NV03_FIFO_CMD_REWIND);                                                 \
+                               if(fifo_get <= RING_SKIPS) {
+                                       if(nmesa->fifo.put <= RING_SKIPS) /* corner case - will be idle */
+                                               NV_FIFO_WRITE(NV03_FIFO_REGS_DMAPUT, RING_SKIPS + 1);
+                                       do { fifo_get = NV_FIFO_READ(NV03_FIFO_REGS_DMAGET); }
+                                       while(fifo_get <= RING_SKIPS);
+                               }
+                               NV03_FIFO_REGS_DMAPUT(NV03_FIFO_REGS_DMAPUT, RING_SKIPS);
+                               nmesa->fifo.current = nmesa->fifo.put = RING_SKIPS;
+                               nmesa->fifo.free = fifo_get - (RING_SKIPS + 1);
+                       }
+               } else 
+                       nmesa->fifo.free = fifo_get - nmesa->fifo.current - 1;
+       }
+}
+
+/* 
+ * Wait for the card to be idle 
+ * XXX we should also wait for an empty fifo
+ */
+void nouveauWaitForIdleLocked(nouveauContextPtr *nmesa)
+{
+       int i,status;
+
+       for(i=0;i<1000000;i++) /* 1 second */
+       {
+               switch(nmesa->screen->card_type)
+               {
+                       case NV_03:
+                               status=NV_READ(NV03_STATUS);
+                               break;
+                       case NV_04:
+                       case NV_05:
+                       case NV_10:
+                       case NV_20:
+                       case NV_30:
+                       case NV_40:
+                       case G_70:
+                       default:
+                               status=NV_READ(NV04_STATUS);
+                               break;
+               }
+               if (status)
+                       return 0;
+               DO_USLEEP(1);
+       }
+}
+
+void nouveauWaitForIdle(nouveauContextPtr *nmesa)
+{
+       LOCK_HARDWARE(nmesa);
+       nouveauWaitForIdleLocked(nmesa);
+       UNLOCK_HARDWARE(nmesa);
+}
+
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_fifo.h b/src/mesa/drivers/dri/nouveau/nouveau_fifo.h
new file mode 100644 (file)
index 0000000..6a21687
--- /dev/null
@@ -0,0 +1,96 @@
+/**************************************************************************
+
+Copyright 2006 Stephane Marchesin
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+
+
+#ifndef __NOUVEAU_FIFO_H__
+#define __NOUVEAU_FIFO_H__
+
+#include "nouveau_context.h"
+
+#define NV_READ(reg) *(volatile u_int32_t *)(nmesa->mmio + (reg))
+
+#define NV_FIFO_READ(reg) *(volatile u_int32_t *)(nmesa->fifo_mmio + (reg))
+#define NV_FIFO_WRITE(reg,value) *(volatile u_int32_t *)(nmesa->fifo_mmio + (reg)) = value;
+
+/* 
+ * Ring/fifo interface
+ *
+ * - Begin a ring section with BEGIN_RING_SIZE (if you know the full size in advance)
+ * - Begin a ring section with BEGIN_RING_PRIM otherwise (and then finish with FINISH_RING_PRIM)
+ * - Output stuff to the ring with either OUT_RINGp (outputs a raw mem chunk), OUT_RING (1 uint32_t) or OUT_RINGf (1 float)
+ * - RING_AVAILABLE returns the available fifo (in uint32_ts)
+ * - RING_AHEAD returns how much ahead of the last submission point we are
+ * - FIRE_RING fire whatever we have that wasn't fired before
+ * - WAIT_RING waits for size (in uint32_ts) to be available in the fifo
+ */
+
+#define OUT_RINGp(ptr,sz) do{                                                  \
+       memcpy(nmesa->fifo.buffer+nmesa->fifo.current,ptr,sz);                  \
+       nmesa->fifo.current+=sz;                                                \
+}while(0)
+
+#define OUT_RING(n) do {                                                       \
+nmesa->fifo.buffer[nmesa->fifo.current++]=n;                                   \
+}while(0)
+
+#define OUT_RINGf(n) do {                                                      \
+*((float*)(nmesa->fifo.buffer+nmesa->fifo.current++))=n;                       \
+}while(0)
+
+extern void WAIT_RING(nouveauContextPtr nmesa,u_int32_t size);
+
+#define BEGIN_RING_PRIM(subchannel,tag,size) do {                                      \
+       if (nmesa->fifo.free<size)                                                      \
+               WAIT_RING(nmesa,(size));                                                \
+       OUT_RING( ((subchannel) << 13) | (tag));                                        \
+}while(0)
+
+#define FINISH_RING_PRIM() do{                                                         \
+       nmesa->fifo.buffer[nmesa->fifo.put]|=((nmesa->fifo.current-nmesa->fifo.put) << 18);             \
+}while(0)
+
+#define BEGIN_RING_SIZE(subchannel,tag,size) do {                                      \
+       if (nmesa->fifo.free<size)                                                      \
+               WAIT_RING(nmesa,(size));                                                \
+       OUT_RING( (size<<18) | ((subchannel) << 13) | (tag));                           \
+}while(0)
+
+#define RING_AVAILABLE() (nmesa->fifo.free-1)
+
+#define RING_AHEAD() ((nmesa->fifo.put<=nmesa->fifo.current)?(nmesa->fifo.current-nmesa->fifo.put):nmesa->fifo.max-nmesa->fifo.put+nmesa->fifo.current)
+
+#define FIRE_RING() do {                                                       \
+       if (nmesa->fifo.current!=nmesa->fifo.put) {\
+               nmesa->fifo.put=nmesa->fifo.current;\
+               NV_FIFO_WRITE(NV03_FIFO_REGS_DMAPUT,nmesa->fifo.put);\
+       }\
+}while(0)
+
+
+#endif /* __NOUVEAU_FIFO_H__ */
+
+
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_ioctl.c b/src/mesa/drivers/dri/nouveau/nouveau_ioctl.c
new file mode 100644 (file)
index 0000000..959c5f4
--- /dev/null
@@ -0,0 +1,53 @@
+/**************************************************************************
+
+Copyright 2006 Stephane Marchesin
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+
+
+#include "nouveau_ioctl.h"
+#include "nouveau_context.h"
+#include "nouveau_msg.h"
+
+// here we call the fifo initialization ioctl and fill in stuff accordingly
+void nouveauIoctlInitFifo()
+{
+       int ret;
+       int fifo_num;
+       __DRIscreenPrivate *sPriv;
+       drm_nouveau_fifo_init_t fifo_init;
+
+       fifo_init.fifo_num=&fifo_num;
+       ret = drmCommandWriteRead(sPriv->fd, DRM_NOUVEAU_FIFO_INIT, &fifo_init, sizeof(fifo_init));
+       if (ret)
+               FATAL("Fifo initialization ioctl failed (returned %d)\n",ret);
+       MESSAGE("Fifo init ok. Got number %d\n",fifo_num);
+       // XXX needs more stuff
+}
+
+void nouveauIoctlInitFunctions( struct dd_function_table *functions )
+{
+       // nothing for now
+}
+
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_ioctl.h b/src/mesa/drivers/dri/nouveau/nouveau_ioctl.h
new file mode 100644 (file)
index 0000000..e6a9a7e
--- /dev/null
@@ -0,0 +1,33 @@
+/**************************************************************************
+
+Copyright 2006 Stephane Marchesin
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+
+#ifndef __NOUVEAU_IOCTL_H__
+#define __NOUVEAU_IOCTL_H__
+
+extern void nouveauIoctlInitFunctions( struct dd_function_table *functions );
+
+#endif /* __NOUVEAU_IOCTL_H__ */
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_lock.c b/src/mesa/drivers/dri/nouveau/nouveau_lock.c
new file mode 100644 (file)
index 0000000..1bd2ee4
--- /dev/null
@@ -0,0 +1,64 @@
+/**************************************************************************
+
+Copyright 2006 Stephane Marchesin
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+
+#include "nouveau_context.h"
+#include "nouveau_lock.h"
+
+#include "drirenderbuffer.h"
+
+
+/* Update the hardware state.  This is called if another context has
+ * grabbed the hardware lock, which includes the X server.  This
+ * function also updates the driver's window state after the X server
+ * moves, resizes or restacks a window -- the change will be reflected
+ * in the drawable position and clip rects.  Since the X server grabs
+ * the hardware lock when it changes the window state, this routine will
+ * automatically be called after such a change.
+ */
+void nouveauGetLock( nouveauContextPtr nmesa, GLuint flags )
+{
+   __DRIdrawablePrivate *dPriv = nmesa->driDrawable;
+   __DRIscreenPrivate *sPriv = nmesa->driScreen;
+   drm_nouveau_sarea_t *sarea = nmesa->sarea;
+   int i;
+
+   drmGetLock( nmesa->driFd, nmesa->hHWContext, flags );
+
+   /* The window might have moved, so we might need to get new clip
+    * rects.
+    *
+    * NOTE: This releases and regrabs the hw lock to allow the X server
+    * to respond to the DRI protocol request for new drawable info.
+    * Since the hardware state depends on having the latest drawable
+    * clip rects, all state checking must be done _after_ this call.
+    */
+   DRI_VALIDATE_DRAWABLE_INFO( sPriv, dPriv );
+
+   nmesa->numClipRects = dPriv->numClipRects;
+   nmesa->pClipRects = dPriv->pClipRects;
+
+}
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_lock.h b/src/mesa/drivers/dri/nouveau/nouveau_lock.h
new file mode 100644 (file)
index 0000000..38bb001
--- /dev/null
@@ -0,0 +1,69 @@
+/**************************************************************************
+
+Copyright 2006 Stephane Marchesin
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+
+#ifndef __NOUVEAU_LOCK_H__
+#define __NOUVEAU_LOCK_H__
+
+#include "nouveau_context.h"
+
+extern void nouveauGetLock( nouveauContextPtr nmesa, GLuint flags );
+
+/*
+ * !!! We may want to separate locks from locks with validation.  This
+ * could be used to improve performance for those things commands that
+ * do not do any drawing !!!
+ */
+
+/* Lock the hardware and validate our state.
+ */
+#define LOCK_HARDWARE( nmesa )                                         \
+   do {                                                                        \
+      char __ret = 0;                                                  \
+      DEBUG_CHECK_LOCK();                                              \
+      DRM_CAS( nmesa->driHwLock, nmesa->hHWContext,                    \
+              (DRM_LOCK_HELD | nmesa->hHWContext), __ret );            \
+      if ( __ret )                                                     \
+        nouveauGetLock( nmesa, 0 );                                    \
+      DEBUG_LOCK();                                                    \
+   } while (0)
+
+/* Unlock the hardware.
+ */
+#define UNLOCK_HARDWARE( nmesa )                                       \
+   do {                                                                        \
+      DRM_UNLOCK( nmesa->driFd,                                                \
+                 nmesa->driHwLock,                                     \
+                 nmesa->hHWContext );                                  \
+      DEBUG_RESET();                                                   \
+   } while (0)
+
+#define DEBUG_LOCK()
+#define DEBUG_RESET()
+#define DEBUG_CHECK_LOCK()
+
+
+#endif /* __NOUVEAU_LOCK_H__ */
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_msg.h b/src/mesa/drivers/dri/nouveau/nouveau_msg.h
new file mode 100644 (file)
index 0000000..7b8f89e
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+Copyright (C) The Weather Channel, Inc.  2002.  All Rights Reserved.
+Copyright 2006 Stephane Marchesin. All Rights Reserved
+
+The Weather Channel (TM) funded Tungsten Graphics to develop the
+initial release of the Radeon 8500 driver under the XFree86 license.
+This notice must be preserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ *   Keith Whitwell <keith@tungstengraphics.com>
+ *   Nicolai Haehnle <prefect_@gmx.net>
+ */
+
+
+#ifndef __NOUVEAU_MSG_H__
+#define __NOUVEAU_MSG_H__
+
+#define WARN_ONCE(a, ...) do {\
+               static int warn##__LINE__=1;\
+               if(warn##__LINE__){\
+                                       fprintf(stderr, "*********************************WARN_ONCE*********************************\n");\
+                                       fprintf(stderr, "File %s function %s line %d\n", __FILE__, __FUNCTION__, __LINE__);\
+                                       fprintf(stderr,  a, ## __VA_ARGS__);\
+                                       fprintf(stderr, "***************************************************************************\n");\
+                                       warn##__LINE__=0;\
+                                       } \
+               }while(0)
+
+#define MESSAGE(a, ...) do{\
+                       fprintf(stderr, "************************************INFO***********************************\n");\
+                       fprintf(stderr, "File %s function %s line %d\n", __FILE__, __FUNCTION__, __LINE__); \
+                       fprintf(stderr,  a, ## __VA_ARGS__);\
+                       fprintf(stderr, "***************************************************************************\n");\
+                       exit(0);\
+               }while(0)
+
+#define FATAL(a, ...) do{\
+                       fprintf(stderr, "***********************************FATAL***********************************\n");\
+                       fprintf(stderr, "File %s function %s line %d\n", __FILE__, __FUNCTION__, __LINE__); \
+                       fprintf(stderr,  a, ## __VA_ARGS__);\
+                       fprintf(stderr, "***************************************************************************\n");\
+                       exit(0);\
+               }while(0)
+
+#endif /* __NOUVEAU_MSG_H__ */
+
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_reg.h b/src/mesa/drivers/dri/nouveau/nouveau_reg.h
new file mode 100644 (file)
index 0000000..8b936a5
--- /dev/null
@@ -0,0 +1,60 @@
+/**************************************************************************
+
+Copyright 2006 Stephane Marchesin
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+
+
+
+#define NV03_BOOT_0                                        0x00100000
+#    define NV03_BOOT_0_RAM_AMOUNT                         0x00000003
+#    define NV03_BOOT_0_RAM_AMOUNT_8MB                     0x00000000
+#    define NV03_BOOT_0_RAM_AMOUNT_2MB                     0x00000001
+#    define NV03_BOOT_0_RAM_AMOUNT_4MB                     0x00000002
+#    define NV03_BOOT_0_RAM_AMOUNT_8MB_SDRAM               0x00000003
+#    define NV04_BOOT_0_RAM_AMOUNT_32MB                    0x00000000
+#    define NV04_BOOT_0_RAM_AMOUNT_4MB                     0x00000001
+#    define NV04_BOOT_0_RAM_AMOUNT_8MB                     0x00000002
+#    define NV04_BOOT_0_RAM_AMOUNT_16MB                    0x00000003
+
+#define NV04_FIFO_DATA                                     0x0010020c
+#    define NV10_FIFO_DATA_RAM_AMOUNT_MB_MASK              0xfff00000
+#    define NV10_FIFO_DATA_RAM_AMOUNT_MB_SHIFT             20
+
+#define NV03_STATUS                                        0x004006b0
+#define NV04_STATUS                                        0x00400700
+
+#define NV03_FIFO_SIZE                                     0x8000
+// NV10 maybe has 12 fifos
+// NV40 probably has 16 fifos
+#define NV03_FIFO_NUMBER                                   8
+#define NV03_FIFO_REGS_SIZE                                0x10000
+#    define NV03_FIFO_REGS_DMAPUT                          0x00000040
+#    define NV03_FIFO_REGS_DMAGET                          0x00000044
+
+/* Fifo commands. These are not regs, neither masks */
+#define NV03_FIFO_CMD_JUMP                                 0x20000000
+#define NV03_FIFO_CMD_JUMP_OFFSET_MASK                     0x1ffffffc
+#define NV03_FIFO_CMD_REWIND                               (NV03_FIFO_CMD_JUMP | (0 & NV03_FIFO_CMD_JUMP_OFFSET_MASK))
+
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..b8e8bfc
--- /dev/null
@@ -0,0 +1,55 @@
+/**************************************************************************
+
+Copyright 2006 Stephane Marchesin
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+
+#ifndef __NOUVEAU_SCREEN_H__
+#define __NOUVEAU_SCREEN_H__
+
+#include "xmlconfig.h"
+
+typedef struct {
+       u_int32_t card_type;
+       u_int32_t bus_type;
+       u_int32_t agp_mode;
+
+       GLuint frontOffset;
+       GLuint frontPitch;
+       GLuint backOffset;
+       GLuint backPitch;
+
+       GLuint depthOffset;
+       GLuint depthPitch;
+       GLuint spanOffset;
+
+       __DRIscreenPrivate *driScreen;
+
+       /* Configuration cache with default values for all contexts */
+       driOptionCache optionCache;
+
+} nouveauScreenRec, *nouveauScreenPtr;
+
+
+#endif /* __NOUVEAU_SCREEN_H__ */
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_span.c b/src/mesa/drivers/dri/nouveau/nouveau_span.c
new file mode 100644 (file)
index 0000000..f990a89
--- /dev/null
@@ -0,0 +1,121 @@
+/**************************************************************************
+
+Copyright 2006 Stephane Marchesin
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+
+#include "nouveau_context.h"
+#include "nouveau_span.h"
+#include "nouveau_fifo.h"
+
+#include "swrast/swrast.h"
+
+#define HAVE_HW_DEPTH_SPANS    0
+#define HAVE_HW_DEPTH_PIXELS   0
+#define HAVE_HW_STENCIL_SPANS  0
+#define HAVE_HW_STENCIL_PIXELS 0
+
+#define LOCAL_VARS                                                     \
+   nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);                     \
+   __DRIscreenPrivate *sPriv = nmesa->driScreen;                       \
+   __DRIdrawablePrivate *dPriv = nmesa->driDrawable;                   \
+   driRenderbuffer *drb = (driRenderbuffer *) rb;                      \
+   GLuint height = dPriv->h;                                           \
+   GLuint p;                                                           \
+   (void) p;
+
+#define Y_FLIP( _y )            (height - _y - 1)
+
+#define HW_LOCK()
+
+#define HW_UNLOCK()
+
+
+
+/* ================================================================
+ * Color buffers
+ */
+
+/* RGB565 */ 
+#define SPANTMP_PIXEL_FMT GL_RGB
+#define SPANTMP_PIXEL_TYPE GL_UNSIGNED_SHORT_5_6_5
+
+#define TAG(x)    nouveau##x##_RGB565
+#define TAG2(x,y) nouveau##x##_RGB565##y
+#define GET_PTR(X,Y) (sPriv->pFB + drb->flippedOffset          \
+     + ((dPriv->y + (Y)) * drb->flippedPitch + (dPriv->x + (X))) * drb->cpp)
+#include "spantmp2.h"
+
+
+/* ARGB8888 */
+#define SPANTMP_PIXEL_FMT GL_BGRA
+#define SPANTMP_PIXEL_TYPE GL_UNSIGNED_INT_8_8_8_8_REV
+
+#define TAG(x)    nouveau##x##_ARGB8888
+#define TAG2(x,y) nouveau##x##_ARGB8888##y
+#define GET_PTR(X,Y) (sPriv->pFB + drb->flippedOffset          \
+     + ((dPriv->y + (Y)) * drb->flippedPitch + (dPriv->x + (X))) * drb->cpp)
+#include "spantmp2.h"
+
+static void
+nouveauSpanRenderStart( GLcontext *ctx )
+{
+   nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+   FIRE_RING();
+   LOCK_HARDWARE(nmesa);
+   nouveauWaitForIdleLocked( nmesa );
+}
+
+static void
+nouveauSpanRenderFinish( GLcontext *ctx )
+{
+   nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+   _swrast_flush( ctx );
+   nouveauWaitForIdleLocked( nmesa );
+   UNLOCK_HARDWARE( nmesa );
+}
+
+void nouveauSpanInitFunctions( GLcontext *ctx )
+{
+   struct swrast_device_driver *swdd = _swrast_GetDeviceDriverReference(ctx);
+   swdd->SpanRenderStart       = nouveauSpanRenderStart;
+   swdd->SpanRenderFinish      = nouveauSpanRenderFinish;
+}
+
+
+/**
+ * Plug in the Get/Put routines for the given driRenderbuffer.
+ */
+void
+nouveauSpanSetFunctions(driRenderbuffer *drb, const GLvisual *vis)
+{
+   if (drb->Base.InternalFormat == GL_RGBA) {
+      if (vis->redBits == 5 && vis->greenBits == 6 && vis->blueBits == 5) {
+         nouveauInitPointers_RGB565(&drb->Base);
+      }
+      else {
+         nouveauInitPointers_ARGB8888(&drb->Base);
+      }
+   }
+}
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_span.h b/src/mesa/drivers/dri/nouveau/nouveau_span.h
new file mode 100644 (file)
index 0000000..f5e5733
--- /dev/null
@@ -0,0 +1,38 @@
+/**************************************************************************
+
+Copyright 2006 Stephane Marchesin
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+
+
+#ifndef __NOUVEAU_SPAN_H__
+#define __NOUVEAU_SPAN_H__
+
+#include "drirenderbuffer.h"
+
+extern void nouveauSpanInitFunctions( GLcontext *ctx );
+extern void nouveauSpanSetFunctions(driRenderbuffer *rb, const GLvisual *vis);
+
+#endif /* __NOUVEAU_SPAN_H__ */
+
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_tex.c b/src/mesa/drivers/dri/nouveau/nouveau_tex.c
new file mode 100644 (file)
index 0000000..e3160b2
--- /dev/null
@@ -0,0 +1,49 @@
+/**************************************************************************
+
+Copyright 2006 Stephane Marchesin
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+
+#include "nouveau_tex.h"
+
+// XXX needs some love
+void nouveauInitTextureFuncs( struct dd_function_table *functions )
+{
+/*
+   functions->TexEnv                   = nouveauTexEnv;
+   functions->ChooseTextureFormat      = nouveauChooseTextureFormat;
+   functions->TexImage1D               = nouveauTexImage1D;
+   functions->TexSubImage1D            = nouveauTexSubImage1D;
+   functions->TexImage2D               = nouveauTexImage2D;
+   functions->TexSubImage2D            = nouveauTexSubImage2D;
+   functions->TexParameter             = nouveauTexParameter;
+   functions->BindTexture              = nouveauBindTexture;
+   functions->NewTextureObject         = nouveauNewTextureObject;
+   functions->DeleteTexture            = nouveauDeleteTexture;
+   functions->IsTextureResident                = driIsTextureResident;
+
+   driInitTextureFormats();
+*/
+}
+
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_tex.h b/src/mesa/drivers/dri/nouveau/nouveau_tex.h
new file mode 100644 (file)
index 0000000..c415dc2
--- /dev/null
@@ -0,0 +1,33 @@
+/**************************************************************************
+
+Copyright 2006 Stephane Marchesin
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+
+#ifndef __NOUVEAU_TEX_H__
+#define __NOUVEAU_TEX_H__
+
+extern void nouveauTexInitFunctions( struct dd_function_table *functions );
+
+#endif /* __NOUVEAU_TEX_H__ */
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_tris.c b/src/mesa/drivers/dri/nouveau/nouveau_tris.c
new file mode 100644 (file)
index 0000000..7707763
--- /dev/null
@@ -0,0 +1,126 @@
+/**************************************************************************
+
+Copyright 2006 Stephane Marchesin
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+#include "nouveau_context.h"
+
+/* Common tri functions */
+
+/* The fallbacks */
+void nouveau_fallback_tri(struct nouveau_context *nmesa,
+               nouveauVertex *v0,
+               nouveauVertex *v1,
+               nouveauVertex *v2)
+{    
+       GLcontext *ctx = nmesa->glCtx;
+       SWvertex v[3];
+       _swsetup_Translate(ctx, v0, &v[0]);
+       _swsetup_Translate(ctx, v1, &v[1]);
+       _swsetup_Translate(ctx, v2, &v[2]);
+       nouveauSpanRenderStart( ctx );
+       _swrast_Triangle(ctx, &v[0], &v[1], &v[2]);
+       nouveauSpanRenderFinish( ctx );
+}
+
+
+void nouveau_fallback_line(struct nouveau_context *nmesa,
+               nouveauVertex *v0,
+               nouveauVertex *v1)
+{
+       GLcontext *ctx = nmesa->glCtx;
+       SWvertex v[2];
+       _swsetup_Translate(ctx, v0, &v[0]);
+       _swsetup_Translate(ctx, v1, &v[1]);
+       nouveauSpanRenderStart( ctx );
+       _swrast_Line(ctx, &v[0], &v[1]);
+       nouveauSpanRenderFinish( ctx );
+}
+
+
+void nouveau_fallback_point(struct nouveau_context *nmesa,
+               nouveauVertex *v0)
+{
+       GLcontext *ctx = nmesa->glCtx;
+       SWvertex v[1];
+       _swsetup_Translate(ctx, v0, &v[0]);
+       nouveauSpanRenderStart( ctx );
+       _swrast_Point(ctx, &v[0]);
+       nouveauSpanRenderFinish( ctx );
+}
+
+
+void nouveauFallback(struct nouveau_context *nmesa, GLuint bit, GLboolean mode)
+{
+       GLcontext *ctx = nmesa->glCtx;
+       TNLcontext *tnl = TNL_CONTEXT(ctx);
+       GLuint oldfallback = nmesa->Fallback;
+
+       if (mode) {
+               nmesa->Fallback |= bit;
+               if (oldfallback == 0) {
+                       nv40FinishPrimitive(nmesa);
+
+                       _swsetup_Wakeup(ctx);
+                       nmesa->renderIndex = ~0;
+               }
+       }
+       else {
+               nmesa->Fallback &= ~bit;
+               if (oldfallback == bit) {
+                       _swrast_flush( ctx );
+
+                       tnl->Driver.Render.Start = nouveauRenderStart;
+                       tnl->Driver.Render.PrimitiveNotify = nouveauRenderPrimitive;
+                       tnl->Driver.Render.Finish = nouveauRenderFinish;
+
+                       tnl->Driver.Render.BuildVertices = _tnl_build_vertices;
+                       tnl->Driver.Render.CopyPV = _tnl_copy_pv;
+                       tnl->Driver.Render.Interp = _tnl_interp;
+                       tnl->Driver.Render.ResetLineStipple = nouveauResetLineStipple;
+
+                       _tnl_invalidate_vertex_state( ctx, ~0 );
+                       _tnl_invalidate_vertices( ctx, ~0 );
+                       _tnl_install_attrs( ctx, 
+                                       nmesa->vertex_attrs, 
+                                       nmesa->vertex_attr_count,
+                                       nmesa->ViewportMatrix.m, 0 ); 
+               }
+       }    
+}
+
+
+void nouveauRunPipeline( GLcontext *ctx )
+{
+       struct nouveau_context *vmesa = NOUVEAU_CONTEXT(ctx);
+
+       if (vmesa->newState) {
+               vmesa->newRenderState |= vmesa->newState;
+               nouveauValidateState( ctx );
+       }
+
+       _tnl_run_pipeline( ctx );
+}
+
+
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_tris.h b/src/mesa/drivers/dri/nouveau/nouveau_tris.h
new file mode 100644 (file)
index 0000000..4d9de53
--- /dev/null
@@ -0,0 +1,52 @@
+/**************************************************************************
+
+Copyright 2006 Stephane Marchesin
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+
+
+#ifndef __NOUVEAU_TRIS_H__
+#define __NOUVEAU_TRIS_H__
+
+#include "nouveau_context.h"
+
+extern void nouveau_fallback_tri(struct nouveau_context *nmesa,
+               nouveauVertex *v0,
+               nouveauVertex *v1,
+               nouveauVertex *v2);
+
+extern void nouveau_fallback_line(struct nouveau_context *nmesa,
+               nouveauVertex *v0,
+               nouveauVertex *v1);
+
+extern void nouveau_fallback_point(struct nouveau_context *nmesa, 
+               nouveauVertex *v0);
+
+extern void nouveauFallback(struct nouveau_context *nmesa, GLuint bit, GLboolean mode);
+
+extern void nouveauRunPipeline( GLcontext *ctx );
+
+#endif /* __NOUVEAU_TRIS_H__ */
+
+
diff --git a/src/mesa/drivers/dri/nouveau/nv40_tris.c b/src/mesa/drivers/dri/nouveau/nv40_tris.c
new file mode 100644 (file)
index 0000000..6550928
--- /dev/null
@@ -0,0 +1,738 @@
+/*
+ * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
+ * Copyright 2006 Stephane Marchesin. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sub license,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <stdio.h>
+#include <math.h>
+
+#include "glheader.h"
+#include "context.h"
+#include "mtypes.h"
+#include "macros.h"
+#include "colormac.h"
+#include "enums.h"
+
+#include "swrast/swrast.h"
+#include "swrast_setup/swrast_setup.h"
+#include "tnl/t_context.h"
+#include "tnl/t_pipeline.h"
+
+#include "nouveau_tris.h"
+#include "nv40_tris.h"
+#include "nouveau_context.h"
+#include "nouveau_state.h"
+#include "nouveau_span.h"
+#include "nouveau_ioctl.h"
+#include "nouveau_3d_reg.h"
+#include "nouveau_tex.h"
+
+/* hack for now */
+#define channel 1
+
+
+/***********************************************************************
+ *                    Emit primitives as inline vertices               *
+ ***********************************************************************/
+#define LINE_FALLBACK (0)
+#define POINT_FALLBACK (0)
+#define TRI_FALLBACK (0)
+#define ANY_FALLBACK_FLAGS (POINT_FALLBACK|LINE_FALLBACK|TRI_FALLBACK)
+#define ANY_RASTER_FLAGS (DD_TRI_LIGHT_TWOSIDE|DD_TRI_OFFSET|DD_TRI_UNFILLED)
+
+
+#define COPY_DWORDS(vb, vertsize, v)           \
+       do {                                    \
+               int j;                                  \
+               for (j = 0; j < vertsize; j++)          \
+               vb[j] = ((GLuint *)v)[j];               \
+               vb += vertsize;                         \
+       } while (0)
+#endif
+
+/* the free room we want before we start a vertex batch */
+#define NV40_MIN_PRIM_SIZE (32/4)
+
+static inline void nv40StartPrimitive(struct nouveau_context* nmesa)
+{
+       BEGIN_RING_SIZE(channel,0x1808,1);
+       OUT_RING(nmesa->current_primitive);
+       BEGIN_RING_PRIM(channel,0x1818,NV40_MIN_PRIM_SIZE);
+}
+
+static inline void nv40FinishPrimitive(struct nouveau_context *nmesa)
+{
+       FINISH_RING_PRIM();
+       BEGIN_RING_SIZE(channel,0x1808,1);
+       OUT_RING(0x0);
+       FIRE_RING();
+}
+
+
+static inline void nv40ExtendPrimitive(struct nouveau_context* nmesa, int size)
+{
+       /* when the fifo has enough stuff (2048 bytes) or there is not enough room, fire */
+       if ((RING_AHEAD()>=2048/4)||(RING_AVAILABLE()<size/4))
+       {
+               nv40FinishPrimitive(nmesa);
+               nv40StartPrimitive(nmesa);
+       }
+
+       /* make sure there's enough room. if not, wait */
+       if (RING_AVAILABLE()<size/4)
+       {
+               WAIT_RING(nmesa,size);
+       }
+}
+
+static inline void nv40_draw_quad(struct nouveau_context *nmesa,
+               nouveauVertexPtr v0,
+               nouveauVertexPtr v1,
+               nouveauVertexPtr v2,
+               nouveauVertexPtr v3)
+{
+       GLuint vertsize = nmesa->vertexSize;
+       GLuint *vb = nv40ExtendPrimitive(nmesa, 4 * 4 * vertsize);
+
+       COPY_DWORDS(vb, vertsize, v0);
+       COPY_DWORDS(vb, vertsize, v1);
+       COPY_DWORDS(vb, vertsize, v2);
+       COPY_DWORDS(vb, vertsize, v3);
+}
+
+static inline void nv40_draw_triangle(struct nouveau_context *nmesa,
+               nouveauVertexPtr v0,
+               nouveauVertexPtr v1,
+               nouveauVertexPtr v2)
+{
+       GLuint vertsize = nmesa->vertexSize;
+       GLuint *vb = nv40ExtendPrimitive(nmesa, 3 * 4 * vertsize);
+
+       COPY_DWORDS(vb, vertsize, v0);
+       COPY_DWORDS(vb, vertsize, v1);
+       COPY_DWORDS(vb, vertsize, v2);
+}
+
+static inline void nouveau_draw_line(struct nouveau_context *nmesa,
+               nouveauVertexPtr v0,
+               nouveauVertexPtr v1)
+{
+       GLuint vertsize = nmesa->vertexSize;
+       GLuint *vb = nv40ExtendPrimitive(nmesa, 2 * 4 * vertsize);
+       COPY_DWORDS(vb, vertsize, v0);
+       COPY_DWORDS(vb, vertsize, v1);
+}
+
+static inline void nouveau_draw_point(struct nouveau_context *nmesa,
+               nouveauVertexPtr v0)
+{
+       GLuint vertsize = nmesa->vertexSize;
+       GLuint *vb = nv40ExtendPrimitive(nmesa, 4 * vertsize);
+       COPY_DWORDS(vb, vertsize, v0);
+}
+
+
+/***********************************************************************
+ *          Macros for nouveau_dd_tritmp.h to draw basic primitives        *
+ ***********************************************************************/
+
+#define TRI(a, b, c)                                \
+       do {                                            \
+               if (DO_FALLBACK)                            \
+               nmesa->draw_tri(nmesa, a, b, c);         \
+               else                                        \
+               nouveau_draw_triangle(nmesa, a, b, c);      \
+       } while (0)
+
+#define QUAD(a, b, c, d)                            \
+       do {                                            \
+               if (DO_FALLBACK) {                          \
+                       nmesa->draw_tri(nmesa, a, b, d);         \
+                       nmesa->draw_tri(nmesa, b, c, d);         \
+               }                                           \
+               else                                        \
+               nouveau_draw_quad(nmesa, a, b, c, d);       \
+       } while (0)
+
+#define LINE(v0, v1)                                \
+       do {                                            \
+               if (DO_FALLBACK)                            \
+               nmesa->draw_line(nmesa, v0, v1);         \
+               else                                        \
+               nouveau_draw_line(nmesa, v0, v1);           \
+       } while (0)
+
+#define POINT(v0)                                    \
+       do {                                             \
+               if (DO_FALLBACK)                             \
+               nmesa->draw_point(nmesa, v0);             \
+               else                                         \
+               nouveau_draw_point(nmesa, v0);               \
+       } while (0)
+
+
+/***********************************************************************
+ *              Build render functions from dd templates               *
+ ***********************************************************************/
+
+#define NOUVEAU_OFFSET_BIT         0x01
+#define NOUVEAU_TWOSIDE_BIT        0x02
+#define NOUVEAU_UNFILLED_BIT       0x04
+#define NOUVEAU_FALLBACK_BIT       0x08
+#define NOUVEAU_MAX_TRIFUNC        0x10
+
+
+static struct {
+       tnl_points_func          points;
+       tnl_line_func            line;
+       tnl_triangle_func        triangle;
+       tnl_quad_func            quad;
+} rast_tab[NOUVEAU_MAX_TRIFUNC + 1];
+
+
+#define DO_FALLBACK (IND & NOUVEAU_FALLBACK_BIT)
+#define DO_OFFSET   (IND & NOUVEAU_OFFSET_BIT)
+#define DO_UNFILLED (IND & NOUVEAU_UNFILLED_BIT)
+#define DO_TWOSIDE  (IND & NOUVEAU_TWOSIDE_BIT)
+#define DO_FLAT      0
+#define DO_TRI       1
+#define DO_QUAD      1
+#define DO_LINE      1
+#define DO_POINTS    1
+#define DO_FULL_QUAD 1
+
+#define HAVE_RGBA         1
+#define HAVE_SPEC         1
+#define HAVE_BACK_COLORS  0
+#define HAVE_HW_FLATSHADE 1
+#define VERTEX            nouveauVertex
+#define TAB               rast_tab
+
+/* Only used to pull back colors into vertices (ie, we know color is
+ * floating point).
+ */
+#define NOUVEAU_COLOR(dst, src)                     \
+       do {                                        \
+               dst[0] = src[2];                        \
+               dst[1] = src[1];                        \
+               dst[2] = src[0];                        \
+               dst[3] = src[3];                        \
+       } while (0)
+
+#define NOUVEAU_SPEC(dst, src)                      \
+       do {                                        \
+               dst[0] = src[2];                        \
+               dst[1] = src[1];                        \
+               dst[2] = src[0];                        \
+       } while (0)
+
+
+#define DEPTH_SCALE nmesa->polygon_offset_scale
+#define UNFILLED_TRI unfilled_tri
+#define UNFILLED_QUAD unfilled_quad
+#define VERT_X(_v) _v->v.x
+#define VERT_Y(_v) _v->v.y
+#define VERT_Z(_v) _v->v.z
+#define AREA_IS_CCW(a) (a > 0)
+#define GET_VERTEX(e) (nmesa->verts + (e * nmesa->vertexSize * sizeof(int)))
+
+#define VERT_SET_RGBA( v, c )                                          \
+       do {                                                            \
+               nouveau_color_t *color = (nouveau_color_t *)&((v)->ui[coloroffset]);    \
+               UNCLAMPED_FLOAT_TO_UBYTE(color->red, (c)[0]);           \
+               UNCLAMPED_FLOAT_TO_UBYTE(color->green, (c)[1]);         \
+               UNCLAMPED_FLOAT_TO_UBYTE(color->blue, (c)[2]);          \
+               UNCLAMPED_FLOAT_TO_UBYTE(color->alpha, (c)[3]);         \
+       } while (0)
+
+#define VERT_COPY_RGBA( v0, v1 ) v0->ui[coloroffset] = v1->ui[coloroffset]
+
+#define VERT_SET_SPEC( v, c )                                  \
+       do {                                                            \
+               if (specoffset) {                                               \
+                       nouveau_color_t *color = (nouveau_color_t *)&((v)->ui[specoffset]);     \
+                       UNCLAMPED_FLOAT_TO_UBYTE(color->red, (c)[0]);           \
+                       UNCLAMPED_FLOAT_TO_UBYTE(color->green, (c)[1]);         \
+                       UNCLAMPED_FLOAT_TO_UBYTE(color->blue, (c)[2]);          \
+               }                                                               \
+       } while (0)
+#define VERT_COPY_SPEC( v0, v1 )                       \
+       do {                                                    \
+               if (specoffset) {                                       \
+                       v0->ub4[specoffset][0] = v1->ub4[specoffset][0];        \
+                       v0->ub4[specoffset][1] = v1->ub4[specoffset][1];        \
+                       v0->ub4[specoffset][2] = v1->ub4[specoffset][2];        \
+               }                                                       \
+       } while (0)
+
+
+#define VERT_SAVE_RGBA( idx )    color[idx] = v[idx]->ui[coloroffset]
+#define VERT_RESTORE_RGBA( idx ) v[idx]->ui[coloroffset] = color[idx]
+#define VERT_SAVE_SPEC( idx )    if (specoffset) spec[idx] = v[idx]->ui[specoffset]
+#define VERT_RESTORE_SPEC( idx ) if (specoffset) v[idx]->ui[specoffset] = spec[idx]
+
+
+#define LOCAL_VARS(n)                                                   \
+       struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx);                             \
+GLuint color[n], spec[n];                                           \
+GLuint coloroffset = nmesa->coloroffset;              \
+GLuint specoffset = nmesa->specoffset;                       \
+(void)color; (void)spec; (void)coloroffset; (void)specoffset;
+
+
+/***********************************************************************
+ *                Helpers for rendering unfilled primitives            *
+ ***********************************************************************/
+
+#define RASTERIZE(x) nv40RasterPrimitive( ctx, x, x )
+#define RENDER_PRIMITIVE nmesa->renderPrimitive
+#define TAG(x) x
+#define IND NOUVEAU_FALLBACK_BIT
+#include "tnl_dd/t_dd_unfilled.h"
+#undef IND
+#undef RASTERIZE
+
+/***********************************************************************
+ *                      Generate GL render functions                   *
+ ***********************************************************************/
+#define RASTERIZE(x)
+
+#define IND (0)
+#define TAG(x) x
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (NOUVEAU_OFFSET_BIT)
+#define TAG(x) x##_offset
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (NOUVEAU_TWOSIDE_BIT)
+#define TAG(x) x##_twoside
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (NOUVEAU_TWOSIDE_BIT|NOUVEAU_OFFSET_BIT)
+#define TAG(x) x##_twoside_offset
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (NOUVEAU_UNFILLED_BIT)
+#define TAG(x) x##_unfilled
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (NOUVEAU_OFFSET_BIT|NOUVEAU_UNFILLED_BIT)
+#define TAG(x) x##_offset_unfilled
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (NOUVEAU_TWOSIDE_BIT|NOUVEAU_UNFILLED_BIT)
+#define TAG(x) x##_twoside_unfilled
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (NOUVEAU_TWOSIDE_BIT|NOUVEAU_OFFSET_BIT|NOUVEAU_UNFILLED_BIT)
+#define TAG(x) x##_twoside_offset_unfilled
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (NOUVEAU_FALLBACK_BIT)
+#define TAG(x) x##_fallback
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (NOUVEAU_OFFSET_BIT|NOUVEAU_FALLBACK_BIT)
+#define TAG(x) x##_offset_fallback
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (NOUVEAU_TWOSIDE_BIT|NOUVEAU_FALLBACK_BIT)
+#define TAG(x) x##_twoside_fallback
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (NOUVEAU_TWOSIDE_BIT|NOUVEAU_OFFSET_BIT|NOUVEAU_FALLBACK_BIT)
+#define TAG(x) x##_twoside_offset_fallback
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (NOUVEAU_UNFILLED_BIT|NOUVEAU_FALLBACK_BIT)
+#define TAG(x) x##_unfilled_fallback
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (NOUVEAU_OFFSET_BIT|NOUVEAU_UNFILLED_BIT|NOUVEAU_FALLBACK_BIT)
+#define TAG(x) x##_offset_unfilled_fallback
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (NOUVEAU_TWOSIDE_BIT|NOUVEAU_UNFILLED_BIT|NOUVEAU_FALLBACK_BIT)
+#define TAG(x) x##_twoside_unfilled_fallback
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (NOUVEAU_TWOSIDE_BIT|NOUVEAU_OFFSET_BIT|NOUVEAU_UNFILLED_BIT| \
+               NOUVEAU_FALLBACK_BIT)
+#define TAG(x) x##_twoside_offset_unfilled_fallback
+#include "tnl_dd/t_dd_tritmp.h"
+
+
+/* Catchall case for flat, separate specular triangles */
+#undef  DO_FALLBACK
+#undef  DO_OFFSET
+#undef  DO_UNFILLED
+#undef  DO_TWOSIDE
+#undef  DO_FLAT
+#define DO_FALLBACK (0)
+#define DO_OFFSET   (ctx->_TriangleCaps & DD_TRI_OFFSET)
+#define DO_UNFILLED (ctx->_TriangleCaps & DD_TRI_UNFILLED)
+#define DO_TWOSIDE  (ctx->_TriangleCaps & DD_TRI_LIGHT_TWOSIDE)
+#define DO_FLAT     1
+#define TAG(x) x##_flat_specular
+#define IND NOUVEAU_MAX_TRIFUNC
+#include "tnl_dd/t_dd_tritmp.h"
+
+
+static void init_rast_tab(void)
+{
+       init();
+       init_offset();
+       init_twoside();
+       init_twoside_offset();
+       init_unfilled();
+       init_offset_unfilled();
+       init_twoside_unfilled();
+       init_twoside_offset_unfilled();
+       init_fallback();
+       init_offset_fallback();
+       init_twoside_fallback();
+       init_twoside_offset_fallback();
+       init_unfilled_fallback();
+       init_offset_unfilled_fallback();
+       init_twoside_unfilled_fallback();
+       init_twoside_offset_unfilled_fallback();
+
+       init_flat_specular();   /* special! */
+}
+
+
+/**********************************************************************/
+/*               Render unclipped begin/end objects                   */
+/**********************************************************************/
+#define IND 0
+#define V(x) (nouveauVertex *)(vertptr + ((x) * vertsize * sizeof(int)))
+#define RENDER_POINTS(start, count)   \
+       for (; start < count; start++) POINT(V(ELT(start)));
+#define RENDER_LINE(v0, v1)         LINE(V(v0), V(v1))
+#define RENDER_TRI( v0, v1, v2)     TRI( V(v0), V(v1), V(v2))
+#define RENDER_QUAD(v0, v1, v2, v3) QUAD(V(v0), V(v1), V(v2), V(v3))
+#define INIT(x) nv40RasterPrimitive(ctx, x, x)
+#undef LOCAL_VARS
+#define LOCAL_VARS                                              \
+       struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx);                     \
+GLubyte *vertptr = (GLubyte *)nmesa->verts;                 \
+const GLuint vertsize = nmesa->vertexSize;          \
+const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts;       \
+const GLboolean stipple = ctx->Line.StippleFlag;               \
+(void) elt; (void) stipple;
+#define RESET_STIPPLE  if ( stipple ) nouveauResetLineStipple( ctx );
+#define RESET_OCCLUSION
+#define PRESERVE_VB_DEFS
+#define ELT(x) x
+#define TAG(x) nouveau_##x##_verts
+#include "tnl/t_vb_rendertmp.h"
+#undef ELT
+#undef TAG
+#define TAG(x) nouveau_##x##_elts
+#define ELT(x) elt[x]
+#include "tnl/t_vb_rendertmp.h"
+#undef ELT
+#undef TAG
+#undef NEED_EDGEFLAG_SETUP
+#undef EDGEFLAG_GET
+#undef EDGEFLAG_SET
+#undef RESET_OCCLUSION
+
+
+/**********************************************************************/
+/*                   Render clipped primitives                        */
+/**********************************************************************/
+
+
+
+static void nouveauRenderClippedPoly(GLcontext *ctx, const GLuint *elts,
+               GLuint n)
+{
+       TNLcontext *tnl = TNL_CONTEXT(ctx);
+       struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+       GLuint prim = NOUVEAU_CONTEXT(ctx)->renderPrimitive;
+
+       /* Render the new vertices as an unclipped polygon.
+        */
+       {
+               GLuint *tmp = VB->Elts;
+               VB->Elts = (GLuint *)elts;
+               tnl->Driver.Render.PrimTabElts[GL_POLYGON](ctx, 0, n,
+                               PRIM_BEGIN|PRIM_END);
+               VB->Elts = tmp;
+       }
+
+       /* Restore the render primitive
+        */
+       if (prim != GL_POLYGON &&
+                       prim != GL_POLYGON + 1)
+               tnl->Driver.Render.PrimitiveNotify( ctx, prim );
+}
+
+static void nouveauRenderClippedLine(GLcontext *ctx, GLuint ii, GLuint jj)
+{
+       TNLcontext *tnl = TNL_CONTEXT(ctx);
+       tnl->Driver.Render.Line(ctx, ii, jj);
+}
+
+static void nouveauFastRenderClippedPoly(GLcontext *ctx, const GLuint *elts,
+               GLuint n)
+{
+       struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx);
+       GLuint vertsize = nmesa->vertexSize;
+       GLuint *vb = nouveauExtendPrimitive(nmesa, (n - 2) * 3 * 4 * vertsize);
+       GLubyte *vertptr = (GLubyte *)nmesa->verts;
+       const GLuint *start = (const GLuint *)V(elts[0]);
+       int i;
+
+       for (i = 2; i < n; i++) {
+               COPY_DWORDS(vb, vertsize, V(elts[i - 1]));
+               COPY_DWORDS(vb, vertsize, V(elts[i]));
+               COPY_DWORDS(vb, vertsize, start);       
+       }
+}
+
+/**********************************************************************/
+/*                    Choose render functions                         */
+/**********************************************************************/
+
+
+
+
+#define _NOUVEAU_NEW_VERTEX (_NEW_TEXTURE |                         \
+               _DD_NEW_SEPARATE_SPECULAR |            \
+               _DD_NEW_TRI_UNFILLED |                 \
+               _DD_NEW_TRI_LIGHT_TWOSIDE |            \
+               _NEW_FOG)
+
+#define _NOUVEAU_NEW_RENDERSTATE (_DD_NEW_LINE_STIPPLE |            \
+               _DD_NEW_TRI_UNFILLED |            \
+               _DD_NEW_TRI_LIGHT_TWOSIDE |       \
+               _DD_NEW_TRI_OFFSET |              \
+               _DD_NEW_TRI_STIPPLE |             \
+               _NEW_POLYGONSTIPPLE)
+
+
+static void nv40ChooseRenderState(GLcontext *ctx)
+{
+       TNLcontext *tnl = TNL_CONTEXT(ctx);
+       struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx);
+       GLuint flags = ctx->_TriangleCaps;
+       GLuint index = 0;
+
+       nmesa->draw_point = nouveau_draw_point;
+       nmesa->draw_line = nouveau_draw_line;
+       nmesa->draw_tri = nouveau_draw_triangle;
+
+       if (flags & (ANY_FALLBACK_FLAGS|ANY_RASTER_FLAGS)) {
+               if (flags & DD_TRI_LIGHT_TWOSIDE)    index |= NOUVEAU_TWOSIDE_BIT;
+               if (flags & DD_TRI_OFFSET)           index |= NOUVEAU_OFFSET_BIT;
+               if (flags & DD_TRI_UNFILLED)         index |= NOUVEAU_UNFILLED_BIT;
+               if (flags & ANY_FALLBACK_FLAGS)      index |= NOUVEAU_FALLBACK_BIT;
+
+               /* Hook in fallbacks for specific primitives.
+                */
+               if (flags & POINT_FALLBACK)
+                       nmesa->draw_point = nouveau_fallback_point;
+
+               if (flags & LINE_FALLBACK)
+                       nmesa->draw_line = nouveau_fallback_line;
+
+               if (flags & TRI_FALLBACK)
+                       nmesa->draw_tri = nouveau_fallback_tri;
+       }
+
+
+       if ((flags & DD_SEPARATE_SPECULAR) &&
+                       ctx->Light.ShadeModel == GL_FLAT) {
+               index = NOUVEAU_MAX_TRIFUNC;    /* flat specular */
+       }
+
+       if (nmesa->renderIndex != index) {
+               nmesa->renderIndex = index;
+
+               tnl->Driver.Render.Points = rast_tab[index].points;
+               tnl->Driver.Render.Line = rast_tab[index].line;
+               tnl->Driver.Render.Triangle = rast_tab[index].triangle;
+               tnl->Driver.Render.Quad = rast_tab[index].quad;
+
+               if (index == 0) {
+                       tnl->Driver.Render.PrimTabVerts = nouveau_render_tab_verts;
+                       tnl->Driver.Render.PrimTabElts = nouveau_render_tab_elts;
+                       tnl->Driver.Render.ClippedLine = line; /* from tritmp.h */
+                       tnl->Driver.Render.ClippedPolygon = nouveauFastRenderClippedPoly;
+               }
+               else {
+                       tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts;
+                       tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts;
+                       tnl->Driver.Render.ClippedLine = nouveauRenderClippedLine;
+                       tnl->Driver.Render.ClippedPolygon = nouveauRenderClippedPoly;
+               }
+       }
+}
+
+
+
+static inline void nv40OutputVertexFormat(struct nouveau_context* mesa, GLuint index)
+{
+       /*
+        * Determine how many inputs we need in the vertex format.
+        * We need to find & setup the right input "slots"
+        * 
+        * The hw attribute order matches nv_vertex_program, and _TNL_BIT_* 
+        * also matches this order, so we can take shortcuts...
+        */
+       int i;
+       int slots=0;
+       for(i=0;i<16;i++)
+               if (index&(1<<i))
+                       slots=i+1;
+
+       BEGIN_RING_SIZE(channel,0x1740,slots);
+       for(i=0;i<slots;i++)
+               if (index&(1<<i))
+               {
+                       /* XXX for now we only emit 3-sized attributes */
+                       int size=3;
+                       OUR_RING(0x00000002|(size*0x10));
+               }
+               else
+               {
+                       OUR_RING(0x00000002);
+               }
+       BEGIN_RING_SIZE(channel,0x1718,1);
+       OUT_RING(0);
+       BEGIN_RING_SIZE(channel,0x1718,1);
+       OUT_RING(0);
+       BEGIN_RING_SIZE(channel,0x1718,1);
+       OUT_RING(0);
+}
+
+
+static void nv40ChooseVertexState( GLcontext *ctx )
+{
+       struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx);
+       TNLcontext *tnl = TNL_CONTEXT(ctx);
+       GLuint index = tnl->render_inputs;
+
+       if (index!=nmesa->render_inputs)
+       {
+               nmesa->render_inputs=index;
+               nv40OutputVertexFormat(nmesa,index);
+       }
+}
+
+
+/**********************************************************************/
+/*                 High level hooks for t_vb_render.c                 */
+/**********************************************************************/
+
+
+static void nv40RenderStart(GLcontext *ctx)
+{
+       struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx);
+
+       if (nmesa->newState) {
+               nmesa->newRenderState |= nmesa->newState;
+               nouveauValidateState( ctx );
+       }
+
+       if (nmesa->Fallback) {
+               tnl->Driver.Render.Start(ctx);
+               return;
+       }
+
+       if (nmesa->newRenderState) {
+               nv40ChooseVertexState(ctx);
+               nv40ChooseRenderState(ctx);
+               nmesa->newRenderState = 0;
+       }
+}
+
+static void nv40RenderFinish(GLcontext *ctx)
+{
+       struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx);
+       nv40FinishPrimitive(nmesa);
+}
+
+
+/* System to flush dma and emit state changes based on the rasterized
+ * primitive.
+ */
+void nv40RasterPrimitive(GLcontext *ctx,
+               GLenum glprim,
+               GLenum hwprim)
+{
+       struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx);
+
+       assert (!nmesa->newState);
+       
+       if (hwprim != nmesa->current_primitive)
+       {
+               nmesa->current_primitive=hwprim;
+               
+       }
+}
+
+/* Callback for mesa:
+ */
+static void nv40RenderPrimitive( GLcontext *ctx, GLuint prim )
+{
+       nv40RasterPrimitive( ctx, prim, prim );
+}
+
+
+
+/**********************************************************************/
+/*                            Initialization.                         */
+/**********************************************************************/
+
+
+void nouveauInitTriFuncs(GLcontext *ctx)
+{
+       struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx);
+       TNLcontext *tnl = TNL_CONTEXT(ctx);
+       static int firsttime = 1;
+
+       if (firsttime) {
+               init_rast_tab();
+               firsttime = 0;
+       }
+
+       tnl->Driver.RunPipeline = nouveauRunPipeline;
+       tnl->Driver.Render.Start = nv40RenderStart;
+       tnl->Driver.Render.Finish = nv40RenderFinish;
+       tnl->Driver.Render.PrimitiveNotify = nv40RenderPrimitive;
+       tnl->Driver.Render.ResetLineStipple = nouveauResetLineStipple;
+       tnl->Driver.Render.BuildVertices = _tnl_build_vertices;
+       tnl->Driver.Render.CopyPV = _tnl_copy_pv;
+       tnl->Driver.Render.Interp = _tnl_interp;
+
+       _tnl_init_vertices( ctx, ctx->Const.MaxArrayLockSize + 12, 
+                       (6 + 2*ctx->Const.MaxTextureUnits) * sizeof(GLfloat) );
+
+       nmesa->verts = (GLubyte *)tnl->clipspace.vertex_buf;
+
+}
+
diff --git a/src/mesa/drivers/dri/nouveau/nv40_tris.h b/src/mesa/drivers/dri/nouveau/nv40_tris.h
new file mode 100644 (file)
index 0000000..92f1896
--- /dev/null
@@ -0,0 +1,39 @@
+/**************************************************************************
+
+Copyright 2006 Stephane Marchesin
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+
+
+#ifndef __NV40_TRIS_H__
+#define __NV40_TRIS_H__
+
+#include "mtypes.h"
+
+extern void nv40TriInitFunctions( GLcontext *ctx );
+extern void nv40Fallback( GLcontext *ctx, GLuint bit, GLboolean mode );
+#define FALLBACK( nmesa, bit, mode ) nouveauFallback( nmesa->glCtx, bit, mode )
+
+#endif /* __NV40_TRIS_H__ */
+