Some work on buffer handling, most likely not entirely correct and
authorBen Skeggs <darktama@iinet.net.au>
Fri, 8 Dec 2006 03:01:33 +0000 (03:01 +0000)
committerBen Skeggs <darktama@iinet.net.au>
Fri, 8 Dec 2006 03:01:33 +0000 (03:01 +0000)
    incomplete. But, it works well enough that windows can be
    moved/resized.

19 files changed:
src/mesa/drivers/dri/nouveau/Makefile
src/mesa/drivers/dri/nouveau/nouveau_buffers.c [new file with mode: 0644]
src/mesa/drivers/dri/nouveau/nouveau_buffers.h [new file with mode: 0644]
src/mesa/drivers/dri/nouveau/nouveau_context.c
src/mesa/drivers/dri/nouveau/nouveau_context.h
src/mesa/drivers/dri/nouveau/nouveau_driver.c
src/mesa/drivers/dri/nouveau/nouveau_driver.h
src/mesa/drivers/dri/nouveau/nouveau_lock.c
src/mesa/drivers/dri/nouveau/nouveau_object.c
src/mesa/drivers/dri/nouveau/nouveau_object.h
src/mesa/drivers/dri/nouveau/nouveau_screen.c
src/mesa/drivers/dri/nouveau/nouveau_shader.c
src/mesa/drivers/dri/nouveau/nouveau_shader.h
src/mesa/drivers/dri/nouveau/nouveau_span.c
src/mesa/drivers/dri/nouveau/nouveau_span.h
src/mesa/drivers/dri/nouveau/nouveau_state.c
src/mesa/drivers/dri/nouveau/nouveau_state.h
src/mesa/drivers/dri/nouveau/nv30_fragprog.c
src/mesa/drivers/dri/nouveau/nv30_state.c

index 384713e..1a76169 100644 (file)
@@ -8,6 +8,7 @@ LIBNAME = nouveau_dri.so
 MINIGLX_SOURCES = 
 
 DRIVER_SOURCES = \
