Merge branch 'mesa_7_6_branch'
[mesa.git] / src / mesa / drivers / osmesa / osmesa.c
index 2b64010c80d624e0d1765f56971c9e4fbe290f83..692657a5dfd626796240b73098899e159766104c 100644 (file)
@@ -1,8 +1,8 @@
 /*
  * Mesa 3-D graphics library
- * Version:  5.1
+ * Version:  6.5.3
  *
- * Copyright (C) 1999-2003  Brian Paul   All Rights Reserved.
+ * Copyright (C) 1999-2007  Brian Paul   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"),
  */
 
 
-#include "glheader.h"
+#include "main/glheader.h"
 #include "GL/osmesa.h"
-#include "buffers.h"
-#include "bufferobj.h"
-#include "context.h"
-#include "colormac.h"
-#include "depth.h"
-#include "extensions.h"
-#include "imports.h"
-#include "macros.h"
-#include "matrix.h"
-#include "mtypes.h"
-#include "texformat.h"
-#include "texobj.h"
-#include "teximage.h"
-#include "texstore.h"
-#include "array_cache/acache.h"
+#include "main/context.h"
+#include "main/extensions.h"
+#include "main/framebuffer.h"
+#include "main/imports.h"
+#include "main/mtypes.h"
+#include "main/renderbuffer.h"
 #include "swrast/swrast.h"
 #include "swrast_setup/swrast_setup.h"
 #include "swrast/s_context.h"
-#include "swrast/s_depth.h"
 #include "swrast/s_lines.h"
 #include "swrast/s_triangle.h"
 #include "tnl/tnl.h"
 #include "tnl/t_context.h"
 #include "tnl/t_pipeline.h"
+#include "drivers/common/driverfuncs.h"
+#include "drivers/common/meta.h"
+#include "vbo/vbo.h"
 
 
 
-/*
- * This is the OS/Mesa context struct.
- * Notice how it includes a GLcontext.  By doing this we're mimicking
- * C++ inheritance/derivation.
- * Later, we can cast a GLcontext pointer into an OSMesaContext pointer
- * or vice versa.
+/**
+ * OSMesa rendering context, derived from core Mesa GLcontext.
  */
-struct osmesa_context {
-   GLcontext mesa;             /* The core GL/Mesa context */
-   GLvisual *gl_visual;                /* Describes the buffers */
-   GLframebuffer *gl_buffer;   /* Depth, stencil, accum, etc buffers */
-   GLenum format;              /* either GL_RGBA or GL_COLOR_INDEX */
-   void *buffer;               /* the image buffer */
-   GLint width, height;                /* size of image buffer */
-   GLint rowlength;            /* number of pixels per row */
-   GLint userRowLength;                /* user-specified number of pixels per row */
-   GLint rshift, gshift;       /* bit shifts for RGBA formats */
-   GLint bshift, ashift;
-   GLint rInd, gInd, bInd, aInd;/* index offsets for RGBA formats */
-   GLchan *rowaddr[MAX_HEIGHT];        /* address of first pixel in each image row */
-   GLboolean yup;              /* TRUE  -> Y increases upward */
-                               /* FALSE -> Y increases downward */
+struct osmesa_context
+{
+   GLcontext mesa;             /*< Base class - this must be first */
+   GLvisual *gl_visual;                /*< Describes the buffers */
+   struct gl_renderbuffer *rb;  /*< The user's colorbuffer */
+   GLframebuffer *gl_buffer;   /*< The framebuffer, containing user's rb */
+   GLenum format;              /*< User-specified context format */
+   GLint userRowLength;                /*< user-specified number of pixels per row */
+   GLint rInd, gInd, bInd, aInd;/*< index offsets for RGBA formats */
+   GLvoid *rowaddr[MAX_HEIGHT];        /*< address of first pixel in each image row */
+   GLboolean yup;              /*< TRUE  -> Y increases upward */
+                               /*< FALSE -> Y increases downward */
 };
 
 
-/* Just cast, since we're using structure containment */
-#define OSMESA_CONTEXT(ctx)  ((OSMesaContext) (ctx->DriverCtx))
-
+static INLINE OSMesaContext
+OSMESA_CONTEXT(GLcontext *ctx)
+{
+   /* Just cast, since we're using structure containment */
+   return (OSMesaContext) ctx;
+}
 
 
 /**********************************************************************/
@@ -122,238 +111,401 @@ osmesa_update_state( GLcontext *ctx, GLuint new_state )
    /* easy - just propogate */
    _swrast_InvalidateState( ctx, new_state );
    _swsetup_InvalidateState( ctx, new_state );
-   _ac_InvalidateState( ctx, new_state );
    _tnl_InvalidateState( ctx, new_state );
+   _vbo_InvalidateState( ctx, new_state );
 }
 
 
-static void
-set_buffer( GLcontext *ctx, GLframebuffer *buffer, GLuint bufferBit )
-{
-   /* separate read buffer not supported */
-   ASSERT(buffer == ctx->DrawBuffer);
-   ASSERT(bufferBit == FRONT_LEFT_BIT);
-}
-
-
-static void
-get_buffer_size( GLframebuffer *buffer, GLuint *width, GLuint *height )
-{
-   /* don't use GET_CURRENT_CONTEXT(ctx) here - it's a problem on Windows */
-   GLcontext *ctx = (GLcontext *) _glapi_get_context();
-   (void) buffer;
-   if (ctx) {
-      OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
-      *width = osmesa->width;
-      *height = osmesa->height;
-   }
-}
 
+/**********************************************************************/
+/*****        Read/write spans/arrays of pixels                   *****/
+/**********************************************************************/
 
-static void
-clear( GLcontext *ctx, GLbitfield mask, GLboolean all,
-       GLint x, GLint y, GLint width, GLint height )
-{
-   OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
-   const GLuint *colorMask = (GLuint *) &ctx->Color.ColorMask;
-
-   /* sanity check - we only have a front-left buffer */
-   ASSERT((mask & (DD_FRONT_RIGHT_BIT |
-                   DD_BACK_LEFT_BIT |
-                   DD_BACK_RIGHT_BIT)) == 0);
-
-   /* use optimized clear for common cases (clear whole buffer to black) */
-   if (mask & DD_FRONT_LEFT_BIT) {
-      if (osmesa->format == OSMESA_COLOR_INDEX) {
-         if (ctx->Color.ClearIndex == 0 &&
-             ctx->Color.IndexMask == (GLuint) ~0 &&
-             osmesa->rowlength == osmesa->width &&
-             all) {
-            /* clear whole buffer to zeros */
-            _mesa_bzero(osmesa->buffer,
-                        osmesa->width * osmesa->height * sizeof(GLchan));
-            mask &= ~DD_FRONT_LEFT_BIT;
-         }
-      }
-      else {
-         /* RGB[A] format */
-         if (*colorMask == 0xffffffff &&
-             ctx->Color.ClearColor[0] == 0.0F &&
-             ctx->Color.ClearColor[1] == 0.0F &&
-             ctx->Color.ClearColor[2] == 0.0F &&
-             ctx->Color.ClearColor[3] == 0.0F &&
-             osmesa->rowlength == osmesa->width &&
-             all) {
-            GLint bytesPerPixel;
-            /* clear whole buffer to black */
-            if (osmesa->format == OSMESA_RGBA ||
-                osmesa->format == OSMESA_BGRA ||
-                osmesa->format == OSMESA_ARGB)
-               bytesPerPixel = 4 * sizeof(GLchan);
-            else if (osmesa->format == OSMESA_RGB ||
-                     osmesa->format == OSMESA_BGR)
-               bytesPerPixel = 3 * sizeof(GLchan);
-            else if (osmesa->format == OSMESA_RGB_565)
-               bytesPerPixel = sizeof(GLushort);
-            else {
-               _mesa_problem(ctx, "bad pixel format in osmesa_clear()");
-               return;
-            }
-            _mesa_bzero(osmesa->buffer,
-                        bytesPerPixel * osmesa->width * osmesa->height);
-            mask &= ~DD_FRONT_LEFT_BIT;
-         }
-      }
-   }
+/* 8-bit RGBA */
+#define NAME(PREFIX) PREFIX##_RGBA8
+#define RB_TYPE GLubyte
+#define SPAN_VARS \
+   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
+#define INIT_PIXEL_PTR(P, X, Y) \
+   GLubyte *P = (GLubyte *) osmesa->rowaddr[Y] + 4 * (X)
+#define INC_PIXEL_PTR(P) P += 4
+#define STORE_PIXEL(DST, X, Y, VALUE) \
+   DST[0] = VALUE[RCOMP];  \
+   DST[1] = VALUE[GCOMP];  \
+   DST[2] = VALUE[BCOMP];  \
+   DST[3] = VALUE[ACOMP]
+#define STORE_PIXEL_RGB(DST, X, Y, VALUE) \
+   DST[0] = VALUE[RCOMP];  \
+   DST[1] = VALUE[GCOMP];  \
+   DST[2] = VALUE[BCOMP];  \
+   DST[3] = 255
+#define FETCH_PIXEL(DST, SRC) \
+   DST[RCOMP] = SRC[0];  \
+   DST[GCOMP] = SRC[1];  \
+   DST[BCOMP] = SRC[2];  \
+   DST[ACOMP] = SRC[3]
+#include "swrast/s_spantemp.h"
 
-   if (mask) {
-      /* software fallback (spans) for everything else. */
-      _swrast_Clear(ctx, mask, all, x, y, width, height);
-   }
-}
+/* 16-bit RGBA */
+#define NAME(PREFIX) PREFIX##_RGBA16
+#define RB_TYPE GLushort
+#define SPAN_VARS \
+   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
+#define INIT_PIXEL_PTR(P, X, Y) \
+   GLushort *P = (GLushort *) osmesa->rowaddr[Y] + 4 * (X)
+#define INC_PIXEL_PTR(P) P += 4
+#define STORE_PIXEL(DST, X, Y, VALUE) \
+   DST[0] = VALUE[RCOMP];  \
+   DST[1] = VALUE[GCOMP];  \
+   DST[2] = VALUE[BCOMP];  \
+   DST[3] = VALUE[ACOMP]
+#define STORE_PIXEL_RGB(DST, X, Y, VALUE) \
+   DST[0] = VALUE[RCOMP];  \
+   DST[1] = VALUE[GCOMP];  \
+   DST[2] = VALUE[BCOMP];  \
+   DST[3] = 65535
+#define FETCH_PIXEL(DST, SRC) \
+   DST[RCOMP] = SRC[0];  \
+   DST[GCOMP] = SRC[1];  \
+   DST[BCOMP] = SRC[2];  \
+   DST[ACOMP] = SRC[3]
+#include "swrast/s_spantemp.h"
 