+       nouveau_buffers.c        \
        nouveau_card.c           \
        nouveau_context.c        \
        nouveau_driver.c         \
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_buffers.c b/src/mesa/drivers/dri/nouveau/nouveau_buffers.c
new file mode 100644 (file)
index 0000000..a356fd1
--- /dev/null
@@ -0,0 +1,331 @@
+#include "utils.h"
+#include "framebuffer.h"
+#include "renderbuffer.h"
+#include "fbobject.h"
+
+#include "nouveau_context.h"
+#include "nouveau_buffers.h"
+
+void
+nouveau_mem_free(GLcontext *ctx, nouveau_mem *mem)
+{
+   nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+   drm_nouveau_mem_free_t memf;
+
+   if (mem->map)
+      drmUnmap(mem->map, mem->size);
+   memf.flags         = mem->type;
+   memf.region_offset = mem->offset;
+   drmCommandWrite(nmesa->driFd, DRM_NOUVEAU_MEM_FREE, &memf, sizeof(memf));
+   FREE(mem);
+}
+
+nouveau_mem *
+nouveau_mem_alloc(GLcontext *ctx, int type, GLuint size, GLuint align)
+{
+   nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+   drm_nouveau_mem_alloc_t mema;
+   nouveau_mem *mem;
+   int ret;
+
+   mem = CALLOC(sizeof(nouveau_mem));
+   if (!mem)
+      return NULL;
+
+   mema.flags     = mem->type = type;
+   mema.size      = mem->size = size;
+   mema.alignment = align;
+   mem->map       = NULL;
+   ret = drmCommandWriteRead(nmesa->driFd, DRM_NOUVEAU_MEM_ALLOC,
+                            &mema, sizeof(mema));
+   if (ret) {
+      FREE(mem);
+      return NULL;
+   }
+   mem->offset = mema.region_offset;
+
+   if (type & NOUVEAU_MEM_MAPPED)
+      ret = drmMap(nmesa->driFd, mem->offset, mem->size, &mem->map);
+   if (ret) {
+      mem->map = NULL;
+      nouveau_mem_free(ctx, mem);
+      mem = NULL;
+   }
+
+   return mem;
+}
+
+uint32_t
+nouveau_mem_gpu_offset_get(GLcontext *ctx, nouveau_mem *mem)
+{
+   nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+
+   if (mem->type & NOUVEAU_MEM_FB)
+      return (uint32_t)mem->offset - nmesa->vram_phys;
+   else if (mem->type & NOUVEAU_MEM_AGP)
+      return (uint32_t)mem->offset - nmesa->agp_phys;
+   else
+      return 0xDEADF00D;
+}
+
+static GLboolean
+nouveau_renderbuffer_pixelformat(nouveau_renderbuffer *nrb,
+                                GLenum internalFormat)
+{
+      nrb->mesa.InternalFormat = internalFormat;
+
+   /*TODO: We probably want to extend this a bit, and maybe make
+    *      card-specific? 
+    */
+      switch (internalFormat) {
+      case GL_RGBA:
+      case GL_RGBA8:
+        nrb->mesa._BaseFormat  = GL_RGBA;
+        nrb->mesa._ActualFormat= GL_RGBA8;
+        nrb->mesa.DataType     = GL_UNSIGNED_BYTE;
+        nrb->mesa.RedBits      = 8;
+        nrb->mesa.GreenBits    = 8;
+        nrb->mesa.BlueBits     = 8;
+        nrb->mesa.AlphaBits    = 8;
+        nrb->cpp               = 4;
+        break;
+      case GL_RGB5:
+        nrb->mesa._BaseFormat  = GL_RGB;
+        nrb->mesa._ActualFormat= GL_RGB5;
+        nrb->mesa.DataType     = GL_UNSIGNED_BYTE;
+        nrb->mesa.RedBits      = 5;
+        nrb->mesa.GreenBits    = 6;
+        nrb->mesa.BlueBits     = 5;
+        nrb->mesa.AlphaBits    = 0;
+        nrb->cpp               = 2;
+        break;
+      case GL_DEPTH_COMPONENT16:
+        nrb->mesa._BaseFormat  = GL_DEPTH_COMPONENT;
+        nrb->mesa._ActualFormat= GL_DEPTH_COMPONENT16;
+        nrb->mesa.DataType     = GL_UNSIGNED_SHORT;
+        nrb->mesa.DepthBits    = 16;
+        nrb->cpp               = 2;
+        break;
+      case GL_DEPTH_COMPONENT24:
+        nrb->mesa._BaseFormat  = GL_DEPTH_COMPONENT;
+        nrb->mesa._ActualFormat= GL_DEPTH24_STENCIL8_EXT;
+        nrb->mesa.DataType     = GL_UNSIGNED_INT_24_8_EXT;
+        nrb->mesa.DepthBits    = 24;
+        nrb->cpp               = 4;
+        break;
+      case GL_STENCIL_INDEX8_EXT:
+        nrb->mesa._BaseFormat  = GL_STENCIL_INDEX;
+        nrb->mesa._ActualFormat= GL_DEPTH24_STENCIL8_EXT;
+        nrb->mesa.DataType     = GL_UNSIGNED_INT_24_8_EXT;
+        nrb->mesa.StencilBits  = 8;
+        nrb->cpp               = 4;
+        break;
+      case GL_DEPTH24_STENCIL8_EXT:
+        nrb->mesa._BaseFormat  = GL_DEPTH_STENCIL_EXT;
+        nrb->mesa._ActualFormat= GL_DEPTH24_STENCIL8_EXT;
+        nrb->mesa.DataType     = GL_UNSIGNED_INT_24_8_EXT;
+        nrb->mesa.DepthBits    = 24;
+        nrb->mesa.StencilBits  = 8;
+        nrb->cpp               = 4;
+        break;
+      default:
+        return GL_FALSE;
+        break;
+      }
+
+      return GL_TRUE;
+}
+
+static GLboolean
+nouveau_renderbuffer_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
+                            GLenum internalFormat,
+                            GLuint width,
+                            GLuint height)
+{
+   nouveau_renderbuffer *nrb = (nouveau_renderbuffer*)rb;
+
+   if (!nouveau_renderbuffer_pixelformat(nrb, internalFormat)) {
+      fprintf(stderr, "%s: unknown internalFormat\n", __func__);
+      return GL_FALSE;
+   }
+
+   /* If this buffer isn't statically alloc'd, we may need to ask the
+    * drm for more memory */
+   if (!nrb->map && (rb->Width != width || rb->Height != height)) {
+      GLuint pitch;
+
+      /* align pitches to 64 bytes */
+      pitch = ((width * nrb->cpp) + 63) & ~63;
+
+      if (nrb->mem)
+        nouveau_mem_free(ctx, nrb->mem);
+      nrb->mem = nouveau_mem_alloc(ctx,
+                                  NOUVEAU_MEM_FB | NOUVEAU_MEM_MAPPED,
+                                  pitch*height,
+                                  0);
+      if (!nrb->mem)
+        return GL_FALSE;
+
+      /* update nouveau_renderbuffer info */
+      nrb->offset = nouveau_mem_gpu_offset_get(ctx, nrb->mem);
+      nrb->pitch  = pitch;
+   }
+
+   rb->Width = width;
+   rb->Height = height;
+   rb->InternalFormat = internalFormat;
+   return GL_TRUE;
+}
+
+static void
+nouveau_renderbuffer_delete(struct gl_renderbuffer *rb)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   nouveau_renderbuffer *nrb = (nouveau_renderbuffer*)rb;
+
+   if (nrb->mem)
+      nouveau_mem_free(ctx, nrb->mem);
+   FREE(nrb);
+}
+
+nouveau_renderbuffer *
+nouveau_renderbuffer_new(GLenum internalFormat, GLvoid *map,
+                        GLuint offset,  GLuint pitch,
+                        __DRIdrawablePrivate *dPriv)
+{
+   nouveau_renderbuffer *nrb;
+
+   nrb = CALLOC_STRUCT(nouveau_renderbuffer_t);
+   if (nrb) {
+      _mesa_init_renderbuffer(&nrb->mesa, 0);
+
+      nouveau_renderbuffer_pixelformat(nrb, internalFormat);
+
+      nrb->mesa.AllocStorage   = nouveau_renderbuffer_storage;
+      nrb->mesa.Delete         = nouveau_renderbuffer_delete;
+
+      nrb->dPriv  = dPriv;
+      nrb->offset = offset;
+      nrb->pitch  = pitch;
+      nrb->map    = map;
+   }
+
+   return nrb;
+}
+
+void
+nouveau_window_moved(GLcontext *ctx)
+{
+   nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+
+   /* Viewport depends on window size/position, nouveauCalcViewport
+    * will take care of calling the hw-specific WindowMoved
+    */
+   ctx->Driver.Viewport(ctx, ctx->Viewport.X, ctx->Viewport.Y,
+                            ctx->Viewport.Width, ctx->Viewport.Height);
+   /* Scissor depends on window position */
+   ctx->Driver.Scissor(ctx, ctx->Scissor.X, ctx->Scissor.Y,
+                           ctx->Scissor.Width, ctx->Scissor.Height);
+}
+
+GLboolean
+nouveau_build_framebuffer(GLcontext *ctx, struct gl_framebuffer *fb)
+{
+   nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+   nouveau_renderbuffer *color[MAX_DRAW_BUFFERS];
+   nouveau_renderbuffer *depth;
+
+   _mesa_update_framebuffer(ctx);
+   _mesa_update_draw_buffer_bounds(ctx);
+
+   color[0] = (nouveau_renderbuffer *)fb->_ColorDrawBuffers[0][0];
+   depth    = (nouveau_renderbuffer *)fb->_DepthBuffer;
+
+   if (!nmesa->hw_func.BindBuffers(nmesa, 1, color, depth))
+      return GL_FALSE;
+   nouveau_window_moved(ctx);
+
+   return GL_TRUE;
+}
+
+nouveau_renderbuffer *
+nouveau_current_draw_buffer(GLcontext *ctx)
+{
+   struct gl_framebuffer *fb = ctx->DrawBuffer;
+   nouveau_renderbuffer *nrb;
+
+   if (!fb)
+      return NULL;
+
+   if (fb->_ColorDrawBufferMask[0] == BUFFER_BIT_FRONT_LEFT)
+      nrb = (nouveau_renderbuffer *)
+        fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer;
+   else if (fb->_ColorDrawBufferMask[0] == BUFFER_BIT_BACK_LEFT)
+      nrb = (nouveau_renderbuffer *)
+        fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer;
+   else
+      nrb = NULL;
+   return nrb;
+}
+
+static struct gl_framebuffer *
+nouveauNewFramebuffer(GLcontext *ctx, GLuint name)
+{
+   return _mesa_new_framebuffer(ctx, name);
+}
+
+static struct gl_renderbuffer *
+nouveauNewRenderbuffer(GLcontext *ctx, GLuint name)
+{
+   nouveau_renderbuffer *nrb;
+
+   nrb = CALLOC_STRUCT(nouveau_renderbuffer_t);
+   if (nrb) {
+      _mesa_init_renderbuffer(&nrb->mesa, name);
+
+      nrb->mesa.AllocStorage   = nouveau_renderbuffer_storage;
+      nrb->mesa.Delete         = nouveau_renderbuffer_delete;
+   }
+   return &nrb->mesa;
+}
+
+static void
+nouveauBindFramebuffer(GLcontext *ctx, GLenum target, struct gl_framebuffer *fb)
+{
+   nouveau_build_framebuffer(ctx, fb);
+}
+
+static void
+nouveauFramebufferRenderbuffer(GLcontext *ctx,
+                              struct gl_framebuffer *fb,
+                              GLenum attachment,
+                              struct gl_renderbuffer *rb)
+{
+   _mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb);
+   nouveau_build_framebuffer(ctx, fb);
+}
+
+static void
+nouveauRenderTexture(GLcontext *ctx,
+                    struct gl_framebuffer *fb,
+                    struct gl_renderbuffer_attachment *att)
+{
+}
+
+static void
+nouveauFinishRenderTexture(GLcontext *ctx,
+                          struct gl_renderbuffer_attachment *att)
+{
+}
+
+void
+nouveauInitBufferFuncs(struct dd_function_table *func)
+{
+   func->NewFramebuffer                 = nouveauNewFramebuffer;
+   func->NewRenderbuffer        = nouveauNewRenderbuffer;
+   func->BindFramebuffer        = nouveauBindFramebuffer;
+   func->FramebufferRenderbuffer = nouveauFramebufferRenderbuffer;
+   func->RenderTexture          = nouveauRenderTexture;
+   func->FinishRenderTexture    = nouveauFinishRenderTexture;
+}
+
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_buffers.h b/src/mesa/drivers/dri/nouveau/nouveau_buffers.h
new file mode 100644 (file)
index 0000000..bb297ad
--- /dev/null
@@ -0,0 +1,41 @@
+#ifndef __NOUVEAU_BUFFERS_H__
+#define __NOUVEAU_BUFFERS_H__
+
+#include <stdint.h>
+#include "mtypes.h"
+#include "utils.h"
+#include "renderbuffer.h"
+
+typedef struct nouveau_mem_t {
+   int type;
+   uint64_t offset;
+   uint64_t size;
+   void*    map;
+} nouveau_mem;
+
+extern nouveau_mem *nouveau_mem_alloc(GLcontext *ctx, int type,
+                                     GLuint size, GLuint align);
+extern void nouveau_mem_free(GLcontext *ctx, nouveau_mem *mem);
+extern uint32_t nouveau_mem_gpu_offset_get(GLcontext *ctx, nouveau_mem *mem);
+
+typedef struct nouveau_renderbuffer_t {
+   struct gl_renderbuffer mesa; /* must be first! */
+   __DRIdrawablePrivate  *dPriv;
+
+   nouveau_mem *mem;
+   void *      map;
+
+   int         cpp;
+   uint32_t    offset;
+   uint32_t    pitch;
+} nouveau_renderbuffer;
+
+extern nouveau_renderbuffer *nouveau_renderbuffer_new(GLenum internalFormat,
+      GLvoid *map, GLuint offset, GLuint pitch, __DRIdrawablePrivate *dPriv);
+extern void nouveau_window_moved(GLcontext *ctx);
+extern GLboolean nouveau_build_framebuffer(GLcontext *, struct gl_framebuffer *);
+extern nouveau_renderbuffer *nouveau_current_draw_buffer(GLcontext *ctx);
+
+extern void nouveauInitBufferFuncs(struct dd_function_table *func);
+
+#endif
index b208d6c..f48c544 100644 (file)
@@ -32,6 +32,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "swrast/swrast.h"
 #include "swrast_setup/swrast_setup.h"
 #include "array_cache/acache.h"