+/* 32-bit RGBA */
+#define NAME(PREFIX) PREFIX##_RGBA32
+#define RB_TYPE GLfloat
+#define SPAN_VARS \
+   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
+#define INIT_PIXEL_PTR(P, X, Y) \
+   GLfloat *P = (GLfloat *) osmesa->rowaddr[Y] + 4 * (X)
+#define INC_PIXEL_PTR(P) P += 4
+#define STORE_PIXEL(DST, X, Y, VALUE) \
+   DST[0] = MAX2((VALUE[RCOMP]), 0.0F); \
+   DST[1] = MAX2((VALUE[GCOMP]), 0.0F); \
+   DST[2] = MAX2((VALUE[BCOMP]), 0.0F); \
+   DST[3] = CLAMP((VALUE[ACOMP]), 0.0F, 1.0F)
+#define STORE_PIXEL_RGB(DST, X, Y, VALUE) \
+   DST[0] = MAX2((VALUE[RCOMP]), 0.0F); \
+   DST[1] = MAX2((VALUE[GCOMP]), 0.0F); \
+   DST[2] = MAX2((VALUE[BCOMP]), 0.0F); \
+   DST[3] = 1.0F
+#define FETCH_PIXEL(DST, SRC) \
+   DST[RCOMP] = SRC[0];  \
+   DST[GCOMP] = SRC[1];  \
+   DST[BCOMP] = SRC[2];  \
+   DST[ACOMP] = SRC[3]
+#include "swrast/s_spantemp.h"
 
-/**********************************************************************/
-/*****        Read/write spans/arrays of pixels                   *****/
-/**********************************************************************/
 
+/* 8-bit BGRA */
+#define NAME(PREFIX) PREFIX##_BGRA8
+#define RB_TYPE GLubyte
+#define SPAN_VARS \
+   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
+#define INIT_PIXEL_PTR(P, X, Y) \
+   GLubyte *P = (GLubyte *) osmesa->rowaddr[Y] + 4 * (X)
+#define INC_PIXEL_PTR(P) P += 4
+#define STORE_PIXEL(DST, X, Y, VALUE) \
+   DST[2] = VALUE[RCOMP];  \
+   DST[1] = VALUE[GCOMP];  \
+   DST[0] = VALUE[BCOMP];  \
+   DST[3] = VALUE[ACOMP]
+#define STORE_PIXEL_RGB(DST, X, Y, VALUE) \
+   DST[2] = VALUE[RCOMP];  \
+   DST[1] = VALUE[GCOMP];  \
+   DST[0] = VALUE[BCOMP];  \
+   DST[3] = 255
+#define FETCH_PIXEL(DST, SRC) \
+   DST[RCOMP] = SRC[2];  \
+   DST[GCOMP] = SRC[1];  \
+   DST[BCOMP] = SRC[0];  \
+   DST[ACOMP] = SRC[3]
+#include "swrast/s_spantemp.h"
 
-/* RGBA */
-#define NAME(PREFIX) PREFIX##_RGBA
+/* 16-bit BGRA */
+#define NAME(PREFIX) PREFIX##_BGRA16
+#define RB_TYPE GLushort
 #define SPAN_VARS \
    const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
 #define INIT_PIXEL_PTR(P, X, Y) \
-   GLchan *P = osmesa->rowaddr[Y] + 4 * (X)
+   GLushort *P = (GLushort *) osmesa->rowaddr[Y] + 4 * (X)
 #define INC_PIXEL_PTR(P) P += 4
-#if CHAN_TYPE == GL_FLOAT
-#define STORE_RGB_PIXEL(P, X, Y, R, G, B) \
-   P[0] = MAX2((R), 0.0F); \
-   P[1] = MAX2((G), 0.0F); \
-   P[2] = MAX2((B), 0.0F); \
-   P[3] = CHAN_MAXF
-#define STORE_RGBA_PIXEL(P, X, Y, R, G, B, A) \
-   P[0] = MAX2((R), 0.0F); \
-   P[1] = MAX2((G), 0.0F); \
-   P[2] = MAX2((B), 0.0F); \
-   P[3] = CLAMP((A), 0.0F, CHAN_MAXF)
-#else
-#define STORE_RGB_PIXEL(P, X, Y, R, G, B) \
-   P[0] = R;  P[1] = G;  P[2] = B;  P[3] = CHAN_MAX
-#define STORE_RGBA_PIXEL(P, X, Y, R, G, B, A) \
-   P[0] = R;  P[1] = G;  P[2] = B;  P[3] = A
-#endif
-#define FETCH_RGBA_PIXEL(R, G, B, A, P) \
-   R = P[0];  G = P[1];  B = P[2];  A = P[3]
+#define STORE_PIXEL(DST, X, Y, VALUE) \
+   DST[2] = VALUE[RCOMP];  \
+   DST[1] = VALUE[GCOMP];  \
+   DST[0] = VALUE[BCOMP];  \
+   DST[3] = VALUE[ACOMP]
+#define STORE_PIXEL_RGB(DST, X, Y, VALUE) \
+   DST[2] = VALUE[RCOMP];  \
+   DST[1] = VALUE[GCOMP];  \
+   DST[0] = VALUE[BCOMP];  \
+   DST[3] = 65535
+#define FETCH_PIXEL(DST, SRC) \
+   DST[RCOMP] = SRC[2];  \
+   DST[GCOMP] = SRC[1];  \
+   DST[BCOMP] = SRC[0];  \
+   DST[ACOMP] = SRC[3]
 #include "swrast/s_spantemp.h"
 
-/* BGRA */
-#define NAME(PREFIX) PREFIX##_BGRA
+/* 32-bit BGRA */
+#define NAME(PREFIX) PREFIX##_BGRA32
+#define RB_TYPE GLfloat
 #define SPAN_VARS \
    const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
 #define INIT_PIXEL_PTR(P, X, Y) \
-   GLchan *P = osmesa->rowaddr[Y] + 4 * (X)
+   GLfloat *P = (GLfloat *) osmesa->rowaddr[Y] + 4 * (X)
 #define INC_PIXEL_PTR(P) P += 4
-#define STORE_RGB_PIXEL(P, X, Y, R, G, B) \
-   P[2] = R;  P[1] = G;  P[0] = B;  P[3] = CHAN_MAX
-#define STORE_RGBA_PIXEL(P, X, Y, R, G, B, A) \
-   P[2] = R;  P[1] = G;  P[0] = B;  P[3] = A
-#define FETCH_RGBA_PIXEL(R, G, B, A, P) \
-   R = P[2];  G = P[1];  B = P[0];  A = P[3]
+#define STORE_PIXEL(DST, X, Y, VALUE) \
+   DST[2] = VALUE[RCOMP];  \
+   DST[1] = VALUE[GCOMP];  \
+   DST[0] = VALUE[BCOMP];  \
+   DST[3] = VALUE[ACOMP]
+#define STORE_PIXEL_RGB(DST, X, Y, VALUE) \
+   DST[2] = VALUE[RCOMP];  \
+   DST[1] = VALUE[GCOMP];  \
+   DST[0] = VALUE[BCOMP];  \
+   DST[3] = 1.0F
+#define FETCH_PIXEL(DST, SRC) \
+   DST[RCOMP] = SRC[2];  \
+   DST[GCOMP] = SRC[1];  \
+   DST[BCOMP] = SRC[0];  \
+   DST[ACOMP] = SRC[3]
 #include "swrast/s_spantemp.h"
 
-/* ARGB */
-#define NAME(PREFIX) PREFIX##_ARGB
+
+/* 8-bit ARGB */
+#define NAME(PREFIX) PREFIX##_ARGB8
+#define RB_TYPE GLubyte
 #define SPAN_VARS \
    const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
 #define INIT_PIXEL_PTR(P, X, Y) \
-   GLchan *P = osmesa->rowaddr[Y] + 4 * (X)
+   GLubyte *P = (GLubyte *) osmesa->rowaddr[Y] + 4 * (X)
 #define INC_PIXEL_PTR(P) P += 4
-#define STORE_RGB_PIXEL(P, X, Y, R, G, B) \
-   P[1] = R;  P[2] = G;  P[3] = B;  P[0] = CHAN_MAX
-#define STORE_RGBA_PIXEL(P, X, Y, R, G, B, A) \
-   P[1] = R;  P[2] = G;  P[3] = B;  P[0] = A
-#define FETCH_RGBA_PIXEL(R, G, B, A, P) \
-   R = P[1];  G = P[2];  B = P[3];  A = P[0]
+#define STORE_PIXEL(DST, X, Y, VALUE) \
+   DST[1] = VALUE[RCOMP];  \
+   DST[2] = VALUE[GCOMP];  \
+   DST[3] = VALUE[BCOMP];  \
+   DST[0] = VALUE[ACOMP]
+#define STORE_PIXEL_RGB(DST, X, Y, VALUE) \
+   DST[1] = VALUE[RCOMP];  \
+   DST[2] = VALUE[GCOMP];  \
+   DST[3] = VALUE[BCOMP];  \
+   DST[0] = 255
+#define FETCH_PIXEL(DST, SRC) \
+   DST[RCOMP] = SRC[1];  \
+   DST[GCOMP] = SRC[2];  \
+   DST[BCOMP] = SRC[3];  \
+   DST[ACOMP] = SRC[0]
 #include "swrast/s_spantemp.h"
 
-/* RGB */
-#define NAME(PREFIX) PREFIX##_RGB
+/* 16-bit ARGB */
+#define NAME(PREFIX) PREFIX##_ARGB16
+#define RB_TYPE GLushort
 #define SPAN_VARS \
    const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
 #define INIT_PIXEL_PTR(P, X, Y) \
-   GLchan *P = osmesa->rowaddr[Y] + 4 * (X)
+   GLushort *P = (GLushort *) osmesa->rowaddr[Y] + 4 * (X)
 #define INC_PIXEL_PTR(P) P += 4
-#define STORE_RGB_PIXEL(P, X, Y, R, G, B) \
-   P[0] = R;  P[1] = G;  P[2] = B
-#define STORE_RGBA_PIXEL(P, X, Y, R, G, B, A) \
-   P[0] = R;  P[1] = G;  P[2] = B
-#define FETCH_RGBA_PIXEL(R, G, B, A, P) \
-   R = P[0];  G = P[1];  B = P[2];  A = CHAN_MAX
+#define STORE_PIXEL(DST, X, Y, VALUE) \
+   DST[1] = VALUE[RCOMP];  \
+   DST[2] = VALUE[GCOMP];  \
+   DST[3] = VALUE[BCOMP];  \
+   DST[0] = VALUE[ACOMP]
+#define STORE_PIXEL_RGB(DST, X, Y, VALUE) \
+   DST[1] = VALUE[RCOMP];  \
+   DST[2] = VALUE[GCOMP];  \
+   DST[3] = VALUE[BCOMP];  \
+   DST[0] = 65535
+#define FETCH_PIXEL(DST, SRC) \
+   DST[RCOMP] = SRC[1];  \
+   DST[GCOMP] = SRC[2];  \
+   DST[BCOMP] = SRC[3];  \
+   DST[ACOMP] = SRC[0]
 #include "swrast/s_spantemp.h"
 
-/* BGR */
-#define NAME(PREFIX) PREFIX##_BGR
+/* 32-bit ARGB */
+#define NAME(PREFIX) PREFIX##_ARGB32
+#define RB_TYPE GLfloat
 #define SPAN_VARS \
    const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
 #define INIT_PIXEL_PTR(P, X, Y) \
-   GLchan *P = osmesa->rowaddr[Y] + 4 * (X)
+   GLfloat *P = (GLfloat *) osmesa->rowaddr[Y] + 4 * (X)
 #define INC_PIXEL_PTR(P) P += 4
-#define STORE_RGB_PIXEL(P, X, Y, R, G, B) \
-   P[0] = B;  P[1] = G;  P[2] = R
-#define STORE_RGBA_PIXEL(P, X, Y, R, G, B, A) \
-   P[0] = B;  P[1] = G;  P[2] = R
-#define FETCH_RGBA_PIXEL(R, G, B, A, P) \
-   B = P[0];  G = P[1];  R = P[2];  A = CHAN_MAX
+#define STORE_PIXEL(DST, X, Y, VALUE) \
+   DST[1] = VALUE[RCOMP];  \
+   DST[2] = VALUE[GCOMP];  \
+   DST[3] = VALUE[BCOMP];  \
+   DST[0] = VALUE[ACOMP]
+#define STORE_PIXEL_RGB(DST, X, Y, VALUE) \
+   DST[1] = VALUE[RCOMP];  \
+   DST[2] = VALUE[GCOMP];  \
+   DST[3] = VALUE[BCOMP];  \
+   DST[0] = 1.0F
+#define FETCH_PIXEL(DST, SRC) \
+   DST[RCOMP] = SRC[1];  \
+   DST[GCOMP] = SRC[2];  \
+   DST[BCOMP] = SRC[3];  \
+   DST[ACOMP] = SRC[0]
+#include "swrast/s_spantemp.h"
+
+
+/* 8-bit RGB */
+#define NAME(PREFIX) PREFIX##_RGB8
+#define RB_TYPE GLubyte
+#define SPAN_VARS \
+   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
+#define INIT_PIXEL_PTR(P, X, Y) \
+   GLubyte *P = (GLubyte *) osmesa->rowaddr[Y] + 3 * (X)
+#define INC_PIXEL_PTR(P) P += 3
+#define STORE_PIXEL(DST, X, Y, VALUE) \
+   DST[0] = VALUE[RCOMP];  \
+   DST[1] = VALUE[GCOMP];  \
+   DST[2] = VALUE[BCOMP]
+#define FETCH_PIXEL(DST, SRC) \
+   DST[RCOMP] = SRC[0];  \
+   DST[GCOMP] = SRC[1];  \
+   DST[BCOMP] = SRC[2];  \
+   DST[ACOMP] = 255
+#include "swrast/s_spantemp.h"
+
+/* 16-bit RGB */
+#define NAME(PREFIX) PREFIX##_RGB16
+#define RB_TYPE GLushort
+#define SPAN_VARS \
+   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
+#define INIT_PIXEL_PTR(P, X, Y) \
+   GLushort *P = (GLushort *) osmesa->rowaddr[Y] + 3 * (X)
+#define INC_PIXEL_PTR(P) P += 3
+#define STORE_PIXEL(DST, X, Y, VALUE) \
+   DST[0] = VALUE[RCOMP];  \
+   DST[1] = VALUE[GCOMP];  \
+   DST[2] = VALUE[BCOMP]
+#define FETCH_PIXEL(DST, SRC) \
+   DST[RCOMP] = SRC[0];  \
+   DST[GCOMP] = SRC[1];  \
+   DST[BCOMP] = SRC[2];  \
+   DST[ACOMP] = 65535U
+#include "swrast/s_spantemp.h"
+
+/* 32-bit RGB */
+#define NAME(PREFIX) PREFIX##_RGB32
+#define RB_TYPE GLfloat
+#define SPAN_VARS \
+   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
+#define INIT_PIXEL_PTR(P, X, Y) \
+   GLfloat *P = (GLfloat *) osmesa->rowaddr[Y] + 3 * (X)
+#define INC_PIXEL_PTR(P) P += 3
+#define STORE_PIXEL(DST, X, Y, VALUE) \
+   DST[0] = VALUE[RCOMP];  \
+   DST[1] = VALUE[GCOMP];  \
+   DST[2] = VALUE[BCOMP]
+#define FETCH_PIXEL(DST, SRC) \
+   DST[RCOMP] = SRC[0];  \
+   DST[GCOMP] = SRC[1];  \
+   DST[BCOMP] = SRC[2];  \
+   DST[ACOMP] = 1.0F
+#include "swrast/s_spantemp.h"
+
+
+/* 8-bit BGR */
+#define NAME(PREFIX) PREFIX##_BGR8
+#define RB_TYPE GLubyte
+#define SPAN_VARS \
+   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
+#define INIT_PIXEL_PTR(P, X, Y) \
+   GLubyte *P = (GLubyte *) osmesa->rowaddr[Y] + 3 * (X)
+#define INC_PIXEL_PTR(P) P += 3
+#define STORE_PIXEL(DST, X, Y, VALUE) \
+   DST[2] = VALUE[RCOMP];  \
+   DST[1] = VALUE[GCOMP];  \
+   DST[0] = VALUE[BCOMP]
+#define FETCH_PIXEL(DST, SRC) \
+   DST[RCOMP] = SRC[2];  \
+   DST[GCOMP] = SRC[1];  \
+   DST[BCOMP] = SRC[0];  \
+   DST[ACOMP] = 255
 #include "swrast/s_spantemp.h"
 
 /* 16-bit BGR */
-#if CHAN_TYPE == GL_UNSIGNED_BYTE
+#define NAME(PREFIX) PREFIX##_BGR16
+#define RB_TYPE GLushort
+#define SPAN_VARS \
+   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
+#define INIT_PIXEL_PTR(P, X, Y) \
+   GLushort *P = (GLushort *) osmesa->rowaddr[Y] + 3 * (X)
+#define INC_PIXEL_PTR(P) P += 3
+#define STORE_PIXEL(DST, X, Y, VALUE) \
+   DST[2] = VALUE[RCOMP];  \
+   DST[1] = VALUE[GCOMP];  \
+   DST[0] = VALUE[BCOMP]
+#define FETCH_PIXEL(DST, SRC) \
+   DST[RCOMP] = SRC[2];  \
+   DST[GCOMP] = SRC[1];  \
+   DST[BCOMP] = SRC[0];  \
+   DST[ACOMP] = 65535
+#include "swrast/s_spantemp.h"
+
+/* 32-bit BGR */
+#define NAME(PREFIX) PREFIX##_BGR32
+#define RB_TYPE GLfloat
+#define SPAN_VARS \
+   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
+#define INIT_PIXEL_PTR(P, X, Y) \
+   GLfloat *P = (GLfloat *) osmesa->rowaddr[Y] + 3 * (X)
+#define INC_PIXEL_PTR(P) P += 3
+#define STORE_PIXEL(DST, X, Y, VALUE) \
+   DST[2] = VALUE[RCOMP];  \
+   DST[1] = VALUE[GCOMP];  \
+   DST[0] = VALUE[BCOMP]
+#define FETCH_PIXEL(DST, SRC) \
+   DST[RCOMP] = SRC[2];  \
+   DST[GCOMP] = SRC[1];  \
+   DST[BCOMP] = SRC[0];  \
+   DST[ACOMP] = 1.0F
+#include "swrast/s_spantemp.h"
+
+
+/* 16-bit 5/6/5 RGB */
 #define NAME(PREFIX) PREFIX##_RGB_565
+#define RB_TYPE GLubyte
 #define SPAN_VARS \
    const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
 #define INIT_PIXEL_PTR(P, X, Y) \
    GLushort *P = (GLushort *) osmesa->rowaddr[Y] + (X)
 #define INC_PIXEL_PTR(P) P += 1
-#define STORE_RGB_PIXEL(P, X, Y, R, G, B) \
-   *P = ( (((R) & 0xf8) << 8) | (((G) & 0xfc) << 3) | ((B) >> 3) )
-#define STORE_RGBA_PIXEL(P, X, Y, R, G, B, A) \
-   *P = ( (((R) & 0xf8) << 8) | (((G) & 0xfc) << 3) | ((B) >> 3) )
-#define FETCH_RGBA_PIXEL(R, G, B, A, P) \
-   R = ( (((*P) >> 8) & 0xf8) | (((*P) >> 11) & 0x7) ); \
-   G = ( (((*P) >> 3) & 0xfc) | (((*P) >>  5) & 0x3) ); \
-   B = ( (((*P) << 3) & 0xf8) | (((*P)      ) & 0x7) ); \
-   A = CHAN_MAX
+#define STORE_PIXEL(DST, X, Y, VALUE) \
+   *DST = ( (((VALUE[RCOMP]) & 0xf8) << 8) | (((VALUE[GCOMP]) & 0xfc) << 3) | ((VALUE[BCOMP]) >> 3) )
+#define FETCH_PIXEL(DST, SRC) \
+   DST[RCOMP] = ( (((*SRC) >> 8) & 0xf8) | (((*SRC) >> 11) & 0x7) ); \
+   DST[GCOMP] = ( (((*SRC) >> 3) & 0xfc) | (((*SRC) >>  5) & 0x3) ); \
+   DST[BCOMP] = ( (((*SRC) << 3) & 0xf8) | (((*SRC)      ) & 0x7) ); \
+   DST[ACOMP] = CHAN_MAX
 #include "swrast/s_spantemp.h"
-#endif
+
 
 /* color index */
 #define NAME(PREFIX) PREFIX##_CI
+#define CI_MODE
+#define RB_TYPE GLubyte
 #define SPAN_VARS \
    const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
 #define INIT_PIXEL_PTR(P, X, Y) \
-   GLchan *P = osmesa->rowaddr[Y] + (X)
+   GLubyte *P = (GLubyte *) osmesa->rowaddr[Y] + (X)
 #define INC_PIXEL_PTR(P) P += 1
-#define STORE_CI_PIXEL(P, CI) \
-   P[0] = CI
-#define FETCH_CI_PIXEL(CI, P) \
-   CI = P[0]
+#define STORE_PIXEL(DST, X, Y, VALUE) \
+   *DST = VALUE[0]
+#define FETCH_PIXEL(DST, SRC) \
+   DST = SRC[0]
 #include "swrast/s_spantemp.h"
 
 