+#include "framebuffer.h"
 
 #include "tnl/tnl.h"
 #include "tnl/t_pipeline.h"
@@ -47,6 +48,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "nouveau_fifo.h"
 #include "nouveau_tex.h"
 #include "nouveau_msg.h"
+#include "nouveau_reg.h"
 #include "nv10_swtcl.h"
 
 #include "vblank.h"
@@ -96,10 +98,17 @@ GLboolean nouveauCreateContext( const __GLcontextModes *glVisual,
        screen=nmesa->screen;
 
        /* Create the hardware context */
+       if (!nouveauDRMGetParam(nmesa, NOUVEAU_GETPARAM_FB_PHYSICAL,
+                               &nmesa->vram_phys))
+          return GL_FALSE;
+       if (!nouveauDRMGetParam(nmesa, NOUVEAU_GETPARAM_AGP_PHYSICAL,
+                               &nmesa->agp_phys))
+          return GL_FALSE;
        if (!nouveauFifoInit(nmesa))
           return GL_FALSE;
        nouveauObjectInit(nmesa);
 
+
        /* Init default driver functions then plug in our nouveau-specific functions
         * (the texture functions are especially important)
         */
@@ -169,6 +178,7 @@ GLboolean nouveauCreateContext( const __GLcontextModes *glVisual,
                        break;
        }
 
+       nmesa->hw_func.InitCard(nmesa);
         nouveauInitState(ctx);
 
        driContextPriv->driverPrivate = (void *)nmesa;
@@ -208,17 +218,26 @@ GLboolean nouveauMakeCurrent( __DRIcontextPrivate *driContextPriv,
                __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->vblank_seq );
-               newNOUVEAUCtx->driDrawable = driDrawPriv;
-
-               _mesa_make_current( newNOUVEAUCtx->glCtx,
-                               (GLframebuffer *) driDrawPriv->driverPrivate,
-                               (GLframebuffer *) driReadPriv->driverPrivate );
-
+               nouveauContextPtr nmesa = (nouveauContextPtr) driContextPriv->driverPrivate;
+               struct gl_framebuffer *draw_fb =
+                       (struct gl_framebuffer*)driDrawPriv->driverPrivate;
+               struct gl_framebuffer *read_fb =
+                       (struct gl_framebuffer*)driReadPriv->driverPrivate;
+
+               driDrawableInitVBlank(driDrawPriv, nmesa->vblank_flags, &nmesa->vblank_seq );
+               nmesa->driDrawable = driDrawPriv;
+
+               _mesa_resize_framebuffer(nmesa->glCtx, draw_fb,
+                                        driDrawPriv->w, driDrawPriv->h);
+               if (draw_fb != read_fb) {
+                       _mesa_resize_framebuffer(nmesa->glCtx, draw_fb,
+                                                driReadPriv->w,
+                                                driReadPriv->h);
+               }
+               _mesa_make_current(nmesa->glCtx, draw_fb, read_fb);
+
+               nouveau_build_framebuffer(nmesa->glCtx,
+                                         driDrawPriv->driverPrivate);
        } else {
                _mesa_make_current( NULL, NULL, NULL );
        }
@@ -234,8 +253,46 @@ GLboolean nouveauUnbindContext( __DRIcontextPrivate *driContextPriv )
        return GL_TRUE;
 }
 
+static void nouveauDoSwapBuffers(nouveauContextPtr nmesa,
+                                __DRIdrawablePrivate *dPriv)
+{
+       struct gl_framebuffer *fb;
+       nouveau_renderbuffer *src, *dst;
+
+       fb = (struct gl_framebuffer *)dPriv->driverPrivate;
+       dst = (nouveau_renderbuffer*)
+               fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer;
+       src = (nouveau_renderbuffer*)
+               fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer;
+
+#ifdef ALLOW_MULTI_SUBCHANNEL
+       /* Ignore this.. it's a hack to test double-buffering, and not how
+        * SwapBuffers should look :)
+        */
+       BEGIN_RING_SIZE(NvSubCtxSurf2D, NV10_CONTEXT_SURFACES_2D_FORMAT, 4);
+       OUT_RING       (6); /* X8R8G8B8 */
+       OUT_RING       ((dst->pitch << 16) | src->pitch);
+       OUT_RING       (src->offset);
+       OUT_RING       (dst->offset);
+
+       BEGIN_RING_SIZE(NvSubImageBlit, NV10_IMAGE_BLIT_SET_POINT, 3);
+       OUT_RING       ((0 << 16) | 0); /* src point */
+       OUT_RING       ((0 << 16) | 0); /* dst point */
+       OUT_RING       ((fb->Height << 16) | fb->Width); /* width/height */
+#endif
+}
+
 void nouveauSwapBuffers(__DRIdrawablePrivate *dPriv)
 {
+       if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
+               nouveauContextPtr nmesa = dPriv->driContextPriv->driverPrivate;
+
+               if (nmesa->glCtx->Visual.doubleBufferMode) {
+                       _mesa_notifySwapBuffers(nmesa->glCtx);
+                       nouveauDoSwapBuffers(nmesa, dPriv);
+               }
+
+       }
 }
 
 void nouveauCopySubBuffer(__DRIdrawablePrivate *dPriv,
index 947e95d..211d4e0 100644 (file)
@@ -38,6 +38,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 #include "nouveau_screen.h"
 #include "nouveau_state_cache.h"
+#include "nouveau_buffers.h"
 #include "nouveau_shader.h"
 
 #include "xmlconfig.h"
@@ -75,6 +76,17 @@ typedef void (*nouveau_line_func)( struct nouveau_context*,
 typedef void (*nouveau_point_func)( struct nouveau_context*,
                nouveauVertex * );
 
+typedef struct nouveau_hw_func_t {
+       /* Initialise any card-specific non-GL related state */
+       GLboolean (*InitCard)(struct nouveau_context *);
+       /* Update buffer offset/pitch/format */
+       GLboolean (*BindBuffers)(struct nouveau_context *, int num_color,
+                                nouveau_renderbuffer **color,
+                                nouveau_renderbuffer *depth);
+       /* Update anything that depends on the window position/size */
+       void      (*WindowMoved)(struct nouveau_context *);
+} nouveau_hw_func;
+
 typedef struct nouveau_context {
        /* Mesa context */
        GLcontext *glCtx;
@@ -85,6 +97,13 @@ typedef struct nouveau_context {
        /* The read-only regs */
        volatile unsigned char* mmio;
 
+       /* Physical addresses of AGP/VRAM apertures */
+       uint64_t vram_phys;
+       uint64_t agp_phys;
+
+       /* Additional hw-specific functions */
+       nouveau_hw_func hw_func;
+
        /* FIXME : do we want to put all state into a separate struct ? */
        /* State for tris */
        GLuint color_offset;
@@ -132,6 +151,7 @@ typedef struct nouveau_context {
        __DRIcontextPrivate  *driContext;    /* DRI context */
        __DRIscreenPrivate   *driScreen;     /* DRI screen */
        __DRIdrawablePrivate *driDrawable;   /* DRI drawable bound to this ctx */
+       GLint lastStamp;
 
        drm_context_t hHWContext;
        drm_hw_lock_t *driHwLock;
index a45530e..f85dc62 100644 (file)
@@ -36,6 +36,35 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 #include "utils.h"
 
+/* Wrapper for DRM_NOUVEAU_GETPARAM ioctl */
+GLboolean nouveauDRMGetParam(nouveauContextPtr nmesa,
+                            unsigned int      param,
+                            uint64_t*         value)
+{
+       drm_nouveau_getparam_t getp;
+
+       getp.param = param;
+       if (!value || drmCommandWriteRead(nmesa->driFd, DRM_NOUVEAU_GETPARAM,
+                                         &getp, sizeof(getp)))
+               return GL_FALSE;
+       *value = getp.value;
+       return GL_TRUE;
+}
+
+/* Wrapper for DRM_NOUVEAU_GETPARAM ioctl */
+GLboolean nouveauDRMSetParam(nouveauContextPtr nmesa,
+                            unsigned int      param,
+                            uint64_t          value)
+{
+       drm_nouveau_setparam_t setp;
+
+       setp.param = param;
+       setp.value = value;
+       if (drmCommandWrite(nmesa->driFd, DRM_NOUVEAU_SETPARAM, &setp,
+                               sizeof(setp)))
+               return GL_FALSE;
+       return GL_TRUE;
+}
 
 /* Return the width and height of the current color buffer */
 static void nouveauGetBufferSize( GLframebuffer *buffer,
index e1541aa..6164012 100644 (file)
@@ -33,7 +33,10 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define DRIVER_AUTHOR  "Stephane Marchesin"
 
 extern void nouveauDriverInitFunctions( struct dd_function_table *functions );
-
+extern GLboolean nouveauDRMGetParam(nouveauContextPtr nmesa, unsigned int param,
+                                   uint64_t *value);
+extern GLboolean nouveauDRMSetParam(nouveauContextPtr nmesa, unsigned int param,
+                                   uint64_t value);
 
 #endif /* __NOUVEAU_DRIVER_H__ */
 
index 7dd67a1..c119d14 100644 (file)
@@ -29,6 +29,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "nouveau_lock.h"
 
 #include "drirenderbuffer.h"
+#include "framebuffer.h"
 
 
 /* Update the hardware state.  This is called if another context has
@@ -57,6 +58,23 @@ void nouveauGetLock( nouveauContextPtr nmesa, GLuint flags )
     */
    DRI_VALIDATE_DRAWABLE_INFO( sPriv, dPriv );
 
+   /* If timestamps don't match, the window has been changed */
+   if (nmesa->lastStamp != dPriv->lastStamp) {
+      struct gl_framebuffer *fb = (struct gl_framebuffer *)dPriv->driverPrivate;
+
+      /* _mesa_resize_framebuffer will take care of calling the renderbuffer's
+       * AllocStorage function if we need more memory to hold it */
+      if (fb->Width != dPriv->w || fb->Height != dPriv->h) {
+        _mesa_resize_framebuffer(nmesa->glCtx, fb, dPriv->w, dPriv->h);
+        /* resize buffers, will call nouveau_window_moved */
+        nouveau_build_framebuffer(nmesa->glCtx, fb);
+      } else {
+        nouveau_window_moved(nmesa->glCtx);
+      }
+
+      nmesa->lastStamp = dPriv->lastStamp;
+   }
+
    nmesa->numClipRects = dPriv->numClipRects;
    nmesa->pClipRects = dPriv->pClipRects;
 
index 032cdee..ef8a428 100644 (file)
@@ -1,6 +1,7 @@
 
 #include "nouveau_fifo.h"
 #include "nouveau_object.h"
+#include "nouveau_reg.h"
 
 
 static GLboolean nouveauCreateContextObject(nouveauContextPtr nmesa, int handle, int class, uint32_t flags, uint32_t dma_in, uint32_t dma_out, uint32_t dma_notifier)
@@ -51,14 +52,30 @@ void nouveauObjectInit(nouveauContextPtr nmesa)
        return;
 #endif
 
-       nouveauCreateContextObject(nmesa, Nv3D, nmesa->screen->card->class_3d, 0, 0, 0, 0);
-       nouveauObjectOnSubchannel(nmesa, NvSub3D, Nv3D);
 /* We need to know vram size.. */
-#if 0
        nouveauCreateDmaObject( nmesa, NvDmaFB,
                                0, (256*1024*1024),
                                0 /*NV_DMA_TARGET_FB*/, 0 /*NV_DMA_ACCESS_RW*/);
+
+       nouveauCreateContextObject(nmesa, Nv3D, nmesa->screen->card->class_3d,
+                                  0, 0, 0, 0);
+       nouveauCreateContextObject(nmesa, NvCtxSurf2D, NV10_CONTEXT_SURFACES_2D,
+                                  0, 0, 0, 0);
+       nouveauCreateContextObject(nmesa, NvImageBlit, NV10_IMAGE_BLIT,
+                                  NV_DMA_CONTEXT_FLAGS_PATCH_SRCCOPY, 0, 0, 0);
+
+#ifdef ALLOW_MULTI_SUBCHANNEL
+       nouveauObjectOnSubchannel(nmesa, NvSubCtxSurf2D, NvCtxSurf2D);
+       BEGIN_RING_SIZE(NvSubCtxSurf2D, NV10_CONTEXT_SURFACES_2D_SET_DMA_IN_MEMORY0, 2);
+       OUT_RING(NvDmaFB);
+       OUT_RING(NvDmaFB);
+
+       nouveauObjectOnSubchannel(nmesa, NvSubImageBlit, NvImageBlit);
+       BEGIN_RING_SIZE(NvSubImageBlit, NV10_IMAGE_BLIT_SET_CONTEXT_SURFACES_2D, 1);
+       OUT_RING(NvCtxSurf2D);
 #endif
+
+       nouveauObjectOnSubchannel(nmesa, NvSub3D, Nv3D);
 }
 
 
index 8386f92..f555eba 100644 (file)
@@ -3,14 +3,21 @@
 
 #include "nouveau_context.h"
 
+#define ALLOW_MULTI_SUBCHANNEL
+
 void nouveauObjectInit(nouveauContextPtr nmesa);
 
 enum DMAObjects {
        Nv3D                    = 0x80000019,
-       NvDmaFB                 = 0xD0FB0001
+       NvCtxSurf2D             = 0x80000020,
+       NvImageBlit             = 0x80000021,
+       NvDmaFB                 = 0xD0FB0001,
+       NvDmaAGP                = 0xD0AA0001
 };
 
 enum DMASubchannel {
+       NvSubCtxSurf2D  = 0,
+       NvSubImageBlit  = 1,
        NvSub3D         = 7,
 };
 
index 51f9fb1..15c1c40 100644 (file)
@@ -120,86 +120,69 @@ nouveauCreateBuffer(__DRIscreenPrivate *driScrnPriv,
                     GLboolean isPixmap)
 {
        nouveauScreenPtr screen = (nouveauScreenPtr) driScrnPriv->private;
+       nouveau_renderbuffer  *nrb;
+       struct gl_framebuffer *fb;
+       const GLboolean swAccum = mesaVis->accumRedBits > 0;
+       const GLboolean swStencil = mesaVis->stencilBits > 0 && mesaVis->depthBits != 24;
 
-       if (isPixmap) {
+       if (isPixmap)
                return GL_FALSE; /* not implemented */
-       }
-       else {
-               const GLboolean swDepth = GL_FALSE;
-               const GLboolean swAlpha = GL_FALSE;
-               const GLboolean swAccum = mesaVis->accumRedBits > 0;
-               const GLboolean swStencil = mesaVis->stencilBits > 0 && mesaVis->depthBits != 24;
-               struct gl_framebuffer *fb = _mesa_create_framebuffer(mesaVis);
-
-               /* front color renderbuffer */
-               {
-                       driRenderbuffer *frontRb
-                               = driNewRenderbuffer(GL_RGBA,
-                                                    driScrnPriv->pFB + screen->frontOffset,
-                                                    screen->fbFormat,
-                                                    screen->frontOffset, screen->frontPitch,
-                                                    driDrawPriv);
-                       nouveauSpanSetFunctions(frontRb, mesaVis);
-                       _mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, &frontRb->Base);
-               }
 
-               /* back color renderbuffer */
-               if (mesaVis->doubleBufferMode) {
-                       driRenderbuffer *backRb
-                               = driNewRenderbuffer(GL_RGBA,
-                                                    driScrnPriv->pFB + screen->backOffset,
-                                                    screen->fbFormat,
-                                                    screen->backOffset, screen->backPitch,
-                                                    driDrawPriv);
-                       nouveauSpanSetFunctions(backRb, mesaVis);
-                       _mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, &backRb->Base);
-               }
+       fb = _mesa_create_framebuffer(mesaVis);
+       if (!fb)
+               return GL_FALSE;
 
-               /* depth renderbuffer */
-               if (mesaVis->depthBits == 16) {
-                       driRenderbuffer *depthRb
-                               = driNewRenderbuffer(GL_DEPTH_COMPONENT16,
-                                                    driScrnPriv->pFB + screen->depthOffset,
-                                                    screen->fbFormat,
-                                                    screen->depthOffset, screen->depthPitch,
-                                                    driDrawPriv);
-                       nouveauSpanSetFunctions(depthRb, mesaVis);
-                       _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base);
-               }
-               else if (mesaVis->depthBits == 24) {
-                       driRenderbuffer *depthRb
-                               = driNewRenderbuffer(GL_DEPTH_COMPONENT24,
-                                                    driScrnPriv->pFB + screen->depthOffset,
-                                                    screen->fbFormat,
-                                                    screen->depthOffset, screen->depthPitch,
-                                                    driDrawPriv);
-                       nouveauSpanSetFunctions(depthRb, mesaVis);
-                       _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base);
+       /* Front buffer */
+       nrb = nouveau_renderbuffer_new(GL_RGBA,
+                                      driScrnPriv->pFB + screen->frontOffset,
+                                      screen->frontOffset,
+                                      screen->frontPitch * 4,
+                                      driDrawPriv);
+       nouveauSpanSetFunctions(nrb, mesaVis);
+       _mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, &nrb->mesa);
+
+       if (0 /* unified buffers if we choose to support them.. */) {
+       } else {
+               if (mesaVis->doubleBufferMode) {
+                       nrb = nouveau_renderbuffer_new(GL_RGBA, NULL,
+                                                      0, 0,
+                                                      driDrawPriv);
+                       nouveauSpanSetFunctions(nrb, mesaVis);
+                       _mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, &nrb->mesa);
                }
 
-               /* stencil renderbuffer */
-               if (mesaVis->stencilBits > 0 && !swStencil) {
-                       driRenderbuffer *stencilRb
-                               = driNewRenderbuffer(GL_STENCIL_INDEX8_EXT,
-                                                    driScrnPriv->pFB + screen->depthOffset,
-                                                    screen->fbFormat,
-                                                    screen->depthOffset, screen->depthPitch,
-                                                    driDrawPriv);
-                       nouveauSpanSetFunctions(stencilRb, mesaVis);
-                       _mesa_add_renderbuffer(fb, BUFFER_STENCIL, &stencilRb->Base);
+               if (mesaVis->depthBits == 24 && mesaVis->stencilBits == 8) {
+                       nrb = nouveau_renderbuffer_new(GL_DEPTH24_STENCIL8_EXT, NULL,
+                                                      0, 0,
+                                                      driDrawPriv);
+                       nouveauSpanSetFunctions(nrb, mesaVis);
+                       _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &nrb->mesa);
+                       _mesa_add_renderbuffer(fb, BUFFER_STENCIL, &nrb->mesa);
+               } else if (mesaVis->depthBits == 24) {
+                       nrb = nouveau_renderbuffer_new(GL_DEPTH_COMPONENT24, NULL,
+                                                      0, 0,
+                                                      driDrawPriv);
+                       nouveauSpanSetFunctions(nrb, mesaVis);
+                       _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &nrb->mesa);
+               } else if (mesaVis->depthBits == 16) {
+                       nrb = nouveau_renderbuffer_new(GL_DEPTH_COMPONENT16, NULL,
+                                                      0, 0,
+                                                      driDrawPriv);
+                       nouveauSpanSetFunctions(nrb, mesaVis);
+                       _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &nrb->mesa);
                }
+       }
 