-/**********************************************************************/
-/*****                   Optimized line rendering                 *****/
-/**********************************************************************/
 
 
-#if CHAN_TYPE == GL_FLOAT
-#define PACK_RGBA(DST, R, G, B, A)     \
-do {                                   \
-   (DST)[0] = MAX2( R, 0.0F );         \
-   (DST)[1] = MAX2( G, 0.0F );         \
-   (DST)[2] = MAX2( B, 0.0F );         \
-   (DST)[3] = CLAMP(A, 0.0F, CHAN_MAXF);\
-} while (0)
-#else
+/**
+ * Macros for optimized line/triangle rendering.
+ * Only for 8-bit channel, RGBA, BGRA, ARGB formats.
+ */
+
 #define PACK_RGBA(DST, R, G, B, A)     \
 do {                                   \
    (DST)[osmesa->rInd] = R;            \
@@ -361,39 +513,11 @@ do {                                      \
    (DST)[osmesa->bInd] = B;            \
    (DST)[osmesa->aInd] = A;            \
 } while (0)
-#endif
-
-#define PACK_RGB(DST, R, G, B)  \
-do {                           \
-   (DST)[0] = R;               \
-   (DST)[1] = G;               \
-   (DST)[2] = B;               \
-} while (0)
-
-#define PACK_BGR(DST, R, G, B)  \
-do {                           \
-   (DST)[0] = B;               \
-   (DST)[1] = G;               \
-   (DST)[2] = R;               \
-} while (0)
-
-#define PACK_RGB_565(DST, R, G, B)                                     \
-do {                                                                   \
-   (DST) = (((int) (R) << 8) & 0xf800) | (((int) (G) << 3) & 0x7e0) | ((int) (B) >> 3);\
-} while (0)
 
-#define UNPACK_RED(P)      ( (P)[osmesa->rInd] )
-#define UNPACK_GREEN(P)    ( (P)[osmesa->gInd] )
-#define UNPACK_BLUE(P)     ( (P)[osmesa->bInd] )
-#define UNPACK_ALPHA(P)    ( (P)[osmesa->aInd] )
+#define PIXELADDR4(X,Y)  ((GLchan *) osmesa->rowaddr[Y] + 4 * (X))
 
-#define PIXELADDR1(X,Y)  (osmesa->rowaddr[Y] + (X))
-#define PIXELADDR2(X,Y)  (osmesa->rowaddr[Y] + 2 * (X))
-#define PIXELADDR3(X,Y)  (osmesa->rowaddr[Y] + 3 * (X))
-#define PIXELADDR4(X,Y)  (osmesa->rowaddr[Y] + 4 * (X))
 
-
-/*
+/**
  * Draw a flat-shaded, RGB line into an osmesa buffer.
  */
 #define NAME flat_rgba_line
@@ -416,7 +540,7 @@ do {                                                                \
 
 
 
-/*
+/**
  * Draw a flat-shaded, Z-less, RGB line into an osmesa buffer.
  */
 #define NAME flat_rgba_z_line
@@ -445,9 +569,9 @@ do {                                                        \
 
 
 
-/*
+/**
  * Analyze context state to see if we can provide a fast line drawing
- * function, like those in lines.c.  Otherwise, return NULL.
+ * function.  Otherwise, return NULL.
  */
 static swrast_line_func
 osmesa_choose_line_function( GLcontext *ctx )
@@ -455,7 +579,9 @@ osmesa_choose_line_function( GLcontext *ctx )
    const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
    const SWcontext *swrast = SWRAST_CONTEXT(ctx);
 
-   if (CHAN_BITS != 8)                    return NULL;
+   if (osmesa->rb->DataType != GL_UNSIGNED_BYTE)
+      return NULL;
+
    if (ctx->RenderMode != GL_RENDER)      return NULL;
    if (ctx->Line.SmoothFlag)              return NULL;
    if (ctx->Texture._EnabledUnits)        return NULL;
@@ -497,11 +623,11 @@ osmesa_choose_line_function( GLcontext *ctx )
 #define INTERP_ALPHA 1
 #define SETUP_CODE \
    const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
-#define RENDER_SPAN( span )                                    \
+#define RENDER_SPAN( span ) {                                  \
    GLuint i;                                                   \
    GLchan *img = PIXELADDR4(span.x, span.y);                   \
    for (i = 0; i < span.end; i++, img += 4) {                  \
-      const GLdepth z = FixedToDepth(span.z);                  \
+      const GLuint z = FixedToDepth(span.z);                   \
       if (z < zRow[i]) {                                       \
          PACK_RGBA(img, FixedToChan(span.red),                 \
             FixedToChan(span.green), FixedToChan(span.blue),   \
@@ -513,7 +639,8 @@ osmesa_choose_line_function( GLcontext *ctx )
       span.blue += span.blueStep;                              \
       span.alpha += span.alphaStep;                            \
       span.z += span.zStep;                                    \
-   }
+   }                                                            \
+}
 #ifdef WIN32
 #include "..\swrast\s_tritemp.h"
 #else
@@ -534,17 +661,18 @@ osmesa_choose_line_function( GLcontext *ctx )
    PACK_RGBA((GLchan *) &pixel, v2->color[0], v2->color[1],    \
                                 v2->color[2], v2->color[3]);
 
-#define RENDER_SPAN( span )                            \
+#define RENDER_SPAN( span ) {                          \
    GLuint i;                                           \
    GLuint *img = (GLuint *) PIXELADDR4(span.x, span.y);        \
    for (i = 0; i < span.end; i++) {                    \
-      const GLdepth z = FixedToDepth(span.z);          \
+      const GLuint z = FixedToDepth(span.z);           \
       if (z < zRow[i]) {                               \
          img[i] = pixel;                               \
          zRow[i] = z;                                  \
       }                                                        \
       span.z += span.zStep;                            \
-   }
+   }                                                    \
+}
 #ifdef WIN32
 #include "..\swrast\s_tritemp.h"
 #else
@@ -553,8 +681,8 @@ osmesa_choose_line_function( GLcontext *ctx )
 
 
 
-/*
- * Return pointer to an accelerated triangle function if possible.
+/**
+ * Return pointer to an optimized triangle function if possible.
  */
 static swrast_tri_func
 osmesa_choose_triangle_function( GLcontext *ctx )
@@ -562,7 +690,9 @@ osmesa_choose_triangle_function( GLcontext *ctx )
    const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
    const SWcontext *swrast = SWRAST_CONTEXT(ctx);
 
-   if (CHAN_BITS != 8)                  return (swrast_tri_func) NULL;
+   if (osmesa->rb->DataType != GL_UNSIGNED_BYTE)
+      return (swrast_tri_func) NULL;
+
    if (ctx->RenderMode != GL_RENDER)    return (swrast_tri_func) NULL;
    if (ctx->Polygon.SmoothFlag)         return (swrast_tri_func) NULL;
    if (ctx->Polygon.StippleFlag)        return (swrast_tri_func) NULL;
@@ -615,165 +745,322 @@ osmesa_choose_line( GLcontext *ctx )
 }
 
 
-#define OSMESA_NEW_LINE   (_NEW_LINE | \
-                           _NEW_TEXTURE | \
-                           _NEW_LIGHT | \
-                           _NEW_DEPTH | \
-                           _NEW_RENDERMODE | \
-                           _SWRAST_NEW_RASTERMASK)
-
-#define OSMESA_NEW_TRIANGLE (_NEW_POLYGON | \
-                             _NEW_TEXTURE | \
-                             _NEW_LIGHT | \
-                             _NEW_DEPTH | \
-                             _NEW_RENDERMODE | \
-                             _SWRAST_NEW_RASTERMASK)
 
-/* one-time, per-context initialization */
+/**
+ * Recompute the values of the context's rowaddr array.
+ */
 static void