-               _mesa_add_soft_renderbuffers(fb,
-                                            GL_FALSE, /* color */
-                                            swDepth,
-                                            swStencil,
-                                            swAccum,
-                                            swAlpha,
-                                            GL_FALSE /* aux */);
-               driDrawPriv->driverPrivate = (void *) fb;
+       _mesa_add_soft_renderbuffers(fb,
+                                    GL_FALSE, /* color */
+                                    GL_FALSE, /* depth */
+                                    swStencil,
+                                    swAccum,
+                                    GL_FALSE, /* alpha */
+                                    GL_FALSE  /* aux */);
 
-               return (driDrawPriv->driverPrivate != NULL);
-       }
+       driDrawPriv->driverPrivate = (void *) fb;
+       return (driDrawPriv->driverPrivate != NULL);
 }
 
 
@@ -363,7 +346,8 @@ void * __driCreateNewScreen_20050727( __DRInativeDisplay *dpy, int scrn, __DRIsc
                *driver_modes = nouveauFillInModes(dri_priv->bpp,
                                                   (dri_priv->bpp == 16) ? 16 : 24,
                                                   (dri_priv->bpp == 16) ? 0  : 8,
-                                                  (dri_priv->back_offset != dri_priv->depth_offset));
+                                                  1
+                                                  );
 
                /* Calling driInitExtensions here, with a NULL context pointer, does not actually
                 * enable the extensions.  It just makes sure that all the dispatch offsets for all
index 63da842..4dedefe 100644 (file)
@@ -132,6 +132,8 @@ nvsUpdateShader(GLcontext *ctx, nouveauShader *nvs)
          */
         nvs->func->UpdateConst(ctx, nvs, i);
       } else if (plist->Parameters[i].Type == PROGRAM_STATE_VAR) {
+        if (!nvs->params[i].source_val) /* this is a workaround when consts aren't alloc'd from id=0.. */
+           continue;
         /* update any changed state parameters */
         if (!TEST_EQ_4V(nvs->params[i].val, nvs->params[i].source_val))
            nvs->func->UpdateConst(ctx, nvs, i);
index a1e7794..dce2e23 100644 (file)
@@ -2,6 +2,7 @@
 #define __SHADER_COMMON_H__
 
 #include "mtypes.h"
+#include "nouveau_buffers.h"
 
 typedef struct _nvsFunc nvsFunc;
 
@@ -40,6 +41,7 @@ typedef struct _nouveauShader {
    unsigned int program_alloc_size;
    unsigned int program_start_id;
    unsigned int program_current;
+   nouveau_mem *program_buffer;
    unsigned int inputs_read;
    unsigned int outputs_written;
    int         inst_count;
index 1763b37..6d99728 100644 (file)
@@ -109,14 +109,10 @@ void nouveauSpanInitFunctions( GLcontext *ctx )
  * Plug in the Get/Put routines for the given driRenderbuffer.
  */
 void
-nouveauSpanSetFunctions(driRenderbuffer *drb, const GLvisual *vis)
+nouveauSpanSetFunctions(nouveau_renderbuffer *nrb, 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);
-      }
-   }
+   if (nrb->mesa._ActualFormat == GL_RGBA8)
+      nouveauInitPointers_ARGB8888(&nrb->mesa);
+   else if (nrb->mesa._ActualFormat == GL_RGB5)
+      nouveauInitPointers_RGB565(&nrb->mesa);
 }