-hook_in_driver_functions( GLcontext *ctx )
+compute_row_addresses( OSMesaContext osmesa )
 {
-   OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
-   SWcontext *swrast = SWRAST_CONTEXT( ctx );
-   struct swrast_device_driver *swdd = _swrast_GetDeviceDriverReference( ctx );
-   TNLcontext *tnl = TNL_CONTEXT(ctx);
-
-   ASSERT((void *) osmesa == (void *) ctx->DriverCtx);
-
-   /* use default TCL pipeline */
-   tnl->Driver.RunPipeline = _tnl_run_pipeline;
-
-   ctx->Driver.GetString = get_string;
-   ctx->Driver.UpdateState = osmesa_update_state;
-   ctx->Driver.ResizeBuffers = _swrast_alloc_buffers;
-   ctx->Driver.GetBufferSize = get_buffer_size;
-
-   ctx->Driver.Accum = _swrast_Accum;
-   ctx->Driver.Bitmap = _swrast_Bitmap;
-   ctx->Driver.Clear = clear;  /* uses _swrast_Clear */
-   ctx->Driver.CopyPixels = _swrast_CopyPixels;
-   ctx->Driver.DrawPixels = _swrast_DrawPixels;
-   ctx->Driver.ReadPixels = _swrast_ReadPixels;
-   ctx->Driver.DrawBuffer = _swrast_DrawBuffer;
-
-   ctx->Driver.ChooseTextureFormat = _mesa_choose_tex_format;
-   ctx->Driver.TexImage1D = _mesa_store_teximage1d;
-   ctx->Driver.TexImage2D = _mesa_store_teximage2d;
-   ctx->Driver.TexImage3D = _mesa_store_teximage3d;
-   ctx->Driver.TexSubImage1D = _mesa_store_texsubimage1d;
-   ctx->Driver.TexSubImage2D = _mesa_store_texsubimage2d;
-   ctx->Driver.TexSubImage3D = _mesa_store_texsubimage3d;
-   ctx->Driver.TestProxyTexImage = _mesa_test_proxy_teximage;
-
-   ctx->Driver.CompressedTexImage1D = _mesa_store_compressed_teximage1d;
-   ctx->Driver.CompressedTexImage2D = _mesa_store_compressed_teximage2d;
-   ctx->Driver.CompressedTexImage3D = _mesa_store_compressed_teximage3d;
-   ctx->Driver.CompressedTexSubImage1D = _mesa_store_compressed_texsubimage1d;
-   ctx->Driver.CompressedTexSubImage2D = _mesa_store_compressed_texsubimage2d;
-   ctx->Driver.CompressedTexSubImage3D = _mesa_store_compressed_texsubimage3d;
-
-   ctx->Driver.CopyTexImage1D = _swrast_copy_teximage1d;
-   ctx->Driver.CopyTexImage2D = _swrast_copy_teximage2d;
-   ctx->Driver.CopyTexSubImage1D = _swrast_copy_texsubimage1d;
-   ctx->Driver.CopyTexSubImage2D = _swrast_copy_texsubimage2d;
-   ctx->Driver.CopyTexSubImage3D = _swrast_copy_texsubimage3d;
-   ctx->Driver.CopyColorTable = _swrast_CopyColorTable;
-   ctx->Driver.CopyColorSubTable = _swrast_CopyColorSubTable;
-   ctx->Driver.CopyConvolutionFilter1D = _swrast_CopyConvolutionFilter1D;
-   ctx->Driver.CopyConvolutionFilter2D = _swrast_CopyConvolutionFilter2D;
-
-#if FEATURE_ARB_vertex_buffer_object
-   ctx->Driver.NewBufferObject = _mesa_new_buffer_object;
-   ctx->Driver.DeleteBuffer = _mesa_delete_buffer_object;
-   ctx->Driver.BindBuffer = NULL;
-   ctx->Driver.BufferData = _mesa_buffer_data;
-   ctx->Driver.BufferSubData = _mesa_buffer_subdata;
-   ctx->Driver.MapBuffer = _mesa_buffer_map;
-   ctx->Driver.UnmapBuffer = NULL;
-#endif
+   GLint bytesPerPixel, bytesPerRow, i;
+   GLubyte *origin = (GLubyte *) osmesa->rb->Data;
+   GLint bpc; /* bytes per channel */
+   GLint rowlength; /* in pixels */
+   GLint height = osmesa->rb->Height;
 
-   swdd->SetBuffer = set_buffer;
-
-   /* RGB(A) span/pixel functions */
-   if (osmesa->format == OSMESA_RGB) {
-      swdd->WriteRGBASpan = write_rgba_span_RGB;
-      swdd->WriteRGBSpan = write_rgb_span_RGB;
-      swdd->WriteMonoRGBASpan = write_monorgba_span_RGB;
-      swdd->WriteRGBAPixels = write_rgba_pixels_RGB;
-      swdd->WriteMonoRGBAPixels = write_monorgba_pixels_RGB;
-      swdd->ReadRGBASpan = read_rgba_span_RGB;
-      swdd->ReadRGBAPixels = read_rgba_pixels_RGB;
+   if (osmesa->userRowLength)
+      rowlength = osmesa->userRowLength;
+   else
+      rowlength = osmesa->rb->Width;
+
+   if (osmesa->rb->DataType == GL_UNSIGNED_BYTE)
+      bpc = 1;
+   else if (osmesa->rb->DataType == GL_UNSIGNED_SHORT)
+      bpc = 2;
+   else if (osmesa->rb->DataType == GL_FLOAT)
+      bpc = 4;
+   else {
+      _mesa_problem(&osmesa->mesa,
+                    "Unexpected datatype in osmesa::compute_row_addresses");
+      return;
    }
-   else if (osmesa->format == OSMESA_BGR) {
-      swdd->WriteRGBASpan = write_rgba_span_BGR;
-      swdd->WriteRGBSpan = write_rgb_span_BGR;
-      swdd->WriteMonoRGBASpan = write_monorgba_span_BGR;
-      swdd->WriteRGBAPixels = write_rgba_pixels_BGR;
-      swdd->WriteMonoRGBAPixels = write_monorgba_pixels_BGR;
-      swdd->ReadRGBASpan = read_rgba_span_BGR;
-      swdd->ReadRGBAPixels = read_rgba_pixels_BGR;
+
+   if (osmesa->format == OSMESA_COLOR_INDEX) {
+      /* CI mode */
+      bytesPerPixel = 1 * sizeof(GLubyte);
+   }
+   else if ((osmesa->format == OSMESA_RGB) || (osmesa->format == OSMESA_BGR)) {
+      /* RGB mode */
+      bytesPerPixel = 3 * bpc;
    }
-#if CHAN_TYPE == GL_UNSIGNED_BYTE
    else if (osmesa->format == OSMESA_RGB_565) {
-      swdd->WriteRGBASpan = write_rgba_span_RGB_565;
-      swdd->WriteRGBSpan = write_rgb_span_RGB_565;
-      swdd->WriteMonoRGBASpan = write_monorgba_span_RGB_565;
-      swdd->WriteRGBAPixels = write_rgba_pixels_RGB_565;
-      swdd->WriteMonoRGBAPixels = write_monorgba_pixels_RGB_565;
-      swdd->ReadRGBASpan = read_rgba_span_RGB_565;
-      swdd->ReadRGBAPixels = read_rgba_pixels_RGB_565;
+      /* 5/6/5 RGB pixel in 16 bits */
+      bytesPerPixel = 2;
    }
-#endif
-   else if (osmesa->format == OSMESA_RGBA) {
-      swdd->WriteRGBASpan = write_rgba_span_RGBA;
-      swdd->WriteRGBSpan = write_rgb_span_RGBA;
-      swdd->WriteMonoRGBASpan = write_monorgba_span_RGBA;
-      swdd->WriteRGBAPixels = write_rgba_pixels_RGBA;
-      swdd->WriteMonoRGBAPixels = write_monorgba_pixels_RGBA;
-      swdd->ReadRGBASpan = read_rgba_span_RGBA;
-      swdd->ReadRGBAPixels = read_rgba_pixels_RGBA;
+   else {
+      /* RGBA mode */
+      bytesPerPixel = 4 * bpc;
+   }
+
+   bytesPerRow = rowlength * bytesPerPixel;
+
+   if (osmesa->yup) {
+      /* Y=0 is bottom line of window */
+      for (i = 0; i < height; i++) {
+         osmesa->rowaddr[i] = (GLvoid *) ((GLubyte *) origin + i * bytesPerRow);
+      }
+   }
+   else {
+      /* Y=0 is top line of window */
+      for (i = 0; i < height; i++) {
+         GLint j = height - i - 1;
+         osmesa->rowaddr[i] = (GLvoid *) ((GLubyte *) origin + j * bytesPerRow);
+      }
+   }
+}
+
+
+
+/**
+ * Don't use _mesa_delete_renderbuffer since we can't free rb->Data.
+ */
+static void
+osmesa_delete_renderbuffer(struct gl_renderbuffer *rb)
+{
+   _mesa_free(rb);
+}
+
+
+/**
+ * Allocate renderbuffer storage.  We don't actually allocate any storage
+ * since we're using a user-provided buffer.
+ * Just set up all the gl_renderbuffer methods.
+ */
+static GLboolean
+osmesa_renderbuffer_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
+                            GLenum internalFormat, GLuint width, GLuint height)
+{
+   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
+   GLint bpc; /* bits per channel */
+
+   if (rb->DataType == GL_UNSIGNED_BYTE)
+      bpc = 8;
+   else if (rb->DataType == GL_UNSIGNED_SHORT)
+      bpc = 16;
+   else
+      bpc = 32;
+
+   rb->RedBits =
+   rb->GreenBits =
+   rb->BlueBits =
+   rb->AlphaBits = bpc;
+
+   /* Note: we can ignoring internalFormat for "window-system" renderbuffers */
+   (void) internalFormat;
+
+   if (osmesa->format == OSMESA_RGBA) {
+      if (rb->DataType == GL_UNSIGNED_BYTE) {
+         rb->GetRow = get_row_RGBA8;
+         rb->GetValues = get_values_RGBA8;
+         rb->PutRow = put_row_RGBA8;
+         rb->PutRowRGB = put_row_rgb_RGBA8;
+         rb->PutMonoRow = put_mono_row_RGBA8;
+         rb->PutValues = put_values_RGBA8;
+         rb->PutMonoValues = put_mono_values_RGBA8;
+      }
+      else if (rb->DataType == GL_UNSIGNED_SHORT) {
+         rb->GetRow = get_row_RGBA16;
+         rb->GetValues = get_values_RGBA16;
+         rb->PutRow = put_row_RGBA16;
+         rb->PutRowRGB = put_row_rgb_RGBA16;
+         rb->PutMonoRow = put_mono_row_RGBA16;
+         rb->PutValues = put_values_RGBA16;
+         rb->PutMonoValues = put_mono_values_RGBA16;
+      }
+      else {
+         rb->GetRow = get_row_RGBA32;
+         rb->GetValues = get_values_RGBA32;
+         rb->PutRow = put_row_RGBA32;
+         rb->PutRowRGB = put_row_rgb_RGBA32;
+         rb->PutMonoRow = put_mono_row_RGBA32;
+         rb->PutValues = put_values_RGBA32;
+         rb->PutMonoValues = put_mono_values_RGBA32;
+      }
+      rb->RedBits = rb->GreenBits = rb->BlueBits = rb->AlphaBits = bpc;
    }
    else if (osmesa->format == OSMESA_BGRA) {
-      swdd->WriteRGBASpan = write_rgba_span_BGRA;
-      swdd->WriteRGBSpan = write_rgb_span_BGRA;
-      swdd->WriteMonoRGBASpan = write_monorgba_span_BGRA;
-      swdd->WriteRGBAPixels = write_rgba_pixels_BGRA;
-      swdd->WriteMonoRGBAPixels = write_monorgba_pixels_BGRA;
-      swdd->ReadRGBASpan = read_rgba_span_BGRA;
-      swdd->ReadRGBAPixels = read_rgba_pixels_BGRA;
+      if (rb->DataType == GL_UNSIGNED_BYTE) {
+         rb->GetRow = get_row_BGRA8;
+         rb->GetValues = get_values_BGRA8;
+         rb->PutRow = put_row_BGRA8;
+         rb->PutRowRGB = put_row_rgb_BGRA8;
+         rb->PutMonoRow = put_mono_row_BGRA8;
+         rb->PutValues = put_values_BGRA8;
+         rb->PutMonoValues = put_mono_values_BGRA8;
+      }
+      else if (rb->DataType == GL_UNSIGNED_SHORT) {
+         rb->GetRow = get_row_BGRA16;
+         rb->GetValues = get_values_BGRA16;
+         rb->PutRow = put_row_BGRA16;
+         rb->PutRowRGB = put_row_rgb_BGRA16;
+         rb->PutMonoRow = put_mono_row_BGRA16;
+         rb->PutValues = put_values_BGRA16;
+         rb->PutMonoValues = put_mono_values_BGRA16;
+      }
+      else {
+         rb->GetRow = get_row_BGRA32;
+         rb->GetValues = get_values_BGRA32;
+         rb->PutRow = put_row_BGRA32;
+         rb->PutRowRGB = put_row_rgb_BGRA32;
+         rb->PutMonoRow = put_mono_row_BGRA32;
+         rb->PutValues = put_values_BGRA32;
+         rb->PutMonoValues = put_mono_values_BGRA32;
+      }
+      rb->RedBits = rb->GreenBits = rb->BlueBits = rb->AlphaBits = bpc;
    }
    else if (osmesa->format == OSMESA_ARGB) {
-      swdd->WriteRGBASpan = write_rgba_span_ARGB;
-      swdd->WriteRGBSpan = write_rgb_span_ARGB;
-      swdd->WriteMonoRGBASpan = write_monorgba_span_ARGB;
-      swdd->WriteRGBAPixels = write_rgba_pixels_ARGB;
-      swdd->WriteMonoRGBAPixels = write_monorgba_pixels_ARGB;
-      swdd->ReadRGBASpan = read_rgba_span_ARGB;
-      swdd->ReadRGBAPixels = read_rgba_pixels_ARGB;
+      if (rb->DataType == GL_UNSIGNED_BYTE) {
+         rb->GetRow = get_row_ARGB8;
+         rb->GetValues = get_values_ARGB8;
+         rb->PutRow = put_row_ARGB8;
+         rb->PutRowRGB = put_row_rgb_ARGB8;
+         rb->PutMonoRow = put_mono_row_ARGB8;
+         rb->PutValues = put_values_ARGB8;
+         rb->PutMonoValues = put_mono_values_ARGB8;
+      }
+      else if (rb->DataType == GL_UNSIGNED_SHORT) {
+         rb->GetRow = get_row_ARGB16;
+         rb->GetValues = get_values_ARGB16;
+         rb->PutRow = put_row_ARGB16;
+         rb->PutRowRGB = put_row_rgb_ARGB16;
+         rb->PutMonoRow = put_mono_row_ARGB16;
+         rb->PutValues = put_values_ARGB16;
+         rb->PutMonoValues = put_mono_values_ARGB16;
+      }
+      else {
+         rb->GetRow = get_row_ARGB32;
+         rb->GetValues = get_values_ARGB32;
+         rb->PutRow = put_row_ARGB32;
+         rb->PutRowRGB = put_row_rgb_ARGB32;
+         rb->PutMonoRow = put_mono_row_ARGB32;
+         rb->PutValues = put_values_ARGB32;
+         rb->PutMonoValues = put_mono_values_ARGB32;
+      }
+      rb->RedBits = rb->GreenBits = rb->BlueBits = rb->AlphaBits = bpc;
+   }
+   else if (osmesa->format == OSMESA_RGB) {
+      if (rb->DataType == GL_UNSIGNED_BYTE) {
+         rb->GetRow = get_row_RGB8;
+         rb->GetValues = get_values_RGB8;
+         rb->PutRow = put_row_RGB8;
+         rb->PutRowRGB = put_row_rgb_RGB8;
+         rb->PutMonoRow = put_mono_row_RGB8;
+         rb->PutValues = put_values_RGB8;
+         rb->PutMonoValues = put_mono_values_RGB8;
+      }
+      else if (rb->DataType == GL_UNSIGNED_SHORT) {
+         rb->GetRow = get_row_RGB16;
+         rb->GetValues = get_values_RGB16;
+         rb->PutRow = put_row_RGB16;
+         rb->PutRowRGB = put_row_rgb_RGB16;
+         rb->PutMonoRow = put_mono_row_RGB16;
+         rb->PutValues = put_values_RGB16;
+         rb->PutMonoValues = put_mono_values_RGB16;
+      }
+      else {
+         rb->GetRow = get_row_RGB32;
+         rb->GetValues = get_values_RGB32;
+         rb->PutRow = put_row_RGB32;
+         rb->PutRowRGB = put_row_rgb_RGB32;
+         rb->PutMonoRow = put_mono_row_RGB32;
+         rb->PutValues = put_values_RGB32;
+         rb->PutMonoValues = put_mono_values_RGB32;
+      }
+      rb->RedBits = rb->GreenBits = rb->BlueBits = bpc;
+   }
+   else if (osmesa->format == OSMESA_BGR) {
+      if (rb->DataType == GL_UNSIGNED_BYTE) {
+         rb->GetRow = get_row_BGR8;
+         rb->GetValues = get_values_BGR8;
+         rb->PutRow = put_row_BGR8;
+         rb->PutRowRGB = put_row_rgb_BGR8;
+         rb->PutMonoRow = put_mono_row_BGR8;
+         rb->PutValues = put_values_BGR8;
+         rb->PutMonoValues = put_mono_values_BGR8;
+      }
+      else if (rb->DataType == GL_UNSIGNED_SHORT) {
+         rb->GetRow = get_row_BGR16;
+         rb->GetValues = get_values_BGR16;
+         rb->PutRow = put_row_BGR16;
+         rb->PutRowRGB = put_row_rgb_BGR16;
+         rb->PutMonoRow = put_mono_row_BGR16;
+         rb->PutValues = put_values_BGR16;
+         rb->PutMonoValues = put_mono_values_BGR16;
+      }
+      else {
+         rb->GetRow = get_row_BGR32;
+         rb->GetValues = get_values_BGR32;
+         rb->PutRow = put_row_BGR32;
+         rb->PutRowRGB = put_row_rgb_BGR32;
+         rb->PutMonoRow = put_mono_row_BGR32;
+         rb->PutValues = put_values_BGR32;
+         rb->PutMonoValues = put_mono_values_BGR32;
+      }
+      rb->RedBits = rb->GreenBits = rb->BlueBits = bpc;
+   }
+   else if (osmesa->format == OSMESA_RGB_565) {
+      ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
+      rb->GetRow = get_row_RGB_565;
+      rb->GetValues = get_values_RGB_565;
+      rb->PutRow = put_row_RGB_565;
+      rb->PutRowRGB = put_row_rgb_RGB_565;
+      rb->PutMonoRow = put_mono_row_RGB_565;
+      rb->PutValues = put_values_RGB_565;
+      rb->PutMonoValues = put_mono_values_RGB_565;
+      rb->RedBits = 5;
+      rb->GreenBits = 6;
+      rb->BlueBits = 5;
    }
    else if (osmesa->format == OSMESA_COLOR_INDEX) {
-      swdd->WriteCI32Span = write_index32_span_CI;
-      swdd->WriteCI8Span = write_index8_span_CI;
-      swdd->WriteMonoCISpan = write_monoindex_span_CI;
-      swdd->WriteCI32Pixels = write_index_pixels_CI;
-      swdd->WriteMonoCIPixels = write_monoindex_pixels_CI;
-      swdd->ReadCI32Span = read_index_span_CI;
-      swdd->ReadCI32Pixels = read_index_pixels_CI;
+      rb->GetRow = get_row_CI;
+      rb->GetValues = get_values_CI;
+      rb->PutRow = put_row_CI;
+      rb->PutMonoRow = put_mono_row_CI;
+      rb->PutValues = put_values_CI;
+      rb->PutMonoValues = put_mono_values_CI;
+      rb->IndexBits = 8;
    }
    else {
-      _mesa_problem(ctx, "bad pixel format in osmesa_update_state!\n");
+      _mesa_problem(ctx, "bad pixel format in osmesa renderbuffer_storage");
    }
 
-   /* Extend the software rasterizer with our optimized line and triangle
-    * drawin functions.
-    */
-   swrast->choose_line = osmesa_choose_line;
-   swrast->choose_triangle = osmesa_choose_triangle;
-   swrast->invalidate_line |= OSMESA_NEW_LINE;
-   swrast->invalidate_triangle |= OSMESA_NEW_TRIANGLE;
+   rb->Width = width;
+   rb->Height = height;
+
+   compute_row_addresses( osmesa );
+
+   return GL_TRUE;
 }
 
 
+/**
+ * Allocate a new renderbuffer to describe the user-provided color buffer.
+ */
+static struct gl_renderbuffer *
+new_osmesa_renderbuffer(GLcontext *ctx, GLenum format, GLenum type)
+{
+   const GLuint name = 0;
+   struct gl_renderbuffer *rb = _mesa_new_renderbuffer(ctx, name);
+   if (rb) {
+      rb->RefCount = 1;
+      rb->Delete = osmesa_delete_renderbuffer;
+      rb->AllocStorage = osmesa_renderbuffer_storage;
+
+      if (format == OSMESA_COLOR_INDEX) {
+         rb->InternalFormat = GL_COLOR_INDEX;
+         rb->_ActualFormat = GL_COLOR_INDEX8_EXT;
+         rb->_BaseFormat = GL_COLOR_INDEX;
+         rb->DataType = GL_UNSIGNED_BYTE;
+      }
+      else {
+         rb->InternalFormat = GL_RGBA;
+         rb->_ActualFormat = GL_RGBA;
+         rb->_BaseFormat = GL_RGBA;
+         rb->DataType = type;
+      }
+   }
+   return rb;
+}
 
 
 /**********************************************************************/
@@ -781,7 +1068,7 @@ hook_in_driver_functions( GLcontext *ctx )
 /**********************************************************************/
 
 
-/*
+/**
  * Create an Off-Screen Mesa rendering context.  The only attribute needed is
  * an RGBA vs Color-Index mode flag.
  *
@@ -800,7 +1087,7 @@ OSMesaCreateContext( GLenum format, OSMesaContext sharelist )
 
 
 
-/*
+/**
  * New in Mesa 3.5
  *
  * Create context and specify size of ancillary buffers.
@@ -810,18 +1097,15 @@ OSMesaCreateContextExt( GLenum format, GLint depthBits, GLint stencilBits,
                         GLint accumBits, OSMesaContext sharelist )
 {
    OSMesaContext osmesa;
-   GLint rshift, gshift, bshift, ashift;
+   struct dd_function_table functions;
    GLint rind, gind, bind, aind;
    GLint indexBits = 0, redBits = 0, greenBits = 0, blueBits = 0, alphaBits =0;
    GLboolean rgbmode;
-   const GLuint i4 = 1;
-   const GLubyte *i1 = (GLubyte *) &i4;
-   const GLint little_endian = *i1;
+   GLenum type = CHAN_TYPE;
 
    rind = gind = bind = aind = 0;
    if (format==OSMESA_COLOR_INDEX) {
       indexBits = 8;
-      rshift = gshift = bshift = ashift = 0;
       rgbmode = GL_FALSE;
    }
    else if (format==OSMESA_RGBA) {
@@ -834,18 +1118,6 @@ OSMesaCreateContextExt( GLenum format, GLint depthBits, GLint stencilBits,
       gind = 1;
       bind = 2;
       aind = 3;
-      if (little_endian) {
-         rshift = 0;
-         gshift = 8;
-         bshift = 16;
-         ashift = 24;
-      }
-      else {
-         rshift = 24;
-         gshift = 16;
-         bshift = 8;
-         ashift = 0;
-      }
       rgbmode = GL_TRUE;
    }
    else if (format==OSMESA_BGRA) {
@@ -858,18 +1130,6 @@ OSMesaCreateContextExt( GLenum format, GLint depthBits, GLint stencilBits,
       gind = 1;
       rind = 2;
       aind = 3;
-      if (little_endian) {
-         bshift = 0;
-         gshift = 8;
-         rshift = 16;
-         ashift = 24;
-      }
-      else {
-         bshift = 24;
-         gshift = 16;
-         rshift = 8;
-         ashift = 0;
-      }
       rgbmode = GL_TRUE;
    }
    else if (format==OSMESA_ARGB) {
@@ -882,18 +1142,6 @@ OSMesaCreateContextExt( GLenum format, GLint depthBits, GLint stencilBits,
       rind = 1;
       gind = 2;
       bind = 3;
-      if (little_endian) {
-         ashift = 0;
-         rshift = 8;
-         gshift = 16;
-         bshift = 24;
-      }
-      else {
-         ashift = 24;
-         rshift = 16;
-         gshift = 8;
-         bshift = 0;
-      }
       rgbmode = GL_TRUE;
    }
    else if (format==OSMESA_RGB) {
@@ -902,10 +1150,6 @@ OSMesaCreateContextExt( GLenum format, GLint depthBits, GLint stencilBits,
       greenBits = CHAN_BITS;
       blueBits = CHAN_BITS;
       alphaBits = 0;
-      bshift = 0;
-      gshift = 8;
-      rshift = 16;
-      ashift = 24;
       rind = 0;
       gind = 1;
       bind = 2;
@@ -917,10 +1161,6 @@ OSMesaCreateContextExt( GLenum format, GLint depthBits, GLint stencilBits,
       greenBits = CHAN_BITS;
       blueBits = CHAN_BITS;
       alphaBits = 0;
-      bshift = 0;
-      gshift = 8;
-      rshift = 16;
-      ashift = 24;
       rind = 2;
       gind = 1;
       bind = 0;
@@ -933,10 +1173,6 @@ OSMesaCreateContextExt( GLenum format, GLint depthBits, GLint stencilBits,
       greenBits = 6;
       blueBits = 5;
       alphaBits = 0;
-      rshift = 11;
-      gshift = 5;
-      bshift = 0;
-      ashift = 0;
       rind = 0; /* not used */
       gind = 0;
       bind = 0;
@@ -947,7 +1183,6 @@ OSMesaCreateContextExt( GLenum format, GLint depthBits, GLint stencilBits,
       return NULL;
    }
 
-
    osmesa = (OSMesaContext) CALLOC_STRUCT(osmesa_context);
    if (osmesa) {
       osmesa->gl_visual = _mesa_create_visual( rgbmode,
@@ -967,26 +1202,24 @@ OSMesaCreateContextExt( GLenum format, GLint depthBits, GLint stencilBits,
                                                1            /* num samples */
                                                );
       if (!osmesa->gl_visual) {
-         FREE(osmesa);
+         _mesa_free(osmesa);
          return NULL;
       }
 
-      /* Setup these pointers here since they're using for making the default
-       * and proxy texture objects.  Actually, we don't really need to do
-       * this since we're using the default fallback functions which
-       * _mesa_initialize_context() would plug in if needed.
-       */
-      osmesa->mesa.Driver.NewTextureObject = _mesa_new_texture_object;
-      osmesa->mesa.Driver.DeleteTexture = _mesa_delete_texture_object;
+      /* Initialize device driver function table */
+      _mesa_init_driver_functions(&functions);
+      /* override with our functions */
+      functions.GetString = get_string;
+      functions.UpdateState = osmesa_update_state;
+      functions.GetBufferSize = NULL;
 
       if (!_mesa_initialize_context(&osmesa->mesa,
                                     osmesa->gl_visual,
                                     sharelist ? &sharelist->mesa
                                               : (GLcontext *) NULL,
-                                    (void *) osmesa,
-                                    GL_FALSE)) {
+                                    &functions, (void *) osmesa)) {
          _mesa_destroy_visual( osmesa->gl_visual );
-         FREE(osmesa);
+         _mesa_free(osmesa);
          return NULL;
       }
 
@@ -994,119 +1227,103 @@ OSMesaCreateContextExt( GLenum format, GLint depthBits, GLint stencilBits,
       _mesa_enable_1_3_extensions(&(osmesa->mesa));
       _mesa_enable_1_4_extensions(&(osmesa->mesa));
       _mesa_enable_1_5_extensions(&(osmesa->mesa));
+      _mesa_enable_2_0_extensions(&(osmesa->mesa));
+      _mesa_enable_2_1_extensions(&(osmesa->mesa));
 
-      osmesa->gl_buffer = _mesa_create_framebuffer( osmesa->gl_visual,
-                           (GLboolean) ( osmesa->gl_visual->depthBits > 0 ),
-                           (GLboolean) ( osmesa->gl_visual->stencilBits > 0 ),
-                           (GLboolean) ( osmesa->gl_visual->accumRedBits > 0 ),
-                           GL_FALSE /* s/w alpha */ );
-
+      osmesa->gl_buffer = _mesa_create_framebuffer(osmesa->gl_visual);
       if (!osmesa->gl_buffer) {
          _mesa_destroy_visual( osmesa->gl_visual );
          _mesa_free_context_data( &osmesa->mesa );
-         FREE(osmesa);
+         _mesa_free(osmesa);
          return NULL;
       }
+
+      /* create front color buffer in user-provided memory (no back buffer) */
+      osmesa->rb = new_osmesa_renderbuffer(&osmesa->mesa, format, type);
+      _mesa_add_renderbuffer(osmesa->gl_buffer, BUFFER_FRONT_LEFT, osmesa->rb);
+      assert(osmesa->rb->RefCount == 2);
+                        
+      _mesa_add_soft_renderbuffers(osmesa->gl_buffer,
+                                   GL_FALSE, /* color */
+                                   osmesa->gl_visual->haveDepthBuffer,
+                                   osmesa->gl_visual->haveStencilBuffer,
+                                   osmesa->gl_visual->haveAccumBuffer,
+                                   GL_FALSE, /* alpha */
+                                   GL_FALSE /* aux */ );
+
       osmesa->format = format;
-      osmesa->buffer = NULL;
-      osmesa->width = 0;
-      osmesa->height = 0;
       osmesa->userRowLength = 0;
-      osmesa->rowlength = 0;
       osmesa->yup = GL_TRUE;
-      osmesa->rshift = rshift;
-      osmesa->gshift = gshift;
-      osmesa->bshift = bshift;
-      osmesa->ashift = ashift;
       osmesa->rInd = rind;
       osmesa->gInd = gind;
       osmesa->bInd = bind;
       osmesa->aInd = aind;
 
+      _mesa_meta_init(&osmesa->mesa);
+
       /* Initialize the software rasterizer and helper modules. */
       {
         GLcontext *ctx = &osmesa->mesa;
-
-        _swrast_CreateContext( ctx );
-        _ac_CreateContext( ctx );
-        _tnl_CreateContext( ctx );
-        _swsetup_CreateContext( ctx );
+         SWcontext *swrast;
+         TNLcontext *tnl;
+
+        if (!_swrast_CreateContext( ctx ) ||
+             !_vbo_CreateContext( ctx ) ||
+             !_tnl_CreateContext( ctx ) ||
+             !_swsetup_CreateContext( ctx )) {
+            _mesa_destroy_visual(osmesa->gl_visual);
+            _mesa_free_context_data(ctx);
+            _mesa_free(osmesa);
+            return NULL;
+         }
        
         _swsetup_Wakeup( ctx );
-         hook_in_driver_functions( ctx );
+
+         /* use default TCL pipeline */
+         tnl = TNL_CONTEXT(ctx);
+         tnl->Driver.RunPipeline = _tnl_run_pipeline;
+
+         /* Extend the software rasterizer with our optimized line and triangle
+          * drawing functions.
+          */
+         swrast = SWRAST_CONTEXT( ctx );
+         swrast->choose_line = osmesa_choose_line;
+         swrast->choose_triangle = osmesa_choose_triangle;
       }
    }
    return osmesa;
 }
 
 
-/*
+/**
  * Destroy an Off-Screen Mesa rendering context.
  *
- * Input:  ctx - the context to destroy
+ * \param osmesa  the context to destroy
  */
 GLAPI void GLAPIENTRY
-OSMesaDestroyContext( OSMesaContext ctx )
+OSMesaDestroyContext( OSMesaContext osmesa )
 {
-   if (ctx) {
-      _swsetup_DestroyContext( &ctx->mesa );
-      _tnl_DestroyContext( &ctx->mesa );
-      _ac_DestroyContext( &ctx->mesa );
-      _swrast_DestroyContext( &ctx->mesa );
-
-      _mesa_destroy_visual( ctx->gl_visual );
-      _mesa_destroy_framebuffer( ctx->gl_buffer );
-      _mesa_free_context_data( &ctx->mesa );
-      FREE( ctx );
-   }
-}
+   if (osmesa) {
+      if (osmesa->rb)
+         _mesa_reference_renderbuffer(&osmesa->rb, NULL);
 
+      _mesa_meta_free( &osmesa->mesa );
 
-/*
- * Recompute the values of the context's rowaddr array.
- */
-static void
-compute_row_addresses( OSMesaContext ctx )
-{
-   GLint bytesPerPixel, bytesPerRow, i;
-   GLubyte *origin = (GLubyte *) ctx->buffer;
-
-   if (ctx->format == OSMESA_COLOR_INDEX) {
-      /* CI mode */
-      bytesPerPixel = 1 * sizeof(GLchan);
-   }
-   else if ((ctx->format == OSMESA_RGB) || (ctx->format == OSMESA_BGR)) {
-      /* RGB mode */
-      bytesPerPixel = 3 * sizeof(GLchan);
-   }
-   else if (ctx->format == OSMESA_RGB_565) {
-      /* 5/6/5 RGB pixel in 16 bits */
-      bytesPerPixel = 2;
-   }
-   else {
-      /* RGBA mode */
-      bytesPerPixel = 4 * sizeof(GLchan);
-   }
+      _swsetup_DestroyContext( &osmesa->mesa );
+      _tnl_DestroyContext( &osmesa->mesa );
+      _vbo_DestroyContext( &osmesa->mesa );
+      _swrast_DestroyContext( &osmesa->mesa );
 
-   bytesPerRow = ctx->rowlength * bytesPerPixel;
+      _mesa_destroy_visual( osmesa->gl_visual );
+      _mesa_reference_framebuffer( &osmesa->gl_buffer, NULL );
 
-   if (ctx->yup) {
-      /* Y=0 is bottom line of window */
-      for (i = 0; i < MAX_HEIGHT; i++) {
-         ctx->rowaddr[i] = (GLchan *) ((GLubyte *) origin + i * bytesPerRow);
-      }
-   }
-   else {
-      /* Y=0 is top line of window */
-      for (i = 0; i < MAX_HEIGHT; i++) {
-         GLint j = ctx->height - i - 1;
-         ctx->rowaddr[i] = (GLchan *) ((GLubyte *) origin + j * bytesPerRow);
-      }
+      _mesa_free_context_data( &osmesa->mesa );
+      _mesa_free( osmesa );
    }
 }
 
 
-/*
+/**
  * Bind an OSMesaContext to an image buffer.  The image buffer is just a
  * block of memory which the client provides.  Its size must be at least
  * as large as width*height*sizeof(type).  Its address should be a multiple
@@ -1119,71 +1336,84 @@ compute_row_addresses( OSMesaContext ctx )
  * If the context's viewport hasn't been initialized yet, it will now be
  * initialized to (0,0,width,height).
  *
- * Input:  ctx - the rendering context
+ * Input:  osmesa - the rendering context
  *         buffer - the image buffer memory
  *         type - data type for pixel components
  *            Normally, only GL_UNSIGNED_BYTE and GL_UNSIGNED_SHORT_5_6_5
  *            are supported.  But if Mesa's been compiled with CHAN_BITS==16
- *            then type must be GL_UNSIGNED_SHORT.  And if Mesa's been build
- *            with CHAN_BITS==32 then type must be GL_FLOAT.
+ *            then type may be GL_UNSIGNED_SHORT or GL_UNSIGNED_BYTE.  And if
+ *            Mesa's been build with CHAN_BITS==32 then type may be GL_FLOAT,
+ *            GL_UNSIGNED_SHORT or GL_UNSIGNED_BYTE.
  *         width, height - size of image buffer in pixels, at least 1
- * Return:  GL_TRUE if success, GL_FALSE if error because of invalid ctx,
+ * Return:  GL_TRUE if success, GL_FALSE if error because of invalid osmesa,
  *          invalid buffer address, invalid type, width<1, height<1,
  *          width>internal limit or height>internal limit.
  */
 GLAPI GLboolean GLAPIENTRY
-OSMesaMakeCurrent( OSMesaContext ctx, void *buffer, GLenum type,
+OSMesaMakeCurrent( OSMesaContext osmesa, void *buffer, GLenum type,
                    GLsizei width, GLsizei height )
 {
-   if (!ctx || !buffer ||
+   if (!osmesa || !buffer ||
        width < 1 || height < 1 ||
        width > MAX_WIDTH || height > MAX_HEIGHT) {
       return GL_FALSE;
    }
 
-   if (ctx->format == OSMESA_RGB_565) {
-      if (type != GL_UNSIGNED_SHORT_5_6_5)
-         return GL_FALSE;
+   if (osmesa->format == OSMESA_RGB_565 && type != GL_UNSIGNED_SHORT_5_6_5) {
+      return GL_FALSE;
    }
-   else if (type != CHAN_TYPE) {
+
+#if 0
+   if (!(type == GL_UNSIGNED_BYTE ||
+         (type == GL_UNSIGNED_SHORT && CHAN_BITS >= 16) ||
+         (type == GL_FLOAT && CHAN_BITS == 32))) {
+      /* i.e. is sizeof(type) * 8 > CHAN_BITS? */
       return GL_FALSE;
    }
+#endif
 
-   osmesa_update_state( &ctx->mesa, 0 );
-   _mesa_make_current( &ctx->mesa, ctx->gl_buffer );
+   osmesa_update_state( &osmesa->mesa, 0 );
 
-   ctx->buffer = buffer;
-   ctx->width = width;
-   ctx->height = height;
-   if (ctx->userRowLength)
-      ctx->rowlength = ctx->userRowLength;
-   else
-      ctx->rowlength = width;
+   /* Call this periodically to detect when the user has begun using
+    * GL rendering from multiple threads.
+    */
+   _glapi_check_multithread();
 
-   compute_row_addresses( ctx );
+   /* Set renderbuffer fields.  Set width/height = 0 to force 
+    * osmesa_renderbuffer_storage() being called by _mesa_resize_framebuffer()
+    */
+   osmesa->rb->Data = buffer;
+   osmesa->rb->DataType = type;
+   osmesa->rb->Width = osmesa->rb->Height = 0;
 
-   /* init viewport */
-   if (ctx->mesa.Viewport.Width == 0) {
-      /* initialize viewport and scissor box to buffer size */
-      _mesa_Viewport( 0, 0, width, height );
-      ctx->mesa.Scissor.Width = width;
-      ctx->mesa.Scissor.Height = height;
-   }
-   else {
-      /* this will make ensure we recognize the new buffer size */
-      _mesa_ResizeBuffersMESA();
-   }
+   /* Set the framebuffer's size.  This causes the
+    * osmesa_renderbuffer_storage() function to get called.
+    */
+   _mesa_resize_framebuffer(&osmesa->mesa, osmesa->gl_buffer, width, height);
+   osmesa->gl_buffer->Initialized = GL_TRUE; /* XXX TEMPORARY? */
+
+   _mesa_make_current( &osmesa->mesa, osmesa->gl_buffer, osmesa->gl_buffer );
 
-   /* Added by Gerk Huisma: */
-   _tnl_MakeCurrent( &ctx->mesa, ctx->mesa.DrawBuffer,
-                     ctx->mesa.ReadBuffer );
+   /* Remove renderbuffer attachment, then re-add.  This installs the
+    * renderbuffer adaptor/wrapper if needed (for bpp conversion).
+    */
+   _mesa_remove_renderbuffer(osmesa->gl_buffer, BUFFER_FRONT_LEFT);
+   _mesa_add_renderbuffer(osmesa->gl_buffer, BUFFER_FRONT_LEFT, osmesa->rb);
+
+
+   /* this updates the visual's red/green/blue/alphaBits fields */
+   _mesa_update_framebuffer_visual(osmesa->gl_buffer);
+
+   /* update the framebuffer size */
+   _mesa_resize_framebuffer(&osmesa->mesa, osmesa->gl_buffer, width, height);
 
    return GL_TRUE;
 }
 
 
 
-GLAPI OSMesaContext GLAPIENTRY OSMesaGetCurrentContext( void )
+GLAPI OSMesaContext GLAPIENTRY
+OSMesaGetCurrentContext( void )
 {
    GLcontext *ctx = _mesa_get_current_context();
    if (ctx)
@@ -1194,7 +1424,8 @@ GLAPI OSMesaContext GLAPIENTRY OSMesaGetCurrentContext( void )
 
 
 
-GLAPI void GLAPIENTRY OSMesaPixelStore( GLint pname, GLint value )
+GLAPI void GLAPIENTRY
+OSMesaPixelStore( GLint pname, GLint value )
 {
    OSMesaContext osmesa = OSMesaGetCurrentContext();
 
@@ -1206,7 +1437,6 @@ GLAPI void GLAPIENTRY OSMesaPixelStore( GLint pname, GLint value )
             return;
          }
          osmesa->userRowLength = value;
-         osmesa->rowlength = value ? value : osmesa->width;
          break;
       case OSMESA_Y_UP:
          osmesa->yup = value ? GL_TRUE : GL_FALSE;
@@ -1220,22 +1450,35 @@ GLAPI void GLAPIENTRY OSMesaPixelStore( GLint pname, GLint value )
 }
 
 
-GLAPI void GLAPIENTRY OSMesaGetIntegerv( GLint pname, GLint *value )
+GLAPI void GLAPIENTRY
+OSMesaGetIntegerv( GLint pname, GLint *value )
 {
    OSMesaContext osmesa = OSMesaGetCurrentContext();
 
    switch (pname) {
       case OSMESA_WIDTH:
-         *value = osmesa->width;
+         if (osmesa->gl_buffer)
+            *value = osmesa->gl_buffer->Width;
+         else
+            *value = 0;
          return;
       case OSMESA_HEIGHT:
-         *value = osmesa->height;
+         if (osmesa->gl_buffer)
+            *value = osmesa->gl_buffer->Height;
+         else
+            *value = 0;
          return;
       case OSMESA_FORMAT:
          *value = osmesa->format;
          return;
       case OSMESA_TYPE:
-         *value = CHAN_TYPE;
+         /* current color buffer's data type */
+         if (osmesa->rb) {
+            *value = osmesa->rb->DataType;
+         }
+         else {
+            *value = 0;
+         }
          return;
       case OSMESA_ROW_LENGTH:
          *value = osmesa->userRowLength;
@@ -1255,7 +1498,8 @@ GLAPI void GLAPIENTRY OSMesaGetIntegerv( GLint pname, GLint *value )
    }
 }
 
-/*
+
+/**
  * Return the depth buffer associated with an OSMesa context.
  * Input:  c - the OSMesa context
  * Output:  width, height - size of buffer in pixels
@@ -1267,7 +1511,12 @@ GLAPI GLboolean GLAPIENTRY
 OSMesaGetDepthBuffer( OSMesaContext c, GLint *width, GLint *height,
                       GLint *bytesPerValue, void **buffer )
 {
-   if ((!c->gl_buffer) || (!c->gl_buffer->DepthBuffer)) {
+   struct gl_renderbuffer *rb = NULL;
+
+   if (c->gl_buffer)
+      rb = c->gl_buffer->Attachment[BUFFER_DEPTH].Renderbuffer;
+
+   if (!rb || !rb->Data) {
       *width = 0;
       *height = 0;
       *bytesPerValue = 0;
@@ -1275,18 +1524,19 @@ OSMesaGetDepthBuffer( OSMesaContext c, GLint *width, GLint *height,
       return GL_FALSE;
    }
    else {
-      *width = c->gl_buffer->Width;
-      *height = c->gl_buffer->Height;
+      *width = rb->Width;
+      *height = rb->Height;
       if (c->gl_visual->depthBits <= 16)
          *bytesPerValue = sizeof(GLushort);
       else
          *bytesPerValue = sizeof(GLuint);
-      *buffer = c->gl_buffer->DepthBuffer;
+      *buffer = rb->Data;
       return GL_TRUE;
    }
 }
 
-/*
+
+/**
  * Return the color buffer associated with an OSMesa context.
  * Input:  c - the OSMesa context
  * Output:  width, height - size of buffer in pixels
@@ -1295,53 +1545,71 @@ OSMesaGetDepthBuffer( OSMesaContext c, GLint *width, GLint *height,
  * Return:  GL_TRUE or GL_FALSE to indicate success or failure.
  */
 GLAPI GLboolean GLAPIENTRY
-OSMesaGetColorBuffer( OSMesaContext c, GLint *width,
+OSMesaGetColorBuffer( OSMesaContext osmesa, GLint *width,
                       GLint *height, GLint *format, void **buffer )
 {
-   if (!c->buffer) {
+   if (osmesa->rb && osmesa->rb->Data) {
+      *width = osmesa->rb->Width;
+      *height = osmesa->rb->Height;
+      *format = osmesa->format;
+      *buffer = osmesa->rb->Data;
+      return GL_TRUE;
+   }
+   else {
       *width = 0;
       *height = 0;
       *format = 0;
       *buffer = 0;
       return GL_FALSE;
    }
-   else {
-      *width = c->width;
-      *height = c->height;
-      *format = c->format;
-      *buffer = c->buffer;
-      return GL_TRUE;
-   }
 }
 
 
-
-struct name_address {
+struct name_function
+{
    const char *Name;
-   GLvoid *Address;
+   OSMESAproc Function;
 };
 
-static struct name_address functions[] = {
-   { "OSMesaCreateContext", (void *) OSMesaCreateContext },
-   { "OSMesaCreateContextExt", (void *) OSMesaCreateContextExt },
-   { "OSMesaDestroyContext", (void *) OSMesaDestroyContext },
-   { "OSMesaMakeCurrent", (void *) OSMesaMakeCurrent },
-   { "OSMesaGetCurrentContext", (void *) OSMesaGetCurrentContext },
-   { "OSMesaPixelsStore", (void *) OSMesaPixelStore },
-   { "OSMesaGetIntegerv", (void *) OSMesaGetIntegerv },
-   { "OSMesaGetDepthBuffer", (void *) OSMesaGetDepthBuffer },
-   { "OSMesaGetColorBuffer", (void *) OSMesaGetColorBuffer },
-   { "OSMesaGetProcAddress", (void *) OSMesaGetProcAddress },
+static struct name_function functions[] = {
+   { "OSMesaCreateContext", (OSMESAproc) OSMesaCreateContext },
+   { "OSMesaCreateContextExt", (OSMESAproc) OSMesaCreateContextExt },
+   { "OSMesaDestroyContext", (OSMESAproc) OSMesaDestroyContext },
+   { "OSMesaMakeCurrent", (OSMESAproc) OSMesaMakeCurrent },
+   { "OSMesaGetCurrentContext", (OSMESAproc) OSMesaGetCurrentContext },
+   { "OSMesaPixelsStore", (OSMESAproc) OSMesaPixelStore },
+   { "OSMesaGetIntegerv", (OSMESAproc) OSMesaGetIntegerv },
+   { "OSMesaGetDepthBuffer", (OSMESAproc) OSMesaGetDepthBuffer },
+   { "OSMesaGetColorBuffer", (OSMESAproc) OSMesaGetColorBuffer },
+   { "OSMesaGetProcAddress", (OSMESAproc) OSMesaGetProcAddress },
+   { "OSMesaColorClamp", (OSMESAproc) OSMesaColorClamp },
    { NULL, NULL }
 };
 
-GLAPI void * GLAPIENTRY
+
+GLAPI OSMESAproc GLAPIENTRY
 OSMesaGetProcAddress( const char *funcName )
 {
    int i;
    for (i = 0; functions[i].Name; i++) {
       if (_mesa_strcmp(functions[i].Name, funcName) == 0)
-         return (void *) functions[i].Address;
+         return functions[i].Function;
+   }
+   return _glapi_get_proc_address(funcName);
+}
+
+
+GLAPI void GLAPIENTRY
+OSMesaColorClamp(GLboolean enable)
+{
+   OSMesaContext osmesa = OSMesaGetCurrentContext();
+
+   if (enable == GL_TRUE) {
+      osmesa->mesa.Color.ClampFragmentColor = GL_TRUE;
+   }
+   else {
+      osmesa->mesa.Color.ClampFragmentColor = GL_FIXED_ONLY_ARB;
    }
-   return (void *) _glapi_get_proc_address(funcName);
 }
+
+