index f5e5733..bc39ecd 100644 (file)
@@ -30,9 +30,10 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define __NOUVEAU_SPAN_H__
 
 #include "drirenderbuffer.h"
+#include "nouveau_buffers.h"
 
 extern void nouveauSpanInitFunctions( GLcontext *ctx );
-extern void nouveauSpanSetFunctions(driRenderbuffer *rb, const GLvisual *vis);
+extern void nouveauSpanSetFunctions(nouveau_renderbuffer *nrb, const GLvisual *vis);
 
 #endif /* __NOUVEAU_SPAN_H__ */
 
index 88a8c9e..6406b2d 100644 (file)
@@ -59,20 +59,33 @@ static void nouveauCalcViewport(GLcontext *ctx)
     /* Calculate the Viewport Matrix */
     
     nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+    nouveau_renderbuffer *nrb;
     const GLfloat *v = ctx->Viewport._WindowMap.m;
     GLfloat *m = nmesa->viewport.m;
+    GLfloat xoffset, yoffset;
     GLint h = 0;
-    
-    if (nmesa->driDrawable) 
-       h = nmesa->driDrawable->h + SUBPIXEL_Y;
-    
+  
+    nrb = nouveau_current_draw_buffer(ctx);
+    nmesa->depth_scale = 1.0 / ctx->DrawBuffer->_DepthMaxF;
+
+    if (nrb && nrb->map) {
+       /* Window */
+       xoffset = nrb->dPriv->x;
+       yoffset = nrb->dPriv->y;
+    } else {
+       /* Offscreen or back buffer */
+       xoffset = 0.0;
+       yoffset = 0.0;
+    }
+
     m[MAT_SX] =   v[MAT_SX];
-    m[MAT_TX] =   v[MAT_TX] + SUBPIXEL_X;
+    m[MAT_TX] =   v[MAT_TX] + xoffset + SUBPIXEL_X;
     m[MAT_SY] = - v[MAT_SY];
-    m[MAT_TY] = - v[MAT_TY] + h;
+    m[MAT_TY] =   v[MAT_TY] + yoffset + SUBPIXEL_Y;
     m[MAT_SZ] =   v[MAT_SZ] * nmesa->depth_scale;
     m[MAT_TZ] =   v[MAT_TZ] * nmesa->depth_scale;
 
+    nmesa->hw_func.WindowMoved(nmesa);
 }
 
 static void nouveauViewport(GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h)
@@ -96,7 +109,7 @@ static void nouveauViewport(GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei
     nouveauCalcViewport(ctx);
 }
 
-static void nouveauDepthRange(GLcontext *ctx)
+static void nouveauDepthRange(GLcontext *ctx, GLclampd near, GLclampd far)
 {
     nouveauCalcViewport(ctx);
 }
@@ -161,15 +174,15 @@ void nouveauDDInitState(nouveauContextPtr nmesa)
             /* No TCL engines for these ones */
             break;
         case NV_10:
-            nv10InitStateFuncs(&nmesa->glCtx->Driver);
+            nv10InitStateFuncs(nmesa->glCtx, &nmesa->glCtx->Driver);
             break;
         case NV_20:
-            nv20InitStateFuncs(&nmesa->glCtx->Driver);
+            nv20InitStateFuncs(nmesa->glCtx, &nmesa->glCtx->Driver);
             break;
         case NV_30:
         case NV_40:
         case NV_50:
-            nv30InitStateFuncs(&nmesa->glCtx->Driver);
+            nv30InitStateFuncs(nmesa->glCtx, &nmesa->glCtx->Driver);
             break;
         default:
             break;
@@ -270,7 +283,6 @@ void nouveauInitState(GLcontext *ctx)
     STATE_INIT(CullFace)( ctx, ctx->Polygon.CullFaceMode );
     STATE_INIT(DepthFunc)( ctx, ctx->Depth.Func );
     STATE_INIT(DepthMask)( ctx, ctx->Depth.Mask );
-    STATE_INIT(DepthRange)( ctx, ctx->Viewport.Near, ctx->Viewport.Far );
 
     STATE_INIT(Enable)( ctx, GL_ALPHA_TEST, ctx->Color.AlphaEnabled );
     STATE_INIT(Enable)( ctx, GL_BLEND, ctx->Color.BlendEnabled );
@@ -320,8 +332,6 @@ void nouveauInitState(GLcontext *ctx)
            ctx->Polygon.OffsetFactor,
            ctx->Polygon.OffsetUnits );
     STATE_INIT(PolygonStipple)( ctx, (const GLubyte *)ctx->PolygonStipple );
-    STATE_INIT(Scissor)( ctx, ctx->Scissor.X, ctx->Scissor.Y,
-            ctx->Scissor.Width, ctx->Scissor.Height );
     STATE_INIT(ShadeModel)( ctx, ctx->Light.ShadeModel );
     STATE_INIT(StencilFuncSeparate)( ctx, GL_FRONT,
             ctx->Stencil.Function[0],
@@ -341,10 +351,4 @@ void nouveauInitState(GLcontext *ctx)
             ctx->Stencil.FailFunc[1],
             ctx->Stencil.ZFailFunc[1],
             ctx->Stencil.ZPassFunc[1]);
-
-    STATE_INIT(Viewport)( ctx,
-           ctx->Viewport.X, ctx->Viewport.Y,
-           ctx->Viewport.Width, ctx->Viewport.Height );
-
-    STATE_INIT(DrawBuffer)( ctx, ctx->Color.DrawBuffer[0] );
 }
index 37f04f4..16d63a6 100644 (file)
@@ -32,9 +32,9 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 extern void nouveauDDInitState(nouveauContextPtr nmesa);
 extern void nouveauDDInitStateFuncs(GLcontext *ctx);
 
-extern void nv10InitStateFuncs(struct dd_function_table *func);
-extern void nv20InitStateFuncs(struct dd_function_table *func);
-extern void nv30InitStateFuncs(struct dd_function_table *func);
+extern void nv10InitStateFuncs(GLcontext *ctx, struct dd_function_table *func);
+extern void nv20InitStateFuncs(GLcontext *ctx, struct dd_function_table *func);
+extern void nv30InitStateFuncs(GLcontext *ctx, struct dd_function_table *func);
 
 extern void nouveauInitState(GLcontext *ctx);
 
index 1c2664e..98aa27e 100644 (file)
@@ -10,6 +10,7 @@
 #include "nouveau_shader.h"
 #include "nouveau_object.h"
 #include "nouveau_msg.h"
+#include "nouveau_buffers.h"
 #include "nv30_shader.h"
 
 unsigned int NVFP_TX_AOP_COUNT = 64;
@@ -19,31 +20,22 @@ struct _op_xlat NVFP_TX_AOP[64];
  * Support routines
  */
 
-/*XXX: bad bad bad bad */
-static uint64_t         fragprog_ofs;
-static uint32_t *fragprog_buf = NULL;
-
 static void
 NV30FPUploadToHW(GLcontext *ctx, nouveauShader *nvs)
 {
    nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
    drm_nouveau_mem_alloc_t mem;
 
-   if (!fragprog_buf) {
-      mem.flags                = NOUVEAU_MEM_FB|NOUVEAU_MEM_MAPPED;
-      mem.size         = nvs->program_size * sizeof(uint32_t);
-      mem.alignment    = 0;
-      mem.region_offset        = &fragprog_ofs;
-      if (drmCommandWriteRead(nmesa->driFd, DRM_NOUVEAU_MEM_ALLOC, &mem,
-                             sizeof(mem))) {
-        fprintf(stderr, "MEM_ALLOC fail\n");
-        return;
-      }
+   if (!nvs->program_buffer) {
+      nouveau_mem *fpbuf;
 
-      if (drmMap(nmesa->driFd, fragprog_ofs, mem.size, &fragprog_buf)) {
-        fprintf(stderr, "MEM_MAP fail\n");
+      fpbuf = nouveau_mem_alloc(ctx, NOUVEAU_MEM_FB|NOUVEAU_MEM_MAPPED,
+                               nvs->program_size * sizeof(uint32_t), 0);
+      if (!fpbuf) {
+        fprintf(stderr, "fragprog vram alloc fail!\n");
         return;
       }
+      nvs->program_buffer = fpbuf;
    }
 
    /*XXX: should do a DMA.. and not copy over a possibly in-use program.. */
@@ -52,9 +44,10 @@ NV30FPUploadToHW(GLcontext *ctx, nouveauShader *nvs)
     * caches the program somewhere? so, maybe not so bad to just clobber the
     * old program in vram..
     */
-   memcpy(fragprog_buf, nvs->program, nvs->program_size * sizeof(uint32_t));
+   memcpy(nvs->program_buffer->map, nvs->program,
+         nvs->program_size * sizeof(uint32_t));
    BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_FP_ACTIVE_PROGRAM, 1);
-   OUT_RING(((uint32_t)fragprog_ofs-0xE0000000)|1);
+   OUT_RING(nouveau_mem_gpu_offset_get(ctx, nvs->program_buffer) | 1);
 }
 
 static void
index 3ffb5d3..3228320 100644 (file)
@@ -304,10 +304,16 @@ static void nv30Enable(GLcontext *ctx, GLenum cap, GLboolean state)
 //             case GL_POST_COLOR_MATRIX_COLOR_TABLE:
 //             case GL_POST_CONVOLUTION_COLOR_TABLE:
 //             case GL_RESCALE_NORMAL:
-//             case GL_SCISSOR_TEST:
+               case GL_SCISSOR_TEST:
+                       /* No enable bit, nv30Scissor will adjust to max range */
+                       ctx->Driver.Scissor(ctx, ctx->Scissor.X, ctx->Scissor.Y,
+                                                ctx->Scissor.Width, ctx->Scissor.Height);
+                       break;
 //             case GL_SEPARABLE_2D:
                case GL_STENCIL_TEST:
                        // TODO BACK and FRONT ?
+                       BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_STENCIL_FRONT_ENABLE, 1);
+                       OUT_RING_CACHE(state);
                        BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_STENCIL_BACK_ENABLE, 1);
                        OUT_RING_CACHE(state);
                        break;
@@ -514,9 +520,26 @@ void (*RenderMode)(GLcontext *ctx, GLenum mode );
 static void nv30Scissor(GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h)
 {
         nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+       nouveau_renderbuffer *nrb;
+
+       /* Adjust offsets if drawing to a window */
+       nrb = nouveau_current_draw_buffer(ctx);
+       if (nrb && nrb->map) {
+          x += nrb->dPriv->x;
+          y += nrb->dPriv->y;
+       }
+
+       /* There's no scissor enable bit, so adjust the scissor to cover the
+        * maximum draw buffer bounds
+        */
+       if (!ctx->Scissor.Enabled) {
+          x = y = 0;
+          w = h = 4095;
+       }
+
         BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_SCISSOR_WIDTH_XPOS, 2);
-        OUT_RING_CACHE((w << 16) | x);
-        OUT_RING_CACHE((h << 16) | y);
+        OUT_RING_CACHE(((w) << 16) | x);
+        OUT_RING_CACHE(((h) << 16) | y);
 }
 
 /** Select flat or smooth shading */
@@ -602,18 +625,117 @@ static void nv30TextureMatrix(GLcontext *ctx, GLuint unit, const GLmatrix *mat)
         OUT_RING_CACHEp(mat->m, 16);
 }
 
-/** Set the viewport */
-static void nv30Viewport(GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h)
+static void nv30WindowMoved(nouveauContextPtr nmesa)
 {
-        /* TODO: Where do the VIEWPORT_XFRM_* regs come in? */
-        nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+       GLcontext *ctx = nmesa->glCtx;
+       nouveau_renderbuffer *nrb;
+       GLfloat *v = nmesa->viewport.m;
+       GLuint w = ctx->Viewport.Width;
+       GLuint h = ctx->Viewport.Height;
+       GLuint x = ctx->Viewport.X;
+       GLuint y = ctx->Viewport.Y;
+
+       /* Adjust offsets if drawing to a window */
+       nrb = nouveau_current_draw_buffer(ctx);
+       if (nrb && nrb->map) {
+          x += nrb->dPriv->x;
+          y += nrb->dPriv->y;
+       }
+
         BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_VIEWPORT_DIMS_0, 2);
         OUT_RING_CACHE((w << 16) | x);
         OUT_RING_CACHE((h << 16) | y);
-}
-
-void nv30InitStateFuncs(struct dd_function_table *func)
+       /* something to do with clears, possibly doesn't belong here */
+       BEGIN_RING_CACHE(NvSub3D,
+             NV30_TCL_PRIMITIVE_3D_VIEWPORT_COLOR_BUFFER_OFS0, 2);
+        OUT_RING_CACHE(((w+x) << 16) | x);
+        OUT_RING_CACHE(((h+y) << 16) | y);
+       /* viewport transform */
+       BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_VIEWPORT_XFRM_OX, 8);
+       OUT_RING_CACHEf (v[MAT_TX]);
+       OUT_RING_CACHEf (v[MAT_TY]);
+       OUT_RING_CACHEf (v[MAT_TZ]);
+       OUT_RING_CACHEf (0.0);
+       OUT_RING_CACHEf (v[MAT_SX]);
+       OUT_RING_CACHEf (v[MAT_SY]);
+       OUT_RING_CACHEf (v[MAT_SZ]);
+       OUT_RING_CACHEf (0.0);
+
+       ctx->Driver.Scissor(ctx, ctx->Scissor.X, ctx->Scissor.Y,
+                           ctx->Scissor.Width, ctx->Scissor.Height);
+}
+
+static GLboolean nv30InitCard(nouveauContextPtr nmesa)
+{
+       /* Need some love.. */
+       return GL_FALSE;
+}
+
+static GLboolean nv40InitCard(nouveauContextPtr nmesa)
+{
+       nouveauObjectOnSubchannel(nmesa, NvSub3D, Nv3D);
+
+       BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_SET_OBJECT1, 2);
+       OUT_RING(NvDmaFB);
+       OUT_RING(NvDmaFB);
+       BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_SET_OBJECT8, 1);
+       OUT_RING(NvDmaFB);
+       BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_SET_OBJECT4, 2);
+       OUT_RING(NvDmaFB);
+       OUT_RING(NvDmaFB);
+       BEGIN_RING_SIZE(NvSub3D, 0x0220, 1);
+       OUT_RING(1);
+       BEGIN_RING_SIZE(NvSub3D, 0x1fc8, 2);
+       OUT_RING(0xedcba987);
+       OUT_RING(0x00000021);
+       BEGIN_RING_SIZE(NvSub3D, 0x1d60, 1);
+       OUT_RING(0x03008000);
+
+       return GL_TRUE;
+}
+
+static GLboolean nv30BindBuffers(nouveauContextPtr nmesa, int num_color,
+                                nouveau_renderbuffer **color,
+                                nouveau_renderbuffer *depth)
+{
+   nouveau_renderbuffer *nrb;
+   GLuint x, y, w, h;
+
+   /* Adjust offsets if drawing to a window */
+   nrb = nouveau_current_draw_buffer(nmesa->glCtx);
+   w = nrb->mesa.Width;
+   h = nrb->mesa.Height;
+   if (nrb && nrb->map) {
+      x = nrb->dPriv->x;
+      y = nrb->dPriv->y;
+   } else {
+      x = 0;
+      y = 0;
+   }
+
+   if (num_color != 1)
+      return GL_FALSE;
+   BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_VIEWPORT_COLOR_BUFFER_DIM0, 5);
+   OUT_RING        (((w+x)<<16)|x);
+   OUT_RING        (((h+y)<<16)|y);
+   OUT_RING        (0x148);
+   OUT_RING        (color[0]->pitch);
+   OUT_RING        (color[0]->offset);
+
+   if (depth) {
+      BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_DEPTH_OFFSET, 1);
+      OUT_RING        (depth->offset);
+      BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_LMA_DEPTH_BUFFER_PITCH, 1);
+      OUT_RING        (depth->pitch);
+   }
+
+   return GL_TRUE;
+}
+
+void nv30InitStateFuncs(GLcontext *ctx, struct dd_function_table *func)
 {
+       nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+
        func->AlphaFunc                 = nv30AlphaFunc;
        func->BlendColor                = nv30BlendColor;
        func->BlendEquationSeparate     = nv30BlendEquationSeparate;
@@ -628,7 +750,6 @@ void nv30InitStateFuncs(struct dd_function_table *func)
        func->FrontFace                 = nv30FrontFace;
        func->DepthFunc                 = nv30DepthFunc;
        func->DepthMask                 = nv30DepthMask;
-       func->DepthRange                = nv30DepthRange;
        func->Enable                    = nv30Enable;
        func->Fogfv                     = nv30Fogfv;
        func->Hint                      = nv30Hint;
@@ -656,6 +777,13 @@ void nv30InitStateFuncs(struct dd_function_table *func)
        func->TexParameter              = nv30TexParameter;
 #endif
        func->TextureMatrix             = nv30TextureMatrix;
-       func->Viewport                  = nv30Viewport;
+
+
+       if (nmesa->screen->card->type >= NV_40)
+          nmesa->hw_func.InitCard      = nv40InitCard;
+       else 
+          nmesa->hw_func.InitCard      = nv30InitCard;
+       nmesa->hw_func.BindBuffers      = nv30BindBuffers;
+       nmesa->hw_func.WindowMoved      = nv30WindowMoved;
 }