From 072157e2ba87f3303958e48815fa2548009d3410 Mon Sep 17 00:00:00 2001
From: marha <marha@users.sourceforge.net>
Date: Mon, 30 May 2011 22:21:12 +0200
Subject: mesa git update 30 May 2011

---
 mesalib/src/mesa/main/shaderapi.c                 |    2 +
 mesalib/src/mesa/state_tracker/st_cb_blit.c       |   14 +-
 mesalib/src/mesa/state_tracker/st_cb_condrender.c |  199 +--
 mesalib/src/mesa/state_tracker/st_cb_drawpixels.c |    3 +-
 mesalib/src/mesa/state_tracker/st_cb_fbo.c        | 1327 ++++++++++-----------
 mesalib/src/mesa/state_tracker/st_cb_texture.c    |   23 +
 mesalib/src/mesa/state_tracker/st_context.h       |    4 +
 mesalib/src/mesa/state_tracker/st_format.c        |   42 +-
 mesalib/src/mesa/state_tracker/st_gen_mipmap.c    |    9 +
 mesalib/src/mesa/swrast/s_blit.c                  | 1235 ++++++++++---------
 10 files changed, 1457 insertions(+), 1401 deletions(-)

(limited to 'mesalib/src/mesa')

diff --git a/mesalib/src/mesa/main/shaderapi.c b/mesalib/src/mesa/main/shaderapi.c
index 03155b7ac..1e237a95d 100644
--- a/mesalib/src/mesa/main/shaderapi.c
+++ b/mesalib/src/mesa/main/shaderapi.c
@@ -1593,6 +1593,8 @@ _mesa_UseProgramObjectARB(GLhandleARB program)
    struct gl_transform_feedback_object *obj =
       ctx->TransformFeedback.CurrentObject;
 
+   ASSERT_OUTSIDE_BEGIN_END(ctx);
+
    if (obj->Active) {
       _mesa_error(ctx, GL_INVALID_OPERATION,
                   "glUseProgram(transform feedback active)");
diff --git a/mesalib/src/mesa/state_tracker/st_cb_blit.c b/mesalib/src/mesa/state_tracker/st_cb_blit.c
index 25c95c7b9..416be194d 100644
--- a/mesalib/src/mesa/state_tracker/st_cb_blit.c
+++ b/mesalib/src/mesa/state_tracker/st_cb_blit.c
@@ -109,6 +109,11 @@ st_BlitFramebuffer(struct gl_context *ctx,
       dstY1 = tmp;
    }
 
+   /* Disable conditional rendering. */
+   if (st->render_condition) {
+      st->pipe->render_condition(st->pipe, NULL, 0);
+   }
+
    if (mask & GL_COLOR_BUFFER_BIT) {
       struct gl_renderbuffer_attachment *srcAtt =
          &readFB->Attachment[readFB->_ColorReadBufferIndex];
@@ -121,7 +126,7 @@ st_BlitFramebuffer(struct gl_context *ctx,
          struct pipe_surface *dstSurf = dstRb->surface;
 
          if (!srcObj->pt)
-            return;
+            goto done;
 
          util_blit_pixels(st->blit, srcObj->pt, srcAtt->TextureLevel,
                           srcX0, srcY0, srcX1, srcY1,
@@ -199,6 +204,13 @@ st_BlitFramebuffer(struct gl_context *ctx,
          }
       }
    }
+
+done:
+   /* Restore conditional rendering state. */
+   if (st->render_condition) {
+      st->pipe->render_condition(st->pipe, st->render_condition,
+                                 st->condition_mode);
+   }
 }
 
 
diff --git a/mesalib/src/mesa/state_tracker/st_cb_condrender.c b/mesalib/src/mesa/state_tracker/st_cb_condrender.c
index 679527569..64c6c117f 100644
--- a/mesalib/src/mesa/state_tracker/st_cb_condrender.c
+++ b/mesalib/src/mesa/state_tracker/st_cb_condrender.c
@@ -1,96 +1,103 @@
-/**************************************************************************
- * 
- * Copyright 2009 VMware, Inc.
- * All Rights Reserved.
- * 
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- * 
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL THE AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- * 
- **************************************************************************/
-
-
-/**
- * glBegin/EndCondtionalRender functions
- *
- * \author Brian Paul
- */
-
-
-#include "main/imports.h"
-#include "main/context.h"
-
-#include "pipe/p_context.h"
-#include "pipe/p_defines.h"
-#include "st_context.h"
-#include "st_cb_queryobj.h"
-#include "st_cb_condrender.h"
-
-
-/**
- * Called via ctx->Driver.BeginConditionalRender()
- */
-static void
-st_BeginConditionalRender(struct gl_context *ctx, struct gl_query_object *q,
-                          GLenum mode)
-{
-   struct st_query_object *stq = st_query_object(q);
-   struct pipe_context *pipe = st_context(ctx)->pipe;
-   uint m;
-
-   switch (mode) {
-   case GL_QUERY_WAIT:
-      m = PIPE_RENDER_COND_WAIT;
-      break;
-   case GL_QUERY_NO_WAIT:
-      m = PIPE_RENDER_COND_NO_WAIT;
-      break;
-   case GL_QUERY_BY_REGION_WAIT:
-      m = PIPE_RENDER_COND_BY_REGION_WAIT;
-      break;
-   case GL_QUERY_BY_REGION_NO_WAIT:
-      m = PIPE_RENDER_COND_BY_REGION_NO_WAIT;
-      break;
-   default:
-      assert(0 && "bad mode in st_BeginConditionalRender");
-      m = PIPE_RENDER_COND_WAIT;
-   }
-
-   pipe->render_condition(pipe, stq->pq, m);
-}
-
-
-/**
- * Called via ctx->Driver.BeginConditionalRender()
- */
-static void
-st_EndConditionalRender(struct gl_context *ctx, struct gl_query_object *q)
-{
-   struct pipe_context *pipe = st_context(ctx)->pipe;
-   (void) q;
-   pipe->render_condition(pipe, NULL, 0);
-}
-
-
-
-void st_init_cond_render_functions(struct dd_function_table *functions)
-{
-   functions->BeginConditionalRender = st_BeginConditionalRender;
-   functions->EndConditionalRender = st_EndConditionalRender;
-}
+/**************************************************************************
+ * 
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+
+/**
+ * glBegin/EndCondtionalRender functions
+ *
+ * \author Brian Paul
+ */
+
+
+#include "main/imports.h"
+#include "main/context.h"
+
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "st_context.h"
+#include "st_cb_queryobj.h"
+#include "st_cb_condrender.h"
+
+
+/**
+ * Called via ctx->Driver.BeginConditionalRender()
+ */
+static void
+st_BeginConditionalRender(struct gl_context *ctx, struct gl_query_object *q,
+                          GLenum mode)
+{
+   struct st_query_object *stq = st_query_object(q);
+   struct st_context *st = st_context(ctx);
+   struct pipe_context *pipe = st->pipe;
+   uint m;
+
+   switch (mode) {
+   case GL_QUERY_WAIT:
+      m = PIPE_RENDER_COND_WAIT;
+      break;
+   case GL_QUERY_NO_WAIT:
+      m = PIPE_RENDER_COND_NO_WAIT;
+      break;
+   case GL_QUERY_BY_REGION_WAIT:
+      m = PIPE_RENDER_COND_BY_REGION_WAIT;
+      break;
+   case GL_QUERY_BY_REGION_NO_WAIT:
+      m = PIPE_RENDER_COND_BY_REGION_NO_WAIT;
+      break;
+   default:
+      assert(0 && "bad mode in st_BeginConditionalRender");
+      m = PIPE_RENDER_COND_WAIT;
+   }
+
+   st->render_condition = stq->pq;
+   st->condition_mode = m;
+
+   pipe->render_condition(pipe, stq->pq, m);
+}
+
+
+/**
+ * Called via ctx->Driver.BeginConditionalRender()
+ */
+static void
+st_EndConditionalRender(struct gl_context *ctx, struct gl_query_object *q)
+{
+   struct st_context *st = st_context(ctx);
+   struct pipe_context *pipe = st->pipe;
+   (void) q;
+
+   pipe->render_condition(pipe, NULL, 0);
+   st->render_condition = NULL;
+}
+
+
+
+void st_init_cond_render_functions(struct dd_function_table *functions)
+{
+   functions->BeginConditionalRender = st_BeginConditionalRender;
+   functions->EndConditionalRender = st_EndConditionalRender;
+}
diff --git a/mesalib/src/mesa/state_tracker/st_cb_drawpixels.c b/mesalib/src/mesa/state_tracker/st_cb_drawpixels.c
index 29c1df4ae..965fbcd1d 100644
--- a/mesalib/src/mesa/state_tracker/st_cb_drawpixels.c
+++ b/mesalib/src/mesa/state_tracker/st_cb_drawpixels.c
@@ -1247,7 +1247,8 @@ blit_copy_pixels(struct gl_context *ctx, GLint srcx, GLint srcy,
        !ctx->VertexProgram.Enabled &&
        !ctx->Shader.CurrentFragmentProgram &&
        st_fb_orientation(ctx->ReadBuffer) == st_fb_orientation(ctx->DrawBuffer) &&
-       ctx->DrawBuffer->_NumColorDrawBuffers == 1) {
+       ctx->DrawBuffer->_NumColorDrawBuffers == 1 &&
+       !ctx->Query.CondRenderQuery) {
       struct st_renderbuffer *rbRead, *rbDraw;
       GLint drawX, drawY;
 
diff --git a/mesalib/src/mesa/state_tracker/st_cb_fbo.c b/mesalib/src/mesa/state_tracker/st_cb_fbo.c
index 2e87d202c..64424f776 100644
--- a/mesalib/src/mesa/state_tracker/st_cb_fbo.c
+++ b/mesalib/src/mesa/state_tracker/st_cb_fbo.c
@@ -1,665 +1,662 @@
-/**************************************************************************
- * 
- * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
- * All Rights Reserved.
- * 
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- * 
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- * 
- **************************************************************************/
-
-
-/**
- * Framebuffer/renderbuffer functions.
- *
- * \author Brian Paul
- */
-
-
-#include "main/imports.h"
-#include "main/context.h"
-#include "main/fbobject.h"
-#include "main/framebuffer.h"
-#include "main/macros.h"
-#include "main/mfeatures.h"
-#include "main/renderbuffer.h"
-
-#include "pipe/p_context.h"
-#include "pipe/p_defines.h"
-#include "pipe/p_screen.h"
-#include "st_context.h"
-#include "st_cb_fbo.h"
-#include "st_cb_flush.h"
-#include "st_format.h"
-#include "st_texture.h"
-#include "st_manager.h"
-
-#include "util/u_format.h"
-#include "util/u_inlines.h"
-#include "util/u_surface.h"
-
-
-/**
- * gl_renderbuffer::AllocStorage()
- * This is called to allocate the original drawing surface, and
- * during window resize.
- */
-static GLboolean
-st_renderbuffer_alloc_storage(struct gl_context * ctx,
-                              struct gl_renderbuffer *rb,
-                              GLenum internalFormat,
-                              GLuint width, GLuint height)
-{
-   struct st_context *st = st_context(ctx);
-   struct pipe_context *pipe = st->pipe;
-   struct pipe_screen *screen = st->pipe->screen;
-   struct st_renderbuffer *strb = st_renderbuffer(rb);
-   enum pipe_format format;
-   struct pipe_surface surf_tmpl;
-
-   if (strb->format != PIPE_FORMAT_NONE)
-      format = strb->format;
-   else
-      format = st_choose_renderbuffer_format(screen, internalFormat,
-                                             rb->NumSamples);
-
-   if (format == PIPE_FORMAT_NONE) {
-      return FALSE;
-   }
-
-   /* init renderbuffer fields */
-   strb->Base.Width  = width;
-   strb->Base.Height = height;
-   strb->Base.Format = st_pipe_format_to_mesa_format(format);
-   strb->Base._BaseFormat = _mesa_base_fbo_format(ctx, internalFormat);
-   strb->Base.DataType = st_format_datatype(format);
-   strb->format = format;
-
-   strb->defined = GL_FALSE;  /* undefined contents now */
-
-   if (strb->software) {
-      size_t size;
-      
-      free(strb->data);
-
-      assert(strb->format != PIPE_FORMAT_NONE);
-      
-      strb->stride = util_format_get_stride(strb->format, width);
-      size = util_format_get_2d_size(strb->format, strb->stride, height);
-      
-      strb->data = malloc(size);
-      
-      return strb->data != NULL;
-   }
-   else {
-      struct pipe_resource template;
-    
-      /* Free the old surface and texture
-       */
-      pipe_surface_reference( &strb->surface, NULL );
-      pipe_resource_reference( &strb->texture, NULL );
-      pipe_sampler_view_reference(&strb->sampler_view, NULL);
-
-      /* Setup new texture template.
-       */
-      memset(&template, 0, sizeof(template));
-      template.target = st->internal_target;
-      template.format = format;
-      template.width0 = width;
-      template.height0 = height;
-      template.depth0 = 1;
-      template.array_size = 1;
-      template.last_level = 0;
-      template.nr_samples = rb->NumSamples;
-      if (util_format_is_depth_or_stencil(format)) {
-         template.bind = PIPE_BIND_DEPTH_STENCIL;
-      }
-      else {
-         template.bind = (PIPE_BIND_DISPLAY_TARGET |
-                          PIPE_BIND_RENDER_TARGET);
-      }
-
-      strb->texture = screen->resource_create(screen, &template);
-
-      if (!strb->texture) 
-         return FALSE;
-
-      memset(&surf_tmpl, 0, sizeof(surf_tmpl));
-      u_surface_default_template(&surf_tmpl, strb->texture, template.bind);
-      strb->surface = pipe->create_surface(pipe,
-                                           strb->texture,
-                                           &surf_tmpl);
-      if (strb->surface) {
-         assert(strb->surface->texture);
-         assert(strb->surface->format);
-         assert(strb->surface->width == width);
-         assert(strb->surface->height == height);
-      }
-
-      return strb->surface != NULL;
-   }
-}
-
-
-/**
- * gl_renderbuffer::Delete()
- */
-static void
-st_renderbuffer_delete(struct gl_renderbuffer *rb)
-{
-   struct st_renderbuffer *strb = st_renderbuffer(rb);
-   ASSERT(strb);
-   pipe_surface_reference(&strb->surface, NULL);
-   pipe_resource_reference(&strb->texture, NULL);
-   pipe_sampler_view_reference(&strb->sampler_view, NULL);
-   free(strb->data);
-   free(strb);
-}
-
-
-/**
- * gl_renderbuffer::GetPointer()
- */
-static void *
-null_get_pointer(struct gl_context * ctx, struct gl_renderbuffer *rb,
-                 GLint x, GLint y)
-{
-   /* By returning NULL we force all software rendering to go through
-    * the span routines.
-    */
-#if 0
-   assert(0);  /* Should never get called with softpipe */
-#endif
-   return NULL;
-}
-
-
-/**
- * Called via ctx->Driver.NewFramebuffer()
- */
-static struct gl_framebuffer *
-st_new_framebuffer(struct gl_context *ctx, GLuint name)
-{
-   /* XXX not sure we need to subclass gl_framebuffer for pipe */
-   return _mesa_new_framebuffer(ctx, name);
-}
-
-
-/**
- * Called via ctx->Driver.NewRenderbuffer()
- */
-static struct gl_renderbuffer *
-st_new_renderbuffer(struct gl_context *ctx, GLuint name)
-{
-   struct st_renderbuffer *strb = ST_CALLOC_STRUCT(st_renderbuffer);
-   if (strb) {
-      _mesa_init_renderbuffer(&strb->Base, name);
-      strb->Base.Delete = st_renderbuffer_delete;
-      strb->Base.AllocStorage = st_renderbuffer_alloc_storage;
-      strb->Base.GetPointer = null_get_pointer;
-      strb->format = PIPE_FORMAT_NONE;
-      return &strb->Base;
-   }
-   return NULL;
-}
-
-
-/**
- * Allocate a renderbuffer for a an on-screen window (not a user-created
- * renderbuffer).  The window system code determines the format.
- */
-struct gl_renderbuffer *
-st_new_renderbuffer_fb(enum pipe_format format, int samples, boolean sw)
-{
-   struct st_renderbuffer *strb;
-
-   strb = ST_CALLOC_STRUCT(st_renderbuffer);
-   if (!strb) {
-      _mesa_error(NULL, GL_OUT_OF_MEMORY, "creating renderbuffer");
-      return NULL;
-   }
-
-   _mesa_init_renderbuffer(&strb->Base, 0);
-   strb->Base.ClassID = 0x4242; /* just a unique value */
-   strb->Base.NumSamples = samples;
-   strb->Base.Format = st_pipe_format_to_mesa_format(format);
-   strb->Base._BaseFormat = _mesa_get_format_base_format(strb->Base.Format);
-   strb->Base.DataType = st_format_datatype(format);
-   strb->format = format;
-   strb->software = sw;
-   
-   switch (format) {
-   case PIPE_FORMAT_R8G8B8A8_UNORM:
-   case PIPE_FORMAT_B8G8R8A8_UNORM:
-   case PIPE_FORMAT_A8R8G8B8_UNORM:
-   case PIPE_FORMAT_R8G8B8X8_UNORM:
-   case PIPE_FORMAT_B8G8R8X8_UNORM:
-   case PIPE_FORMAT_X8R8G8B8_UNORM:
-   case PIPE_FORMAT_B5G5R5A1_UNORM:
-   case PIPE_FORMAT_B4G4R4A4_UNORM:
-   case PIPE_FORMAT_B5G6R5_UNORM:
-      strb->Base.InternalFormat = GL_RGBA;
-      break;
-   case PIPE_FORMAT_Z16_UNORM:
-      strb->Base.InternalFormat = GL_DEPTH_COMPONENT16;
-      break;
-   case PIPE_FORMAT_Z32_UNORM:
-      strb->Base.InternalFormat = GL_DEPTH_COMPONENT32;
-      break;
-   case PIPE_FORMAT_Z24_UNORM_S8_USCALED:
-   case PIPE_FORMAT_S8_USCALED_Z24_UNORM:
-   case PIPE_FORMAT_Z24X8_UNORM:
-   case PIPE_FORMAT_X8Z24_UNORM:
-      strb->Base.InternalFormat = GL_DEPTH24_STENCIL8_EXT;
-      break;
-   case PIPE_FORMAT_S8_USCALED:
-      strb->Base.InternalFormat = GL_STENCIL_INDEX8_EXT;
-      break;
-   case PIPE_FORMAT_R16G16B16A16_SNORM:
-      strb->Base.InternalFormat = GL_RGBA16;
-      break;
-   case PIPE_FORMAT_R8_UNORM:
-      strb->Base.InternalFormat = GL_R8;
-      break;
-   case PIPE_FORMAT_R8G8_UNORM:
-      strb->Base.InternalFormat = GL_RG8;
-      break;
-   case PIPE_FORMAT_R16_UNORM:
-      strb->Base.InternalFormat = GL_R16;
-      break;
-   case PIPE_FORMAT_R16G16_UNORM:
-      strb->Base.InternalFormat = GL_RG16;
-      break;
-   default:
-      _mesa_problem(NULL,
-		    "Unexpected format in st_new_renderbuffer_fb");
-      free(strb);
-      return NULL;
-   }
-
-   /* st-specific methods */
-   strb->Base.Delete = st_renderbuffer_delete;
-   strb->Base.AllocStorage = st_renderbuffer_alloc_storage;
-   strb->Base.GetPointer = null_get_pointer;
-
-   /* surface is allocated in st_renderbuffer_alloc_storage() */
-   strb->surface = NULL;
-
-   return &strb->Base;
-}
-
-
-
-
-/**
- * Called via ctx->Driver.BindFramebufferEXT().
- */
-static void
-st_bind_framebuffer(struct gl_context *ctx, GLenum target,
-                    struct gl_framebuffer *fb, struct gl_framebuffer *fbread)
-{
-
-}
-
-/**
- * Called by ctx->Driver.FramebufferRenderbuffer
- */
-static void
-st_framebuffer_renderbuffer(struct gl_context *ctx, 
-                            struct gl_framebuffer *fb,
-                            GLenum attachment,
-                            struct gl_renderbuffer *rb)
-{
-   /* XXX no need for derivation? */
-   _mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb);
-}
-
-
-/**
- * Called by ctx->Driver.RenderTexture
- */
-static void
-st_render_texture(struct gl_context *ctx,
-                  struct gl_framebuffer *fb,
-                  struct gl_renderbuffer_attachment *att)
-{
-   struct st_context *st = st_context(ctx);
-   struct pipe_context *pipe = st->pipe;
-   struct st_renderbuffer *strb;
-   struct gl_renderbuffer *rb;
-   struct pipe_resource *pt = st_get_texobj_resource(att->Texture);
-   struct st_texture_object *stObj;
-   const struct gl_texture_image *texImage;
-   struct pipe_surface surf_tmpl;
-
-   /* When would this fail?  Perhaps assert? */
-   if (!pt) 
-      return;
-
-   /* get pointer to texture image we're rendeing to */
-   texImage = _mesa_get_attachment_teximage(att);
-
-   /* create new renderbuffer which wraps the texture image */
-   rb = st_new_renderbuffer(ctx, 0);
-   if (!rb) {
-      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glFramebufferTexture()");
-      return;
-   }
-
-   _mesa_reference_renderbuffer(&att->Renderbuffer, rb);
-   assert(rb->RefCount == 1);
-   rb->AllocStorage = NULL; /* should not get called */
-   strb = st_renderbuffer(rb);
-
-   assert(strb->Base.RefCount > 0);
-
-   /* get the texture for the texture object */
-   stObj = st_texture_object(att->Texture);
-
-   /* point renderbuffer at texobject */
-   strb->rtt = stObj;
-   strb->rtt_level = att->TextureLevel;
-   strb->rtt_face = att->CubeMapFace;
-   strb->rtt_slice = att->Zoffset;
-
-   rb->Width = texImage->Width2;
-   rb->Height = texImage->Height2;
-   rb->_BaseFormat = texImage->_BaseFormat;
-   /*printf("***** render to texture level %d: %d x %d\n", att->TextureLevel, rb->Width, rb->Height);*/
-
-   /*printf("***** pipe texture %d x %d\n", pt->width0, pt->height0);*/
-
-   pipe_resource_reference( &strb->texture, pt );
-
-   pipe_surface_reference(&strb->surface, NULL);
-
-   pipe_sampler_view_reference(&strb->sampler_view,
-                               st_get_texture_sampler_view(stObj, pipe));
-
-   assert(strb->rtt_level <= strb->texture->last_level);
-
-   /* new surface for rendering into the texture */
-   memset(&surf_tmpl, 0, sizeof(surf_tmpl));
-   surf_tmpl.format = ctx->Color.sRGBEnabled ? strb->texture->format : util_format_linear(strb->texture->format);
-   surf_tmpl.usage = PIPE_BIND_RENDER_TARGET;
-   surf_tmpl.u.tex.level = strb->rtt_level;
-   surf_tmpl.u.tex.first_layer = strb->rtt_face + strb->rtt_slice;
-   surf_tmpl.u.tex.last_layer = strb->rtt_face + strb->rtt_slice;
-   strb->surface = pipe->create_surface(pipe,
-                                        strb->texture,
-                                        &surf_tmpl);
-
-   strb->format = pt->format;
-
-   strb->Base.Format = st_pipe_format_to_mesa_format(pt->format);
-   strb->Base.DataType = st_format_datatype(pt->format);
-
-   /*
-   printf("RENDER TO TEXTURE obj=%p pt=%p surf=%p  %d x %d\n",
-          att->Texture, pt, strb->surface, rb->Width, rb->Height);
-   */
-
-   /* Invalidate buffer state so that the pipe's framebuffer state
-    * gets updated.
-    * That's where the new renderbuffer (which we just created) gets
-    * passed to the pipe as a (color/depth) render target.
-    */
-   st_invalidate_state(ctx, _NEW_BUFFERS);
-}
-
-
-/**
- * Called via ctx->Driver.FinishRenderTexture.
- */
-static void
-st_finish_render_texture(struct gl_context *ctx,
-                         struct gl_renderbuffer_attachment *att)
-{
-   struct st_renderbuffer *strb = st_renderbuffer(att->Renderbuffer);
-
-   if (!strb)
-      return;
-
-   strb->rtt = NULL;
-
-   /*
-   printf("FINISH RENDER TO TEXTURE surf=%p\n", strb->surface);
-   */
-
-   /* restore previous framebuffer state */
-   st_invalidate_state(ctx, _NEW_BUFFERS);
-}
-
-
-/**
- * Validate a renderbuffer attachment for a particular set of bindings.
- */
-static GLboolean
-st_validate_attachment(struct gl_context *ctx,
-		       struct pipe_screen *screen,
-		       const struct gl_renderbuffer_attachment *att,
-		       unsigned bindings)
-{
-   const struct st_texture_object *stObj = st_texture_object(att->Texture);
-   enum pipe_format format;
-   gl_format texFormat;
-
-   /* Only validate texture attachments for now, since
-    * st_renderbuffer_alloc_storage makes sure that
-    * the format is supported.
-    */
-   if (att->Type != GL_TEXTURE)
-      return GL_TRUE;
-
-   if (!stObj)
-      return GL_FALSE;
-
-   format = stObj->pt->format;
-   texFormat = _mesa_get_attachment_teximage_const(att)->TexFormat;
-
-   /* If the encoding is sRGB and sRGB rendering cannot be enabled,
-    * check for linear format support instead.
-    * Later when we create a surface, we change the format to a linear one. */
-   if (!ctx->Const.sRGBCapable &&
-       _mesa_get_format_color_encoding(texFormat) == GL_SRGB) {
-      const gl_format linearFormat = _mesa_get_srgb_format_linear(texFormat);
-      format = st_mesa_format_to_pipe_format(linearFormat);
-   }
-
-   return screen->is_format_supported(screen, format,
-                                      PIPE_TEXTURE_2D,
-                                      stObj->pt->nr_samples, bindings);
-}
-
-
-/**
- * Check if two renderbuffer attachments name a combined depth/stencil
- * renderbuffer.
- */
-GLboolean
-st_is_depth_stencil_combined(const struct gl_renderbuffer_attachment *depth,
-                             const struct gl_renderbuffer_attachment *stencil)
-{
-   assert(depth && stencil);
-
-   if (depth->Type == stencil->Type) {
-      if (depth->Type == GL_RENDERBUFFER_EXT &&
-          depth->Renderbuffer == stencil->Renderbuffer)
-         return GL_TRUE;
-
-      if (depth->Type == GL_TEXTURE &&
-          depth->Texture == stencil->Texture)
-         return GL_TRUE;
-   }
-
-   return GL_FALSE;
-}
- 
-
-/**
- * Check that the framebuffer configuration is valid in terms of what
- * the driver can support.
- *
- * For Gallium we only supports combined Z+stencil, not separate buffers.
- */
-static void
-st_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb)
-{
-   struct st_context *st = st_context(ctx);
-   struct pipe_screen *screen = st->pipe->screen;
-   const struct gl_renderbuffer_attachment *depth =
-         &fb->Attachment[BUFFER_DEPTH];
-   const struct gl_renderbuffer_attachment *stencil =
-         &fb->Attachment[BUFFER_STENCIL];
-   GLuint i;
-   enum pipe_format first_format = PIPE_FORMAT_NONE;
-   boolean mixed_formats =
-         screen->get_param(screen, PIPE_CAP_MIXED_COLORBUFFER_FORMATS) != 0;
-
-   if (depth->Type && stencil->Type && depth->Type != stencil->Type) {
-      fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
-      return;
-   }
-   if (depth->Type == GL_RENDERBUFFER_EXT &&
-       stencil->Type == GL_RENDERBUFFER_EXT &&
-       depth->Renderbuffer != stencil->Renderbuffer) {
-      fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
-      return;
-   }
-   if (depth->Type == GL_TEXTURE &&
-       stencil->Type == GL_TEXTURE &&
-       depth->Texture != stencil->Texture) {
-      fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
-      return;
-   }
-
-   if (!st_validate_attachment(ctx,
-                               screen,
-                               depth,
-			       PIPE_BIND_DEPTH_STENCIL)) {
-      fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
-      return;
-   }
-   if (!st_validate_attachment(ctx,
-                               screen,
-                               stencil,
-			       PIPE_BIND_DEPTH_STENCIL)) {
-      fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
-      return;
-   }
-   for (i = 0; i < ctx->Const.MaxColorAttachments; i++) {
-      struct gl_renderbuffer_attachment *att =
-            &fb->Attachment[BUFFER_COLOR0 + i];
-      enum pipe_format format;
-
-      if (!st_validate_attachment(ctx,
-                                  screen,
-				  att,
-				  PIPE_BIND_RENDER_TARGET)) {
-	 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
-	 return;
-      }
-
-      if (!mixed_formats) {
-         /* Disallow mixed formats. */
-         if (att->Type != GL_NONE) {
-            format = st_renderbuffer(att->Renderbuffer)->surface->format;
-         } else {
-            continue;
-         }
-
-         if (first_format == PIPE_FORMAT_NONE) {
-            first_format = format;
-         } else if (format != first_format) {
-            fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
-            return;
-         }
-      }
-   }
-}
-
-
-/**
- * Called via glDrawBuffer.
- */
-static void
-st_DrawBuffers(struct gl_context *ctx, GLsizei count, const GLenum *buffers)
-{
-   struct st_context *st = st_context(ctx);
-   struct gl_framebuffer *fb = ctx->DrawBuffer;
-   GLuint i;
-
-   (void) count;
-   (void) buffers;
-
-   /* add the renderbuffers on demand */
-   for (i = 0; i < fb->_NumColorDrawBuffers; i++) {
-      gl_buffer_index idx = fb->_ColorDrawBufferIndexes[i];
-      st_manager_add_color_renderbuffer(st, fb, idx);
-   }
-}
-
-
-/**
- * Called via glReadBuffer.
- */
-static void
-st_ReadBuffer(struct gl_context *ctx, GLenum buffer)
-{
-   struct st_context *st = st_context(ctx);
-   struct gl_framebuffer *fb = ctx->ReadBuffer;
-
-   (void) buffer;
-
-   /* add the renderbuffer on demand */
-   st_manager_add_color_renderbuffer(st, fb, fb->_ColorReadBufferIndex);
-}
-
-
-void st_init_fbo_functions(struct dd_function_table *functions)
-{
-#if FEATURE_EXT_framebuffer_object
-   functions->NewFramebuffer = st_new_framebuffer;
-   functions->NewRenderbuffer = st_new_renderbuffer;
-   functions->BindFramebuffer = st_bind_framebuffer;
-   functions->FramebufferRenderbuffer = st_framebuffer_renderbuffer;
-   functions->RenderTexture = st_render_texture;
-   functions->FinishRenderTexture = st_finish_render_texture;
-   functions->ValidateFramebuffer = st_validate_framebuffer;
-#endif
-   /* no longer needed by core Mesa, drivers handle resizes...
-   functions->ResizeBuffers = st_resize_buffers;
-   */
-
-   functions->DrawBuffers = st_DrawBuffers;
-   functions->ReadBuffer = st_ReadBuffer;
-}
-
-/* XXX unused ? */
-struct pipe_sampler_view *
-st_get_renderbuffer_sampler_view(struct st_renderbuffer *rb,
-                                 struct pipe_context *pipe)
-{
-   if (!rb->sampler_view) {
-      rb->sampler_view = st_create_texture_sampler_view(pipe, rb->texture);
-   }
-
-   return rb->sampler_view;
-}
+/**************************************************************************
+ * 
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+
+/**
+ * Framebuffer/renderbuffer functions.
+ *
+ * \author Brian Paul
+ */
+
+
+#include "main/imports.h"
+#include "main/context.h"
+#include "main/fbobject.h"
+#include "main/framebuffer.h"
+#include "main/macros.h"
+#include "main/mfeatures.h"
+#include "main/renderbuffer.h"
+
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_screen.h"
+#include "st_context.h"
+#include "st_cb_fbo.h"
+#include "st_cb_flush.h"
+#include "st_format.h"
+#include "st_texture.h"
+#include "st_manager.h"
+
+#include "util/u_format.h"
+#include "util/u_inlines.h"
+#include "util/u_surface.h"
+
+
+/**
+ * gl_renderbuffer::AllocStorage()
+ * This is called to allocate the original drawing surface, and
+ * during window resize.
+ */
+static GLboolean
+st_renderbuffer_alloc_storage(struct gl_context * ctx,
+                              struct gl_renderbuffer *rb,
+                              GLenum internalFormat,
+                              GLuint width, GLuint height)
+{
+   struct st_context *st = st_context(ctx);
+   struct pipe_context *pipe = st->pipe;
+   struct pipe_screen *screen = st->pipe->screen;
+   struct st_renderbuffer *strb = st_renderbuffer(rb);
+   enum pipe_format format;
+   struct pipe_surface surf_tmpl;
+
+   format = st_choose_renderbuffer_format(screen, internalFormat,
+                                          rb->NumSamples);
+
+   if (format == PIPE_FORMAT_NONE) {
+      return FALSE;
+   }
+
+   /* init renderbuffer fields */
+   strb->Base.Width  = width;
+   strb->Base.Height = height;
+   strb->Base.Format = st_pipe_format_to_mesa_format(format);
+   strb->Base._BaseFormat = _mesa_base_fbo_format(ctx, internalFormat);
+   strb->Base.DataType = st_format_datatype(format);
+   strb->format = format;
+
+   strb->defined = GL_FALSE;  /* undefined contents now */
+
+   if (strb->software) {
+      size_t size;
+      
+      free(strb->data);
+
+      assert(strb->format != PIPE_FORMAT_NONE);
+      
+      strb->stride = util_format_get_stride(strb->format, width);
+      size = util_format_get_2d_size(strb->format, strb->stride, height);
+      
+      strb->data = malloc(size);
+      
+      return strb->data != NULL;
+   }
+   else {
+      struct pipe_resource template;
+    
+      /* Free the old surface and texture
+       */
+      pipe_surface_reference( &strb->surface, NULL );
+      pipe_resource_reference( &strb->texture, NULL );
+      pipe_sampler_view_reference(&strb->sampler_view, NULL);
+
+      /* Setup new texture template.
+       */
+      memset(&template, 0, sizeof(template));
+      template.target = st->internal_target;
+      template.format = format;
+      template.width0 = width;
+      template.height0 = height;
+      template.depth0 = 1;
+      template.array_size = 1;
+      template.last_level = 0;
+      template.nr_samples = rb->NumSamples;
+      if (util_format_is_depth_or_stencil(format)) {
+         template.bind = PIPE_BIND_DEPTH_STENCIL;
+      }
+      else {
+         template.bind = (PIPE_BIND_DISPLAY_TARGET |
+                          PIPE_BIND_RENDER_TARGET);
+      }
+
+      strb->texture = screen->resource_create(screen, &template);
+
+      if (!strb->texture) 
+         return FALSE;
+
+      memset(&surf_tmpl, 0, sizeof(surf_tmpl));
+      u_surface_default_template(&surf_tmpl, strb->texture, template.bind);
+      strb->surface = pipe->create_surface(pipe,
+                                           strb->texture,
+                                           &surf_tmpl);
+      if (strb->surface) {
+         assert(strb->surface->texture);
+         assert(strb->surface->format);
+         assert(strb->surface->width == width);
+         assert(strb->surface->height == height);
+      }
+
+      return strb->surface != NULL;
+   }
+}
+
+
+/**
+ * gl_renderbuffer::Delete()
+ */
+static void
+st_renderbuffer_delete(struct gl_renderbuffer *rb)
+{
+   struct st_renderbuffer *strb = st_renderbuffer(rb);
+   ASSERT(strb);
+   pipe_surface_reference(&strb->surface, NULL);
+   pipe_resource_reference(&strb->texture, NULL);
+   pipe_sampler_view_reference(&strb->sampler_view, NULL);
+   free(strb->data);
+   free(strb);
+}
+
+
+/**
+ * gl_renderbuffer::GetPointer()
+ */
+static void *
+null_get_pointer(struct gl_context * ctx, struct gl_renderbuffer *rb,
+                 GLint x, GLint y)
+{
+   /* By returning NULL we force all software rendering to go through
+    * the span routines.
+    */
+#if 0
+   assert(0);  /* Should never get called with softpipe */
+#endif
+   return NULL;
+}
+
+
+/**
+ * Called via ctx->Driver.NewFramebuffer()
+ */
+static struct gl_framebuffer *
+st_new_framebuffer(struct gl_context *ctx, GLuint name)
+{
+   /* XXX not sure we need to subclass gl_framebuffer for pipe */
+   return _mesa_new_framebuffer(ctx, name);
+}
+
+
+/**
+ * Called via ctx->Driver.NewRenderbuffer()
+ */
+static struct gl_renderbuffer *
+st_new_renderbuffer(struct gl_context *ctx, GLuint name)
+{
+   struct st_renderbuffer *strb = ST_CALLOC_STRUCT(st_renderbuffer);
+   if (strb) {
+      _mesa_init_renderbuffer(&strb->Base, name);
+      strb->Base.Delete = st_renderbuffer_delete;
+      strb->Base.AllocStorage = st_renderbuffer_alloc_storage;
+      strb->Base.GetPointer = null_get_pointer;
+      strb->format = PIPE_FORMAT_NONE;
+      return &strb->Base;
+   }
+   return NULL;
+}
+
+
+/**
+ * Allocate a renderbuffer for a an on-screen window (not a user-created
+ * renderbuffer).  The window system code determines the format.
+ */
+struct gl_renderbuffer *
+st_new_renderbuffer_fb(enum pipe_format format, int samples, boolean sw)
+{
+   struct st_renderbuffer *strb;
+
+   strb = ST_CALLOC_STRUCT(st_renderbuffer);
+   if (!strb) {
+      _mesa_error(NULL, GL_OUT_OF_MEMORY, "creating renderbuffer");
+      return NULL;
+   }
+
+   _mesa_init_renderbuffer(&strb->Base, 0);
+   strb->Base.ClassID = 0x4242; /* just a unique value */
+   strb->Base.NumSamples = samples;
+   strb->Base.Format = st_pipe_format_to_mesa_format(format);
+   strb->Base._BaseFormat = _mesa_get_format_base_format(strb->Base.Format);
+   strb->Base.DataType = st_format_datatype(format);
+   strb->format = format;
+   strb->software = sw;
+   
+   switch (format) {
+   case PIPE_FORMAT_R8G8B8A8_UNORM:
+   case PIPE_FORMAT_B8G8R8A8_UNORM:
+   case PIPE_FORMAT_A8R8G8B8_UNORM:
+   case PIPE_FORMAT_R8G8B8X8_UNORM:
+   case PIPE_FORMAT_B8G8R8X8_UNORM:
+   case PIPE_FORMAT_X8R8G8B8_UNORM:
+   case PIPE_FORMAT_B5G5R5A1_UNORM:
+   case PIPE_FORMAT_B4G4R4A4_UNORM:
+   case PIPE_FORMAT_B5G6R5_UNORM:
+      strb->Base.InternalFormat = GL_RGBA;
+      break;
+   case PIPE_FORMAT_Z16_UNORM:
+      strb->Base.InternalFormat = GL_DEPTH_COMPONENT16;
+      break;
+   case PIPE_FORMAT_Z32_UNORM:
+      strb->Base.InternalFormat = GL_DEPTH_COMPONENT32;
+      break;
+   case PIPE_FORMAT_Z24_UNORM_S8_USCALED:
+   case PIPE_FORMAT_S8_USCALED_Z24_UNORM:
+   case PIPE_FORMAT_Z24X8_UNORM:
+   case PIPE_FORMAT_X8Z24_UNORM:
+      strb->Base.InternalFormat = GL_DEPTH24_STENCIL8_EXT;
+      break;
+   case PIPE_FORMAT_S8_USCALED:
+      strb->Base.InternalFormat = GL_STENCIL_INDEX8_EXT;
+      break;
+   case PIPE_FORMAT_R16G16B16A16_SNORM:
+      strb->Base.InternalFormat = GL_RGBA16;
+      break;
+   case PIPE_FORMAT_R8_UNORM:
+      strb->Base.InternalFormat = GL_R8;
+      break;
+   case PIPE_FORMAT_R8G8_UNORM:
+      strb->Base.InternalFormat = GL_RG8;
+      break;
+   case PIPE_FORMAT_R16_UNORM:
+      strb->Base.InternalFormat = GL_R16;
+      break;
+   case PIPE_FORMAT_R16G16_UNORM:
+      strb->Base.InternalFormat = GL_RG16;
+      break;
+   default:
+      _mesa_problem(NULL,
+		    "Unexpected format in st_new_renderbuffer_fb");
+      free(strb);
+      return NULL;
+   }
+
+   /* st-specific methods */
+   strb->Base.Delete = st_renderbuffer_delete;
+   strb->Base.AllocStorage = st_renderbuffer_alloc_storage;
+   strb->Base.GetPointer = null_get_pointer;
+
+   /* surface is allocated in st_renderbuffer_alloc_storage() */
+   strb->surface = NULL;
+
+   return &strb->Base;
+}
+
+
+
+
+/**
+ * Called via ctx->Driver.BindFramebufferEXT().
+ */
+static void
+st_bind_framebuffer(struct gl_context *ctx, GLenum target,
+                    struct gl_framebuffer *fb, struct gl_framebuffer *fbread)
+{
+
+}
+
+/**
+ * Called by ctx->Driver.FramebufferRenderbuffer
+ */
+static void
+st_framebuffer_renderbuffer(struct gl_context *ctx, 
+                            struct gl_framebuffer *fb,
+                            GLenum attachment,
+                            struct gl_renderbuffer *rb)
+{
+   /* XXX no need for derivation? */
+   _mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb);
+}
+
+
+/**
+ * Called by ctx->Driver.RenderTexture
+ */
+static void
+st_render_texture(struct gl_context *ctx,
+                  struct gl_framebuffer *fb,
+                  struct gl_renderbuffer_attachment *att)
+{
+   struct st_context *st = st_context(ctx);
+   struct pipe_context *pipe = st->pipe;
+   struct st_renderbuffer *strb;
+   struct gl_renderbuffer *rb;
+   struct pipe_resource *pt = st_get_texobj_resource(att->Texture);
+   struct st_texture_object *stObj;
+   const struct gl_texture_image *texImage;
+   struct pipe_surface surf_tmpl;
+
+   /* When would this fail?  Perhaps assert? */
+   if (!pt) 
+      return;
+
+   /* get pointer to texture image we're rendeing to */
+   texImage = _mesa_get_attachment_teximage(att);
+
+   /* create new renderbuffer which wraps the texture image */
+   rb = st_new_renderbuffer(ctx, 0);
+   if (!rb) {
+      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glFramebufferTexture()");
+      return;
+   }
+
+   _mesa_reference_renderbuffer(&att->Renderbuffer, rb);
+   assert(rb->RefCount == 1);
+   rb->AllocStorage = NULL; /* should not get called */
+   strb = st_renderbuffer(rb);
+
+   assert(strb->Base.RefCount > 0);
+
+   /* get the texture for the texture object */
+   stObj = st_texture_object(att->Texture);
+
+   /* point renderbuffer at texobject */
+   strb->rtt = stObj;
+   strb->rtt_level = att->TextureLevel;
+   strb->rtt_face = att->CubeMapFace;
+   strb->rtt_slice = att->Zoffset;
+
+   rb->Width = texImage->Width2;
+   rb->Height = texImage->Height2;
+   rb->_BaseFormat = texImage->_BaseFormat;
+   /*printf("***** render to texture level %d: %d x %d\n", att->TextureLevel, rb->Width, rb->Height);*/
+
+   /*printf("***** pipe texture %d x %d\n", pt->width0, pt->height0);*/
+
+   pipe_resource_reference( &strb->texture, pt );
+
+   pipe_surface_reference(&strb->surface, NULL);
+
+   pipe_sampler_view_reference(&strb->sampler_view,
+                               st_get_texture_sampler_view(stObj, pipe));
+
+   assert(strb->rtt_level <= strb->texture->last_level);
+
+   /* new surface for rendering into the texture */
+   memset(&surf_tmpl, 0, sizeof(surf_tmpl));
+   surf_tmpl.format = ctx->Color.sRGBEnabled ? strb->texture->format : util_format_linear(strb->texture->format);
+   surf_tmpl.usage = PIPE_BIND_RENDER_TARGET;
+   surf_tmpl.u.tex.level = strb->rtt_level;
+   surf_tmpl.u.tex.first_layer = strb->rtt_face + strb->rtt_slice;
+   surf_tmpl.u.tex.last_layer = strb->rtt_face + strb->rtt_slice;
+   strb->surface = pipe->create_surface(pipe,
+                                        strb->texture,
+                                        &surf_tmpl);
+
+   strb->format = pt->format;
+
+   strb->Base.Format = st_pipe_format_to_mesa_format(pt->format);
+   strb->Base.DataType = st_format_datatype(pt->format);
+
+   /*
+   printf("RENDER TO TEXTURE obj=%p pt=%p surf=%p  %d x %d\n",
+          att->Texture, pt, strb->surface, rb->Width, rb->Height);
+   */
+
+   /* Invalidate buffer state so that the pipe's framebuffer state
+    * gets updated.
+    * That's where the new renderbuffer (which we just created) gets
+    * passed to the pipe as a (color/depth) render target.
+    */
+   st_invalidate_state(ctx, _NEW_BUFFERS);
+}
+
+
+/**
+ * Called via ctx->Driver.FinishRenderTexture.
+ */
+static void
+st_finish_render_texture(struct gl_context *ctx,
+                         struct gl_renderbuffer_attachment *att)
+{
+   struct st_renderbuffer *strb = st_renderbuffer(att->Renderbuffer);
+
+   if (!strb)
+      return;
+
+   strb->rtt = NULL;
+
+   /*
+   printf("FINISH RENDER TO TEXTURE surf=%p\n", strb->surface);
+   */
+
+   /* restore previous framebuffer state */
+   st_invalidate_state(ctx, _NEW_BUFFERS);
+}
+
+
+/**
+ * Validate a renderbuffer attachment for a particular set of bindings.
+ */
+static GLboolean
+st_validate_attachment(struct gl_context *ctx,
+		       struct pipe_screen *screen,
+		       const struct gl_renderbuffer_attachment *att,
+		       unsigned bindings)
+{
+   const struct st_texture_object *stObj = st_texture_object(att->Texture);
+   enum pipe_format format;
+   gl_format texFormat;
+
+   /* Only validate texture attachments for now, since
+    * st_renderbuffer_alloc_storage makes sure that
+    * the format is supported.
+    */
+   if (att->Type != GL_TEXTURE)
+      return GL_TRUE;
+
+   if (!stObj)
+      return GL_FALSE;
+
+   format = stObj->pt->format;
+   texFormat = _mesa_get_attachment_teximage_const(att)->TexFormat;
+
+   /* If the encoding is sRGB and sRGB rendering cannot be enabled,
+    * check for linear format support instead.
+    * Later when we create a surface, we change the format to a linear one. */
+   if (!ctx->Const.sRGBCapable &&
+       _mesa_get_format_color_encoding(texFormat) == GL_SRGB) {
+      const gl_format linearFormat = _mesa_get_srgb_format_linear(texFormat);
+      format = st_mesa_format_to_pipe_format(linearFormat);
+   }
+
+   return screen->is_format_supported(screen, format,
+                                      PIPE_TEXTURE_2D,
+                                      stObj->pt->nr_samples, bindings);
+}
+
+
+/**
+ * Check if two renderbuffer attachments name a combined depth/stencil
+ * renderbuffer.
+ */
+GLboolean
+st_is_depth_stencil_combined(const struct gl_renderbuffer_attachment *depth,
+                             const struct gl_renderbuffer_attachment *stencil)
+{
+   assert(depth && stencil);
+
+   if (depth->Type == stencil->Type) {
+      if (depth->Type == GL_RENDERBUFFER_EXT &&
+          depth->Renderbuffer == stencil->Renderbuffer)
+         return GL_TRUE;
+
+      if (depth->Type == GL_TEXTURE &&
+          depth->Texture == stencil->Texture)
+         return GL_TRUE;
+   }
+
+   return GL_FALSE;
+}
+ 
+
+/**
+ * Check that the framebuffer configuration is valid in terms of what
+ * the driver can support.
+ *
+ * For Gallium we only supports combined Z+stencil, not separate buffers.
+ */
+static void
+st_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb)
+{
+   struct st_context *st = st_context(ctx);
+   struct pipe_screen *screen = st->pipe->screen;
+   const struct gl_renderbuffer_attachment *depth =
+         &fb->Attachment[BUFFER_DEPTH];
+   const struct gl_renderbuffer_attachment *stencil =
+         &fb->Attachment[BUFFER_STENCIL];
+   GLuint i;
+   enum pipe_format first_format = PIPE_FORMAT_NONE;
+   boolean mixed_formats =
+         screen->get_param(screen, PIPE_CAP_MIXED_COLORBUFFER_FORMATS) != 0;
+
+   if (depth->Type && stencil->Type && depth->Type != stencil->Type) {
+      fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
+      return;
+   }
+   if (depth->Type == GL_RENDERBUFFER_EXT &&
+       stencil->Type == GL_RENDERBUFFER_EXT &&
+       depth->Renderbuffer != stencil->Renderbuffer) {
+      fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
+      return;
+   }
+   if (depth->Type == GL_TEXTURE &&
+       stencil->Type == GL_TEXTURE &&
+       depth->Texture != stencil->Texture) {
+      fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
+      return;
+   }
+
+   if (!st_validate_attachment(ctx,
+                               screen,
+                               depth,
+			       PIPE_BIND_DEPTH_STENCIL)) {
+      fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
+      return;
+   }
+   if (!st_validate_attachment(ctx,
+                               screen,
+                               stencil,
+			       PIPE_BIND_DEPTH_STENCIL)) {
+      fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
+      return;
+   }
+   for (i = 0; i < ctx->Const.MaxColorAttachments; i++) {
+      struct gl_renderbuffer_attachment *att =
+            &fb->Attachment[BUFFER_COLOR0 + i];
+      enum pipe_format format;
+
+      if (!st_validate_attachment(ctx,
+                                  screen,
+				  att,
+				  PIPE_BIND_RENDER_TARGET)) {
+	 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
+	 return;
+      }
+
+      if (!mixed_formats) {
+         /* Disallow mixed formats. */
+         if (att->Type != GL_NONE) {
+            format = st_renderbuffer(att->Renderbuffer)->surface->format;
+         } else {
+            continue;
+         }
+
+         if (first_format == PIPE_FORMAT_NONE) {
+            first_format = format;
+         } else if (format != first_format) {
+            fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
+            return;
+         }
+      }
+   }
+}
+
+
+/**
+ * Called via glDrawBuffer.
+ */
+static void
+st_DrawBuffers(struct gl_context *ctx, GLsizei count, const GLenum *buffers)
+{
+   struct st_context *st = st_context(ctx);
+   struct gl_framebuffer *fb = ctx->DrawBuffer;
+   GLuint i;
+
+   (void) count;
+   (void) buffers;
+
+   /* add the renderbuffers on demand */
+   for (i = 0; i < fb->_NumColorDrawBuffers; i++) {
+      gl_buffer_index idx = fb->_ColorDrawBufferIndexes[i];
+      st_manager_add_color_renderbuffer(st, fb, idx);
+   }
+}
+
+
+/**
+ * Called via glReadBuffer.
+ */
+static void
+st_ReadBuffer(struct gl_context *ctx, GLenum buffer)
+{
+   struct st_context *st = st_context(ctx);
+   struct gl_framebuffer *fb = ctx->ReadBuffer;
+
+   (void) buffer;
+
+   /* add the renderbuffer on demand */
+   st_manager_add_color_renderbuffer(st, fb, fb->_ColorReadBufferIndex);
+}
+
+
+void st_init_fbo_functions(struct dd_function_table *functions)
+{
+#if FEATURE_EXT_framebuffer_object
+   functions->NewFramebuffer = st_new_framebuffer;
+   functions->NewRenderbuffer = st_new_renderbuffer;
+   functions->BindFramebuffer = st_bind_framebuffer;
+   functions->FramebufferRenderbuffer = st_framebuffer_renderbuffer;
+   functions->RenderTexture = st_render_texture;
+   functions->FinishRenderTexture = st_finish_render_texture;
+   functions->ValidateFramebuffer = st_validate_framebuffer;
+#endif
+   /* no longer needed by core Mesa, drivers handle resizes...
+   functions->ResizeBuffers = st_resize_buffers;
+   */
+
+   functions->DrawBuffers = st_DrawBuffers;
+   functions->ReadBuffer = st_ReadBuffer;
+}
+
+/* XXX unused ? */
+struct pipe_sampler_view *
+st_get_renderbuffer_sampler_view(struct st_renderbuffer *rb,
+                                 struct pipe_context *pipe)
+{
+   if (!rb->sampler_view) {
+      rb->sampler_view = st_create_texture_sampler_view(pipe, rb->texture);
+   }
+
+   return rb->sampler_view;
+}
diff --git a/mesalib/src/mesa/state_tracker/st_cb_texture.c b/mesalib/src/mesa/state_tracker/st_cb_texture.c
index 9d824b46c..88f62902b 100644
--- a/mesalib/src/mesa/state_tracker/st_cb_texture.c
+++ b/mesalib/src/mesa/state_tracker/st_cb_texture.c
@@ -795,6 +795,11 @@ decompress_with_blit(struct gl_context * ctx, GLenum target, GLint level,
       return;
    }
 
+   /* Disable conditional rendering. */
+   if (st->render_condition) {
+      pipe->render_condition(pipe, NULL, 0);
+   }
+
    /* blit/render/decompress */
    util_blit_pixels_tex(st->blit,
                         src_view,      /* pipe_resource (src) */
@@ -806,6 +811,12 @@ decompress_with_blit(struct gl_context * ctx, GLenum target, GLint level,
                         0.0,              /* z */
                         PIPE_TEX_MIPFILTER_NEAREST);
 
+   /* Restore conditional rendering state. */
+   if (st->render_condition) {
+      pipe->render_condition(pipe, st->render_condition,
+                             st->condition_mode);
+   }
+
    /* map the dst_surface so we can read from it */
    tex_xfer = pipe_get_transfer(pipe,
                                 dst_texture, 0, 0,
@@ -1556,6 +1567,11 @@ st_copy_texsubimage(struct gl_context *ctx,
             srcY1 = srcY0 + height;
          }
 
+         /* Disable conditional rendering. */
+         if (st->render_condition) {
+            pipe->render_condition(pipe, NULL, 0);
+         }
+
          util_blit_pixels_writemask(st->blit,
                                     strb->texture,
                                     strb->surface->u.tex.level,
@@ -1567,6 +1583,13 @@ st_copy_texsubimage(struct gl_context *ctx,
                                     destX + width, destY + height,
                                     0.0, PIPE_TEX_MIPFILTER_NEAREST,
                                     format_writemask);
+
+         /* Restore conditional rendering state. */
+         if (st->render_condition) {
+            pipe->render_condition(pipe, st->render_condition,
+                                   st->condition_mode);
+         }
+
          use_fallback = GL_FALSE;
       }
 
diff --git a/mesalib/src/mesa/state_tracker/st_context.h b/mesalib/src/mesa/state_tracker/st_context.h
index c6fc31801..ff207039d 100644
--- a/mesalib/src/mesa/state_tracker/st_context.h
+++ b/mesalib/src/mesa/state_tracker/st_context.h
@@ -200,6 +200,10 @@ struct st_context
       GLsizei stride;
    } user_attrib[PIPE_MAX_ATTRIBS];
    unsigned num_user_attribs;
+
+   /* Active render condition. */
+   struct pipe_query *render_condition;
+   unsigned condition_mode;
 };
 
 
diff --git a/mesalib/src/mesa/state_tracker/st_format.c b/mesalib/src/mesa/state_tracker/st_format.c
index de30b4fc6..dc8551dfe 100644
--- a/mesalib/src/mesa/state_tracker/st_format.c
+++ b/mesalib/src/mesa/state_tracker/st_format.c
@@ -595,6 +595,14 @@ struct format_mapping
       PIPE_FORMAT_A8B8G8R8_SRGB, \
       0
 
+#define DEFAULT_DEPTH_FORMATS \
+      PIPE_FORMAT_Z24X8_UNORM, \
+      PIPE_FORMAT_X8Z24_UNORM, \
+      PIPE_FORMAT_Z16_UNORM, \
+      PIPE_FORMAT_Z24_UNORM_S8_USCALED, \
+      PIPE_FORMAT_S8_USCALED_Z24_UNORM, \
+      0
+
 /**
  * This table maps OpenGL texture format enums to Gallium pipe_format enums.
  * Multiple GL enums might map to multiple pipe_formats.
@@ -604,7 +612,7 @@ static struct format_mapping format_map[] = {
    /* Basic RGB, RGBA formats */
    {
       { GL_RGB10, GL_RGB10_A2, 0 },
-      { PIPE_FORMAT_B10G10R10A2_UNORM, 0 }
+      { PIPE_FORMAT_B10G10R10A2_UNORM, DEFAULT_RGBA_FORMATS }
    },
    {
       { 4, GL_RGBA, GL_RGBA8, 0 },
@@ -612,7 +620,7 @@ static struct format_mapping format_map[] = {
    },
    {
       { GL_BGRA, 0 },
-      { PIPE_FORMAT_B8G8R8A8_UNORM, DEFAULT_RGB_FORMATS, 0 }
+      { PIPE_FORMAT_B8G8R8A8_UNORM, DEFAULT_RGBA_FORMATS }
    },
    {
       { 3, GL_RGB, GL_RGB8, 0 },
@@ -620,7 +628,7 @@ static struct format_mapping format_map[] = {
    },
    {
       { GL_RGB12, GL_RGB16, GL_RGBA12, GL_RGBA16, 0 },
-      { PIPE_FORMAT_R16G16B16A16_UNORM, DEFAULT_RGB_FORMATS, 0 }
+      { PIPE_FORMAT_R16G16B16A16_UNORM, DEFAULT_RGBA_FORMATS }
    },
    {
       { GL_RGBA4, GL_RGBA2, 0 },
@@ -628,7 +636,7 @@ static struct format_mapping format_map[] = {
    },
    {
       { GL_RGB5_A1, 0 },
-      { PIPE_FORMAT_B5G5R5A1_UNORM, DEFAULT_RGBA_FORMATS, 0 }
+      { PIPE_FORMAT_B5G5R5A1_UNORM, DEFAULT_RGBA_FORMATS }
    },
    {
       { GL_R3_G3_B2, 0 },
@@ -655,11 +663,11 @@ static struct format_mapping format_map[] = {
    /* basic Luminance formats */
    {
       { GL_LUMINANCE12, GL_LUMINANCE16, 0 },
-      { PIPE_FORMAT_L16_UNORM, PIPE_FORMAT_L8_UNORM, DEFAULT_RGBA_FORMATS, 0 }
+      { PIPE_FORMAT_L16_UNORM, PIPE_FORMAT_L8_UNORM, DEFAULT_RGB_FORMATS }
    },
    {
       { 1, GL_LUMINANCE, GL_LUMINANCE4, GL_LUMINANCE8, 0 },
-      { PIPE_FORMAT_L8_UNORM, DEFAULT_RGBA_FORMATS }
+      { PIPE_FORMAT_L8_UNORM, DEFAULT_RGB_FORMATS }
    },
 
    /* basic Luminance/Alpha formats */
@@ -667,7 +675,7 @@ static struct format_mapping format_map[] = {
       { GL_LUMINANCE12_ALPHA4, GL_LUMINANCE12_ALPHA12,
         GL_LUMINANCE16_ALPHA16, 0},
       { PIPE_FORMAT_L16A16_UNORM, PIPE_FORMAT_L8A8_UNORM,
-        PIPE_FORMAT_L8A8_UNORM, DEFAULT_RGBA_FORMATS }
+        DEFAULT_RGBA_FORMATS }
    },
    {
       { 2, GL_LUMINANCE_ALPHA, GL_LUMINANCE6_ALPHA2, GL_LUMINANCE8_ALPHA8, 0 },
@@ -675,7 +683,7 @@ static struct format_mapping format_map[] = {
    },
    {
       { GL_LUMINANCE4_ALPHA4, 0 },
-      { PIPE_FORMAT_L4A4_UNORM, PIPE_FORMAT_L4A4_UNORM,
+      { PIPE_FORMAT_L4A4_UNORM, PIPE_FORMAT_L8A8_UNORM,
         DEFAULT_RGBA_FORMATS }
    },
 
@@ -699,11 +707,11 @@ static struct format_mapping format_map[] = {
    /* compressed formats */ /* XXX PIPE_BIND_SAMPLER_VIEW only */
    {
       { GL_COMPRESSED_RGB, 0 },
-      { PIPE_FORMAT_DXT1_RGB, 0 }
+      { PIPE_FORMAT_DXT1_RGB, DEFAULT_RGB_FORMATS }
    },
    {
       { GL_COMPRESSED_RGBA, 0 },
-      { PIPE_FORMAT_DXT5_RGBA, 0 }
+      { PIPE_FORMAT_DXT5_RGBA, DEFAULT_RGBA_FORMATS }
    },
    {
       { GL_RGB_S3TC, GL_RGB4_S3TC, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 0 },
@@ -729,31 +737,27 @@ static struct format_mapping format_map[] = {
    },
    {
       { GL_COMPRESSED_RGBA_FXT1_3DFX, 0 },
-      { PIPE_FORMAT_RGB_FXT1, 0 }
+      { PIPE_FORMAT_RGBA_FXT1, 0 }
    },
 #endif
 
    /* Depth formats */
    {
       { GL_DEPTH_COMPONENT16, 0 },
-      { PIPE_FORMAT_Z16_UNORM, PIPE_FORMAT_Z24_UNORM_S8_USCALED,
-        PIPE_FORMAT_S8_USCALED_Z24_UNORM, PIPE_FORMAT_Z32_UNORM, 0 }
+      { PIPE_FORMAT_Z16_UNORM, DEFAULT_DEPTH_FORMATS }
    },
    {
       { GL_DEPTH_COMPONENT24, 0 },
       { PIPE_FORMAT_Z24X8_UNORM, PIPE_FORMAT_X8Z24_UNORM,
-        PIPE_FORMAT_Z24_UNORM_S8_USCALED, PIPE_FORMAT_S8_USCALED_Z24_UNORM,
-        PIPE_FORMAT_Z32_UNORM, 0 }
+        DEFAULT_DEPTH_FORMATS }
    },
    {
       { GL_DEPTH_COMPONENT32, 0 },
-      { PIPE_FORMAT_Z32_UNORM, 0 }
+      { PIPE_FORMAT_Z32_UNORM, DEFAULT_DEPTH_FORMATS }
    },
    {
       { GL_DEPTH_COMPONENT, 0 },
-      { PIPE_FORMAT_Z24X8_UNORM, PIPE_FORMAT_X8Z24_UNORM,
-        PIPE_FORMAT_Z32_UNORM, PIPE_FORMAT_Z16_UNORM,
-        PIPE_FORMAT_Z24_UNORM_S8_USCALED, PIPE_FORMAT_S8_USCALED_Z24_UNORM, 0 }
+      { DEFAULT_DEPTH_FORMATS }
    },
 
    /* stencil formats */
diff --git a/mesalib/src/mesa/state_tracker/st_gen_mipmap.c b/mesalib/src/mesa/state_tracker/st_gen_mipmap.c
index b34794f1b..b0911294a 100644
--- a/mesalib/src/mesa/state_tracker/st_gen_mipmap.c
+++ b/mesalib/src/mesa/state_tracker/st_gen_mipmap.c
@@ -91,9 +91,18 @@ st_render_mipmap(struct st_context *st,
       return FALSE;
    }
 
+   /* Disable conditional rendering. */
+   if (st->render_condition) {
+      pipe->render_condition(pipe, NULL, 0);
+   }
+
    util_gen_mipmap(st->gen_mipmap, psv, face, baseLevel, lastLevel,
                    PIPE_TEX_FILTER_LINEAR);
 
+   if (st->render_condition) {
+      pipe->render_condition(pipe, st->render_condition, st->condition_mode);
+   }
+
    return TRUE;
 }
 
diff --git a/mesalib/src/mesa/swrast/s_blit.c b/mesalib/src/mesa/swrast/s_blit.c
index 2dd11399f..3516a41bf 100644
--- a/mesalib/src/mesa/swrast/s_blit.c
+++ b/mesalib/src/mesa/swrast/s_blit.c
@@ -1,619 +1,616 @@
-/*
- * Mesa 3-D graphics library
- * Version:  6.5
- *
- * Copyright (C) 1999-2006  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"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-
-#include "main/glheader.h"
-#include "main/condrender.h"
-#include "main/image.h"
-#include "main/macros.h"
-#include "s_context.h"
-
-
-#define ABS(X)   ((X) < 0 ? -(X) : (X))
-
-
-/**
- * Generate a row resampler function for GL_NEAREST mode.
- */
-#define RESAMPLE(NAME, PIXELTYPE, SIZE)			\
-static void						\
-NAME(GLint srcWidth, GLint dstWidth,			\
-     const GLvoid *srcBuffer, GLvoid *dstBuffer,	\
-     GLboolean flip)					\
-{							\
-   const PIXELTYPE *src = (const PIXELTYPE *) srcBuffer;\
-   PIXELTYPE *dst = (PIXELTYPE *) dstBuffer;		\
-   GLint dstCol;					\
-							\
-   if (flip) {						\
-      for (dstCol = 0; dstCol < dstWidth; dstCol++) {	\
-         GLint srcCol = (dstCol * srcWidth) / dstWidth;	\
-         ASSERT(srcCol >= 0);				\
-         ASSERT(srcCol < srcWidth);			\
-         srcCol = srcWidth - 1 - srcCol; /* flip */	\
-         if (SIZE == 1) {				\
-            dst[dstCol] = src[srcCol];			\
-         }						\
-         else if (SIZE == 2) {				\
-            dst[dstCol*2+0] = src[srcCol*2+0];		\
-            dst[dstCol*2+1] = src[srcCol*2+1];		\
-         }						\
-         else if (SIZE == 4) {				\
-            dst[dstCol*4+0] = src[srcCol*4+0];		\
-            dst[dstCol*4+1] = src[srcCol*4+1];		\
-            dst[dstCol*4+2] = src[srcCol*4+2];		\
-            dst[dstCol*4+3] = src[srcCol*4+3];		\
-         }						\
-      }							\
-   }							\
-   else {						\
-      for (dstCol = 0; dstCol < dstWidth; dstCol++) {	\
-         GLint srcCol = (dstCol * srcWidth) / dstWidth;	\
-         ASSERT(srcCol >= 0);				\
-         ASSERT(srcCol < srcWidth);			\
-         if (SIZE == 1) {				\
-            dst[dstCol] = src[srcCol];			\
-         }						\
-         else if (SIZE == 2) {				\
-            dst[dstCol*2+0] = src[srcCol*2+0];		\
-            dst[dstCol*2+1] = src[srcCol*2+1];		\
-         }						\
-         else if (SIZE == 4) {				\
-            dst[dstCol*4+0] = src[srcCol*4+0];		\
-            dst[dstCol*4+1] = src[srcCol*4+1];		\
-            dst[dstCol*4+2] = src[srcCol*4+2];		\
-            dst[dstCol*4+3] = src[srcCol*4+3];		\
-         }						\
-      }							\
-   }							\
-}
-
-/**
- * Resamplers for 1, 2, 4, 8 and 16-byte pixels.
- */
-RESAMPLE(resample_row_1, GLubyte, 1)
-RESAMPLE(resample_row_2, GLushort, 1)
-RESAMPLE(resample_row_4, GLuint, 1)
-RESAMPLE(resample_row_8, GLuint, 2)
-RESAMPLE(resample_row_16, GLuint, 4)
-
-
-/**
- * Blit color, depth or stencil with GL_NEAREST filtering.
- */
-static void
-blit_nearest(struct gl_context *ctx,
-             GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
-             GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
-             GLbitfield buffer)
-{
-   struct gl_renderbuffer *readRb, *drawRb;
-
-   const GLint srcWidth = ABS(srcX1 - srcX0);
-   const GLint dstWidth = ABS(dstX1 - dstX0);
-   const GLint srcHeight = ABS(srcY1 - srcY0);
-   const GLint dstHeight = ABS(dstY1 - dstY0);
-
-   const GLint srcXpos = MIN2(srcX0, srcX1);
-   const GLint srcYpos = MIN2(srcY0, srcY1);
-   const GLint dstXpos = MIN2(dstX0, dstX1);
-   const GLint dstYpos = MIN2(dstY0, dstY1);
-
-   const GLboolean invertX = (srcX1 < srcX0) ^ (dstX1 < dstX0);
-   const GLboolean invertY = (srcY1 < srcY0) ^ (dstY1 < dstY0);
-
-   GLint dstRow;
-
-   GLint comps, pixelSize;
-   GLvoid *srcBuffer, *dstBuffer;
-   GLint prevY = -1;
-
-   typedef void (*resample_func)(GLint srcWidth, GLint dstWidth,
-                                 const GLvoid *srcBuffer, GLvoid *dstBuffer,
-                                 GLboolean flip);
-   resample_func resampleRow;
-
-   switch (buffer) {
-   case GL_COLOR_BUFFER_BIT:
-      readRb = ctx->ReadBuffer->_ColorReadBuffer;
-      drawRb = ctx->DrawBuffer->_ColorDrawBuffers[0];
-      comps = 4;
-      break;
-   case GL_DEPTH_BUFFER_BIT:
-      readRb = ctx->ReadBuffer->_DepthBuffer;
-      drawRb = ctx->DrawBuffer->_DepthBuffer;
-      comps = 1;
-      break;
-   case GL_STENCIL_BUFFER_BIT:
-      readRb = ctx->ReadBuffer->_StencilBuffer;
-      drawRb = ctx->DrawBuffer->_StencilBuffer;
-      comps = 1;
-      break;
-   default:
-      _mesa_problem(ctx, "unexpected buffer in blit_nearest()");
-      return;
-   }
-
-   switch (readRb->DataType) {
-   case GL_UNSIGNED_BYTE:
-      pixelSize = comps * sizeof(GLubyte);
-      break;
-   case GL_UNSIGNED_SHORT:
-      pixelSize = comps * sizeof(GLushort);
-      break;
-   case GL_UNSIGNED_INT:
-      pixelSize = comps * sizeof(GLuint);
-      break;
-   case GL_FLOAT:
-      pixelSize = comps * sizeof(GLfloat);
-      break;
-   default:
-      _mesa_problem(ctx, "unexpected buffer type (0x%x) in blit_nearest",
-                    readRb->DataType);
-      return;
-   }
-
-   /* choose row resampler */
-   switch (pixelSize) {
-   case 1:
-      resampleRow = resample_row_1;
-      break;
-   case 2:
-      resampleRow = resample_row_2;
-      break;
-   case 4:
-      resampleRow = resample_row_4;
-      break;
-   case 8:
-      resampleRow = resample_row_8;
-      break;
-   case 16:
-      resampleRow = resample_row_16;
-      break;
-   default:
-      _mesa_problem(ctx, "unexpected pixel size (%d) in blit_nearest",
-                    pixelSize);
-      return;
-   }
-
-   /* allocate the src/dst row buffers */
-   srcBuffer = malloc(pixelSize * srcWidth);
-   if (!srcBuffer) {
-      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT");
-      return;
-   }
-   dstBuffer = malloc(pixelSize * dstWidth);
-   if (!dstBuffer) {
-      free(srcBuffer);
-      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT");
-      return;
-   }
-
-   for (dstRow = 0; dstRow < dstHeight; dstRow++) {
-      const GLint dstY = dstYpos + dstRow;
-      GLint srcRow = (dstRow * srcHeight) / dstHeight;
-      GLint srcY;
-
-      ASSERT(srcRow >= 0);
-      ASSERT(srcRow < srcHeight);
-
-      if (invertY) {
-         srcRow = srcHeight - 1 - srcRow;
-      }
-
-      srcY = srcYpos + srcRow;
-
-      /* get pixel row from source and resample to match dest width */
-      if (prevY != srcY) {
-         readRb->GetRow(ctx, readRb, srcWidth, srcXpos, srcY, srcBuffer);
-         (*resampleRow)(srcWidth, dstWidth, srcBuffer, dstBuffer, invertX);
-         prevY = srcY;
-      }
-
-      /* store pixel row in destination */
-      drawRb->PutRow(ctx, drawRb, dstWidth, dstXpos, dstY, dstBuffer, NULL);
-   }
-
-   free(srcBuffer);
-   free(dstBuffer);
-}
-
-
-
-#define LERP(T, A, B)  ( (A) + (T) * ((B) - (A)) )
-
-static INLINE GLfloat
-lerp_2d(GLfloat a, GLfloat b,
-        GLfloat v00, GLfloat v10, GLfloat v01, GLfloat v11)
-{
-   const GLfloat temp0 = LERP(a, v00, v10);
-   const GLfloat temp1 = LERP(a, v01, v11);
-   return LERP(b, temp0, temp1);
-}
-
-
-/**
- * Bilinear interpolation of two source rows.
- * GLubyte pixels.
- */
-static void
-resample_linear_row_ub(GLint srcWidth, GLint dstWidth,
-                       const GLvoid *srcBuffer0, const GLvoid *srcBuffer1,
-                       GLvoid *dstBuffer, GLboolean flip, GLfloat rowWeight)
-{
-   const GLubyte (*srcColor0)[4] = (const GLubyte (*)[4]) srcBuffer0;
-   const GLubyte (*srcColor1)[4] = (const GLubyte (*)[4]) srcBuffer1;
-   GLubyte (*dstColor)[4] = (GLubyte (*)[4]) dstBuffer;
-   const GLfloat dstWidthF = (GLfloat) dstWidth;
-   GLint dstCol;
-
-   for (dstCol = 0; dstCol < dstWidth; dstCol++) {
-      const GLfloat srcCol = (dstCol * srcWidth) / dstWidthF;
-      GLint srcCol0 = IFLOOR(srcCol);
-      GLint srcCol1 = srcCol0 + 1;
-      GLfloat colWeight = srcCol - srcCol0; /* fractional part of srcCol */
-      GLfloat red, green, blue, alpha;
-
-      ASSERT(srcCol0 >= 0);
-      ASSERT(srcCol0 < srcWidth);
-      ASSERT(srcCol1 <= srcWidth);
-
-      if (srcCol1 == srcWidth) {
-         /* last column fudge */
-         srcCol1--;
-         colWeight = 0.0;
-      }
-
-      if (flip) {
-         srcCol0 = srcWidth - 1 - srcCol0;
-         srcCol1 = srcWidth - 1 - srcCol1;
-      }
-
-      red = lerp_2d(colWeight, rowWeight,
-                    srcColor0[srcCol0][RCOMP], srcColor0[srcCol1][RCOMP],
-                    srcColor1[srcCol0][RCOMP], srcColor1[srcCol1][RCOMP]);
-      green = lerp_2d(colWeight, rowWeight,
-                    srcColor0[srcCol0][GCOMP], srcColor0[srcCol1][GCOMP],
-                    srcColor1[srcCol0][GCOMP], srcColor1[srcCol1][GCOMP]);
-      blue = lerp_2d(colWeight, rowWeight,
-                    srcColor0[srcCol0][BCOMP], srcColor0[srcCol1][BCOMP],
-                    srcColor1[srcCol0][BCOMP], srcColor1[srcCol1][BCOMP]);
-      alpha = lerp_2d(colWeight, rowWeight,
-                    srcColor0[srcCol0][ACOMP], srcColor0[srcCol1][ACOMP],
-                    srcColor1[srcCol0][ACOMP], srcColor1[srcCol1][ACOMP]);
-      
-      dstColor[dstCol][RCOMP] = IFLOOR(red);
-      dstColor[dstCol][GCOMP] = IFLOOR(green);
-      dstColor[dstCol][BCOMP] = IFLOOR(blue);
-      dstColor[dstCol][ACOMP] = IFLOOR(alpha);
-   }
-}
-
-
-
-/**
- * Bilinear filtered blit (color only).
- */
-static void
-blit_linear(struct gl_context *ctx,
-            GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
-            GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1)
-{
-   struct gl_renderbuffer *readRb = ctx->ReadBuffer->_ColorReadBuffer;
-   struct gl_renderbuffer *drawRb = ctx->DrawBuffer->_ColorDrawBuffers[0];
-
-   const GLint srcWidth = ABS(srcX1 - srcX0);
-   const GLint dstWidth = ABS(dstX1 - dstX0);
-   const GLint srcHeight = ABS(srcY1 - srcY0);
-   const GLint dstHeight = ABS(dstY1 - dstY0);
-   const GLfloat dstHeightF = (GLfloat) dstHeight;
-
-   const GLint srcXpos = MIN2(srcX0, srcX1);
-   const GLint srcYpos = MIN2(srcY0, srcY1);
-   const GLint dstXpos = MIN2(dstX0, dstX1);
-   const GLint dstYpos = MIN2(dstY0, dstY1);
-
-   const GLboolean invertX = (srcX1 < srcX0) ^ (dstX1 < dstX0);
-   const GLboolean invertY = (srcY1 < srcY0) ^ (dstY1 < dstY0);
-
-   GLint dstRow;
-
-   GLint pixelSize;
-   GLvoid *srcBuffer0, *srcBuffer1;
-   GLint srcBufferY0 = -1, srcBufferY1 = -1;
-   GLvoid *dstBuffer;
-
-   switch (readRb->DataType) {
-   case GL_UNSIGNED_BYTE:
-      pixelSize = 4 * sizeof(GLubyte);
-      break;
-   case GL_UNSIGNED_SHORT:
-      pixelSize = 4 * sizeof(GLushort);
-      break;
-   case GL_UNSIGNED_INT:
-      pixelSize = 4 * sizeof(GLuint);
-      break;
-   case GL_FLOAT:
-      pixelSize = 4 * sizeof(GLfloat);
-      break;
-   default:
-      _mesa_problem(ctx, "unexpected buffer type (0x%x) in blit_nearest",
-                    readRb->DataType);
-      return;
-   }
-
-   /* Allocate the src/dst row buffers.
-    * Keep two adjacent src rows around for bilinear sampling.
-    */
-   srcBuffer0 = malloc(pixelSize * srcWidth);
-   if (!srcBuffer0) {
-      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT");
-      return;
-   }
-   srcBuffer1 = malloc(pixelSize * srcWidth);
-   if (!srcBuffer1) {
-      free(srcBuffer0);
-      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT");
-      return;
-   }
-   dstBuffer = malloc(pixelSize * dstWidth);
-   if (!dstBuffer) {
-      free(srcBuffer0);
-      free(srcBuffer1);
-      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT");
-      return;
-   }
-
-   for (dstRow = 0; dstRow < dstHeight; dstRow++) {
-      const GLint dstY = dstYpos + dstRow;
-      const GLfloat srcRow = (dstRow * srcHeight) / dstHeightF;
-      GLint srcRow0 = IFLOOR(srcRow);
-      GLint srcRow1 = srcRow0 + 1;
-      GLfloat rowWeight = srcRow - srcRow0; /* fractional part of srcRow */
-
-      ASSERT(srcRow >= 0);
-      ASSERT(srcRow < srcHeight);
-
-      if (srcRow1 == srcHeight) {
-         /* last row fudge */
-         srcRow1 = srcRow0;
-         rowWeight = 0.0;
-      }
-
-      if (invertY) {
-         srcRow0 = srcHeight - 1 - srcRow0;
-         srcRow1 = srcHeight - 1 - srcRow1;
-      }
-
-      srcY0 = srcYpos + srcRow0;
-      srcY1 = srcYpos + srcRow1;
-
-      /* get the two source rows */
-      if (srcY0 == srcBufferY0 && srcY1 == srcBufferY1) {
-         /* use same source row buffers again */
-      }
-      else if (srcY0 == srcBufferY1) {
-         /* move buffer1 into buffer0 by swapping pointers */
-         GLvoid *tmp = srcBuffer0;
-         srcBuffer0 = srcBuffer1;
-         srcBuffer1 = tmp;
-         /* get y1 row */
-         readRb->GetRow(ctx, readRb, srcWidth, srcXpos, srcY1, srcBuffer1);
-         srcBufferY0 = srcY0;
-         srcBufferY1 = srcY1;
-      }
-      else {
-         /* get both new rows */
-         readRb->GetRow(ctx, readRb, srcWidth, srcXpos, srcY0, srcBuffer0);
-         readRb->GetRow(ctx, readRb, srcWidth, srcXpos, srcY1, srcBuffer1);
-         srcBufferY0 = srcY0;
-         srcBufferY1 = srcY1;
-      }
-
-      if (readRb->DataType == GL_UNSIGNED_BYTE) {
-         resample_linear_row_ub(srcWidth, dstWidth, srcBuffer0, srcBuffer1,
-                                dstBuffer, invertX, rowWeight);
-      }
-      else {
-         _mesa_problem(ctx, "Unsupported color channel type in sw blit");
-         break;
-      }
-
-      /* store pixel row in destination */
-      drawRb->PutRow(ctx, drawRb, dstWidth, dstXpos, dstY, dstBuffer, NULL);
-   }
-
-   free(srcBuffer0);
-   free(srcBuffer1);
-   free(dstBuffer);
-}
-
-
-/**
- * Simple case:  Blit color, depth or stencil with no scaling or flipping.
- * XXX we could easily support vertical flipping here.
- */
-static void
-simple_blit(struct gl_context *ctx,
-            GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
-            GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
-            GLbitfield buffer)
-{
-   struct gl_renderbuffer *readRb, *drawRb;
-   const GLint width = srcX1 - srcX0;
-   const GLint height = srcY1 - srcY0;
-   GLint row, srcY, dstY, yStep;
-   GLint comps, bytesPerRow;
-   void *rowBuffer;
-
-   /* only one buffer */
-   ASSERT(_mesa_bitcount(buffer) == 1);
-   /* no flipping checks */
-   ASSERT(srcX0 < srcX1);
-   ASSERT(srcY0 < srcY1);
-   ASSERT(dstX0 < dstX1);
-   ASSERT(dstY0 < dstY1);
-   /* size checks */
-   ASSERT(srcX1 - srcX0 == dstX1 - dstX0);
-   ASSERT(srcY1 - srcY0 == dstY1 - dstY0);
-
-   /* determine if copy should be bottom-to-top or top-to-bottom */
-   if (srcY0 > dstY0) {
-      /* src above dst: copy bottom-to-top */
-      yStep = 1;
-      srcY = srcY0;
-      dstY = dstY0;
-   }
-   else {
-      /* src below dst: copy top-to-bottom */
-      yStep = -1;
-      srcY = srcY1 - 1;
-      dstY = dstY1 - 1;
-   }
-
-   switch (buffer) {
-   case GL_COLOR_BUFFER_BIT:
-      readRb = ctx->ReadBuffer->_ColorReadBuffer;
-      drawRb = ctx->DrawBuffer->_ColorDrawBuffers[0];
-      comps = 4;
-      break;
-   case GL_DEPTH_BUFFER_BIT:
-      readRb = ctx->ReadBuffer->_DepthBuffer;
-      drawRb = ctx->DrawBuffer->_DepthBuffer;
-      comps = 1;
-      break;
-   case GL_STENCIL_BUFFER_BIT:
-      readRb = ctx->ReadBuffer->_StencilBuffer;
-      drawRb = ctx->DrawBuffer->_StencilBuffer;
-      comps = 1;
-      break;
-   default:
-      _mesa_problem(ctx, "unexpected buffer in simple_blit()");
-      return;
-   }
-
-   ASSERT(readRb->DataType == drawRb->DataType);
-
-   /* compute bytes per row */
-   switch (readRb->DataType) {
-   case GL_UNSIGNED_BYTE:
-      bytesPerRow = comps * width * sizeof(GLubyte);
-      break;
-   case GL_UNSIGNED_SHORT:
-      bytesPerRow = comps * width * sizeof(GLushort);
-      break;
-   case GL_UNSIGNED_INT:
-      bytesPerRow = comps * width * sizeof(GLuint);
-      break;
-   case GL_FLOAT:
-      bytesPerRow = comps * width * sizeof(GLfloat);
-      break;
-   default:
-      _mesa_problem(ctx, "unexpected buffer type in simple_blit");
-      return;
-   }
-
-   /* allocate the row buffer */
-   rowBuffer = malloc(bytesPerRow);
-   if (!rowBuffer) {
-      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT");
-      return;
-   }
-
-   for (row = 0; row < height; row++) {
-      readRb->GetRow(ctx, readRb, width, srcX0, srcY, rowBuffer);
-      drawRb->PutRow(ctx, drawRb, width, dstX0, dstY, rowBuffer, NULL);
-      srcY += yStep;
-      dstY += yStep;
-   }
-
-   free(rowBuffer);
-}
-
-
-/**
- * Software fallback for glBlitFramebufferEXT().
- */
-void
-_swrast_BlitFramebuffer(struct gl_context *ctx,
-                        GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
-                        GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
-                        GLbitfield mask, GLenum filter)
-{
-   static const GLbitfield buffers[3] = {
-      GL_COLOR_BUFFER_BIT,
-      GL_DEPTH_BUFFER_BIT,
-      GL_STENCIL_BUFFER_BIT
-   };
-   GLint i;
-
-   if (!_mesa_check_conditional_render(ctx))
-      return; /* don't clear */
-
-   if (!ctx->DrawBuffer->_NumColorDrawBuffers)
-      return;
-
-   if (!_mesa_clip_blit(ctx, &srcX0, &srcY0, &srcX1, &srcY1,
-                        &dstX0, &dstY0, &dstX1, &dstY1)) {
-      return;
-   }
-
-   swrast_render_start(ctx);
-
-   if (srcX1 - srcX0 == dstX1 - dstX0 &&
-       srcY1 - srcY0 == dstY1 - dstY0 &&
-       srcX0 < srcX1 &&
-       srcY0 < srcY1 &&
-       dstX0 < dstX1 &&
-       dstY0 < dstY1) {
-      /* no stretching or flipping.
-       * filter doesn't matter.
-       */
-      for (i = 0; i < 3; i++) {
-         if (mask & buffers[i]) {
-            simple_blit(ctx, srcX0, srcY0, srcX1, srcY1,
-                        dstX0, dstY0, dstX1, dstY1, buffers[i]);
-         }
-      }
-   }
-   else {
-      if (filter == GL_NEAREST) {
-         for (i = 0; i < 3; i++) {
-            if (mask & buffers[i]) {
-               blit_nearest(ctx,  srcX0, srcY0, srcX1, srcY1,
-                            dstX0, dstY0, dstX1, dstY1, buffers[i]);
-            }
-         }
-      }
-      else {
-         ASSERT(filter == GL_LINEAR);
-         if (mask & GL_COLOR_BUFFER_BIT) {  /* depth/stencil not allowed */
-            blit_linear(ctx,  srcX0, srcY0, srcX1, srcY1,
-                        dstX0, dstY0, dstX1, dstY1);
-         }
-      }
-   }
-
-   swrast_render_finish(ctx);
-}
+/*
+ * Mesa 3-D graphics library
+ * Version:  6.5
+ *
+ * Copyright (C) 1999-2006  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"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+#include "main/glheader.h"
+#include "main/condrender.h"
+#include "main/image.h"
+#include "main/macros.h"
+#include "s_context.h"
+
+
+#define ABS(X)   ((X) < 0 ? -(X) : (X))
+
+
+/**
+ * Generate a row resampler function for GL_NEAREST mode.
+ */
+#define RESAMPLE(NAME, PIXELTYPE, SIZE)			\
+static void						\
+NAME(GLint srcWidth, GLint dstWidth,			\
+     const GLvoid *srcBuffer, GLvoid *dstBuffer,	\
+     GLboolean flip)					\
+{							\
+   const PIXELTYPE *src = (const PIXELTYPE *) srcBuffer;\
+   PIXELTYPE *dst = (PIXELTYPE *) dstBuffer;		\
+   GLint dstCol;					\
+							\
+   if (flip) {						\
+      for (dstCol = 0; dstCol < dstWidth; dstCol++) {	\
+         GLint srcCol = (dstCol * srcWidth) / dstWidth;	\
+         ASSERT(srcCol >= 0);				\
+         ASSERT(srcCol < srcWidth);			\
+         srcCol = srcWidth - 1 - srcCol; /* flip */	\
+         if (SIZE == 1) {				\
+            dst[dstCol] = src[srcCol];			\
+         }						\
+         else if (SIZE == 2) {				\
+            dst[dstCol*2+0] = src[srcCol*2+0];		\
+            dst[dstCol*2+1] = src[srcCol*2+1];		\
+         }						\
+         else if (SIZE == 4) {				\
+            dst[dstCol*4+0] = src[srcCol*4+0];		\
+            dst[dstCol*4+1] = src[srcCol*4+1];		\
+            dst[dstCol*4+2] = src[srcCol*4+2];		\
+            dst[dstCol*4+3] = src[srcCol*4+3];		\
+         }						\
+      }							\
+   }							\
+   else {						\
+      for (dstCol = 0; dstCol < dstWidth; dstCol++) {	\
+         GLint srcCol = (dstCol * srcWidth) / dstWidth;	\
+         ASSERT(srcCol >= 0);				\
+         ASSERT(srcCol < srcWidth);			\
+         if (SIZE == 1) {				\
+            dst[dstCol] = src[srcCol];			\
+         }						\
+         else if (SIZE == 2) {				\
+            dst[dstCol*2+0] = src[srcCol*2+0];		\
+            dst[dstCol*2+1] = src[srcCol*2+1];		\
+         }						\
+         else if (SIZE == 4) {				\
+            dst[dstCol*4+0] = src[srcCol*4+0];		\
+            dst[dstCol*4+1] = src[srcCol*4+1];		\
+            dst[dstCol*4+2] = src[srcCol*4+2];		\
+            dst[dstCol*4+3] = src[srcCol*4+3];		\
+         }						\
+      }							\
+   }							\
+}
+
+/**
+ * Resamplers for 1, 2, 4, 8 and 16-byte pixels.
+ */
+RESAMPLE(resample_row_1, GLubyte, 1)
+RESAMPLE(resample_row_2, GLushort, 1)
+RESAMPLE(resample_row_4, GLuint, 1)
+RESAMPLE(resample_row_8, GLuint, 2)
+RESAMPLE(resample_row_16, GLuint, 4)
+
+
+/**
+ * Blit color, depth or stencil with GL_NEAREST filtering.
+ */
+static void
+blit_nearest(struct gl_context *ctx,
+             GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
+             GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
+             GLbitfield buffer)
+{
+   struct gl_renderbuffer *readRb, *drawRb;
+
+   const GLint srcWidth = ABS(srcX1 - srcX0);
+   const GLint dstWidth = ABS(dstX1 - dstX0);
+   const GLint srcHeight = ABS(srcY1 - srcY0);
+   const GLint dstHeight = ABS(dstY1 - dstY0);
+
+   const GLint srcXpos = MIN2(srcX0, srcX1);
+   const GLint srcYpos = MIN2(srcY0, srcY1);
+   const GLint dstXpos = MIN2(dstX0, dstX1);
+   const GLint dstYpos = MIN2(dstY0, dstY1);
+
+   const GLboolean invertX = (srcX1 < srcX0) ^ (dstX1 < dstX0);
+   const GLboolean invertY = (srcY1 < srcY0) ^ (dstY1 < dstY0);
+
+   GLint dstRow;
+
+   GLint comps, pixelSize;
+   GLvoid *srcBuffer, *dstBuffer;
+   GLint prevY = -1;
+
+   typedef void (*resample_func)(GLint srcWidth, GLint dstWidth,
+                                 const GLvoid *srcBuffer, GLvoid *dstBuffer,
+                                 GLboolean flip);
+   resample_func resampleRow;
+
+   switch (buffer) {
+   case GL_COLOR_BUFFER_BIT:
+      readRb = ctx->ReadBuffer->_ColorReadBuffer;
+      drawRb = ctx->DrawBuffer->_ColorDrawBuffers[0];
+      comps = 4;
+      break;
+   case GL_DEPTH_BUFFER_BIT:
+      readRb = ctx->ReadBuffer->_DepthBuffer;
+      drawRb = ctx->DrawBuffer->_DepthBuffer;
+      comps = 1;
+      break;
+   case GL_STENCIL_BUFFER_BIT:
+      readRb = ctx->ReadBuffer->_StencilBuffer;
+      drawRb = ctx->DrawBuffer->_StencilBuffer;
+      comps = 1;
+      break;
+   default:
+      _mesa_problem(ctx, "unexpected buffer in blit_nearest()");
+      return;
+   }
+
+   switch (readRb->DataType) {
+   case GL_UNSIGNED_BYTE:
+      pixelSize = comps * sizeof(GLubyte);
+      break;
+   case GL_UNSIGNED_SHORT:
+      pixelSize = comps * sizeof(GLushort);
+      break;
+   case GL_UNSIGNED_INT:
+      pixelSize = comps * sizeof(GLuint);
+      break;
+   case GL_FLOAT:
+      pixelSize = comps * sizeof(GLfloat);
+      break;
+   default:
+      _mesa_problem(ctx, "unexpected buffer type (0x%x) in blit_nearest",
+                    readRb->DataType);
+      return;
+   }
+
+   /* choose row resampler */
+   switch (pixelSize) {
+   case 1:
+      resampleRow = resample_row_1;
+      break;
+   case 2:
+      resampleRow = resample_row_2;
+      break;
+   case 4:
+      resampleRow = resample_row_4;
+      break;
+   case 8:
+      resampleRow = resample_row_8;
+      break;
+   case 16:
+      resampleRow = resample_row_16;
+      break;
+   default:
+      _mesa_problem(ctx, "unexpected pixel size (%d) in blit_nearest",
+                    pixelSize);
+      return;
+   }
+
+   /* allocate the src/dst row buffers */
+   srcBuffer = malloc(pixelSize * srcWidth);
+   if (!srcBuffer) {
+      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT");
+      return;
+   }
+   dstBuffer = malloc(pixelSize * dstWidth);
+   if (!dstBuffer) {
+      free(srcBuffer);
+      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT");
+      return;
+   }
+
+   for (dstRow = 0; dstRow < dstHeight; dstRow++) {
+      const GLint dstY = dstYpos + dstRow;
+      GLint srcRow = (dstRow * srcHeight) / dstHeight;
+      GLint srcY;
+
+      ASSERT(srcRow >= 0);
+      ASSERT(srcRow < srcHeight);
+
+      if (invertY) {
+         srcRow = srcHeight - 1 - srcRow;
+      }
+
+      srcY = srcYpos + srcRow;
+
+      /* get pixel row from source and resample to match dest width */
+      if (prevY != srcY) {
+         readRb->GetRow(ctx, readRb, srcWidth, srcXpos, srcY, srcBuffer);
+         (*resampleRow)(srcWidth, dstWidth, srcBuffer, dstBuffer, invertX);
+         prevY = srcY;
+      }
+
+      /* store pixel row in destination */
+      drawRb->PutRow(ctx, drawRb, dstWidth, dstXpos, dstY, dstBuffer, NULL);
+   }
+
+   free(srcBuffer);
+   free(dstBuffer);
+}
+
+
+
+#define LERP(T, A, B)  ( (A) + (T) * ((B) - (A)) )
+
+static INLINE GLfloat
+lerp_2d(GLfloat a, GLfloat b,
+        GLfloat v00, GLfloat v10, GLfloat v01, GLfloat v11)
+{
+   const GLfloat temp0 = LERP(a, v00, v10);
+   const GLfloat temp1 = LERP(a, v01, v11);
+   return LERP(b, temp0, temp1);
+}
+
+
+/**
+ * Bilinear interpolation of two source rows.
+ * GLubyte pixels.
+ */
+static void
+resample_linear_row_ub(GLint srcWidth, GLint dstWidth,
+                       const GLvoid *srcBuffer0, const GLvoid *srcBuffer1,
+                       GLvoid *dstBuffer, GLboolean flip, GLfloat rowWeight)
+{
+   const GLubyte (*srcColor0)[4] = (const GLubyte (*)[4]) srcBuffer0;
+   const GLubyte (*srcColor1)[4] = (const GLubyte (*)[4]) srcBuffer1;
+   GLubyte (*dstColor)[4] = (GLubyte (*)[4]) dstBuffer;
+   const GLfloat dstWidthF = (GLfloat) dstWidth;
+   GLint dstCol;
+
+   for (dstCol = 0; dstCol < dstWidth; dstCol++) {
+      const GLfloat srcCol = (dstCol * srcWidth) / dstWidthF;
+      GLint srcCol0 = IFLOOR(srcCol);
+      GLint srcCol1 = srcCol0 + 1;
+      GLfloat colWeight = srcCol - srcCol0; /* fractional part of srcCol */
+      GLfloat red, green, blue, alpha;
+
+      ASSERT(srcCol0 >= 0);
+      ASSERT(srcCol0 < srcWidth);
+      ASSERT(srcCol1 <= srcWidth);
+
+      if (srcCol1 == srcWidth) {
+         /* last column fudge */
+         srcCol1--;
+         colWeight = 0.0;
+      }
+
+      if (flip) {
+         srcCol0 = srcWidth - 1 - srcCol0;
+         srcCol1 = srcWidth - 1 - srcCol1;
+      }
+
+      red = lerp_2d(colWeight, rowWeight,
+                    srcColor0[srcCol0][RCOMP], srcColor0[srcCol1][RCOMP],
+                    srcColor1[srcCol0][RCOMP], srcColor1[srcCol1][RCOMP]);
+      green = lerp_2d(colWeight, rowWeight,
+                    srcColor0[srcCol0][GCOMP], srcColor0[srcCol1][GCOMP],
+                    srcColor1[srcCol0][GCOMP], srcColor1[srcCol1][GCOMP]);
+      blue = lerp_2d(colWeight, rowWeight,
+                    srcColor0[srcCol0][BCOMP], srcColor0[srcCol1][BCOMP],
+                    srcColor1[srcCol0][BCOMP], srcColor1[srcCol1][BCOMP]);
+      alpha = lerp_2d(colWeight, rowWeight,
+                    srcColor0[srcCol0][ACOMP], srcColor0[srcCol1][ACOMP],
+                    srcColor1[srcCol0][ACOMP], srcColor1[srcCol1][ACOMP]);
+      
+      dstColor[dstCol][RCOMP] = IFLOOR(red);
+      dstColor[dstCol][GCOMP] = IFLOOR(green);
+      dstColor[dstCol][BCOMP] = IFLOOR(blue);
+      dstColor[dstCol][ACOMP] = IFLOOR(alpha);
+   }
+}
+
+
+
+/**
+ * Bilinear filtered blit (color only).
+ */
+static void
+blit_linear(struct gl_context *ctx,
+            GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
+            GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1)
+{
+   struct gl_renderbuffer *readRb = ctx->ReadBuffer->_ColorReadBuffer;
+   struct gl_renderbuffer *drawRb = ctx->DrawBuffer->_ColorDrawBuffers[0];
+
+   const GLint srcWidth = ABS(srcX1 - srcX0);
+   const GLint dstWidth = ABS(dstX1 - dstX0);
+   const GLint srcHeight = ABS(srcY1 - srcY0);
+   const GLint dstHeight = ABS(dstY1 - dstY0);
+   const GLfloat dstHeightF = (GLfloat) dstHeight;
+
+   const GLint srcXpos = MIN2(srcX0, srcX1);
+   const GLint srcYpos = MIN2(srcY0, srcY1);
+   const GLint dstXpos = MIN2(dstX0, dstX1);
+   const GLint dstYpos = MIN2(dstY0, dstY1);
+
+   const GLboolean invertX = (srcX1 < srcX0) ^ (dstX1 < dstX0);
+   const GLboolean invertY = (srcY1 < srcY0) ^ (dstY1 < dstY0);
+
+   GLint dstRow;
+
+   GLint pixelSize;
+   GLvoid *srcBuffer0, *srcBuffer1;
+   GLint srcBufferY0 = -1, srcBufferY1 = -1;
+   GLvoid *dstBuffer;
+
+   switch (readRb->DataType) {
+   case GL_UNSIGNED_BYTE:
+      pixelSize = 4 * sizeof(GLubyte);
+      break;
+   case GL_UNSIGNED_SHORT:
+      pixelSize = 4 * sizeof(GLushort);
+      break;
+   case GL_UNSIGNED_INT:
+      pixelSize = 4 * sizeof(GLuint);
+      break;
+   case GL_FLOAT:
+      pixelSize = 4 * sizeof(GLfloat);
+      break;
+   default:
+      _mesa_problem(ctx, "unexpected buffer type (0x%x) in blit_nearest",
+                    readRb->DataType);
+      return;
+   }
+
+   /* Allocate the src/dst row buffers.
+    * Keep two adjacent src rows around for bilinear sampling.
+    */
+   srcBuffer0 = malloc(pixelSize * srcWidth);
+   if (!srcBuffer0) {
+      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT");
+      return;
+   }
+   srcBuffer1 = malloc(pixelSize * srcWidth);
+   if (!srcBuffer1) {
+      free(srcBuffer0);
+      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT");
+      return;
+   }
+   dstBuffer = malloc(pixelSize * dstWidth);
+   if (!dstBuffer) {
+      free(srcBuffer0);
+      free(srcBuffer1);
+      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT");
+      return;
+   }
+
+   for (dstRow = 0; dstRow < dstHeight; dstRow++) {
+      const GLint dstY = dstYpos + dstRow;
+      const GLfloat srcRow = (dstRow * srcHeight) / dstHeightF;
+      GLint srcRow0 = IFLOOR(srcRow);
+      GLint srcRow1 = srcRow0 + 1;
+      GLfloat rowWeight = srcRow - srcRow0; /* fractional part of srcRow */
+
+      ASSERT(srcRow >= 0);
+      ASSERT(srcRow < srcHeight);
+
+      if (srcRow1 == srcHeight) {
+         /* last row fudge */
+         srcRow1 = srcRow0;
+         rowWeight = 0.0;
+      }
+
+      if (invertY) {
+         srcRow0 = srcHeight - 1 - srcRow0;
+         srcRow1 = srcHeight - 1 - srcRow1;
+      }
+
+      srcY0 = srcYpos + srcRow0;
+      srcY1 = srcYpos + srcRow1;
+
+      /* get the two source rows */
+      if (srcY0 == srcBufferY0 && srcY1 == srcBufferY1) {
+         /* use same source row buffers again */
+      }
+      else if (srcY0 == srcBufferY1) {
+         /* move buffer1 into buffer0 by swapping pointers */
+         GLvoid *tmp = srcBuffer0;
+         srcBuffer0 = srcBuffer1;
+         srcBuffer1 = tmp;
+         /* get y1 row */
+         readRb->GetRow(ctx, readRb, srcWidth, srcXpos, srcY1, srcBuffer1);
+         srcBufferY0 = srcY0;
+         srcBufferY1 = srcY1;
+      }
+      else {
+         /* get both new rows */
+         readRb->GetRow(ctx, readRb, srcWidth, srcXpos, srcY0, srcBuffer0);
+         readRb->GetRow(ctx, readRb, srcWidth, srcXpos, srcY1, srcBuffer1);
+         srcBufferY0 = srcY0;
+         srcBufferY1 = srcY1;
+      }
+
+      if (readRb->DataType == GL_UNSIGNED_BYTE) {
+         resample_linear_row_ub(srcWidth, dstWidth, srcBuffer0, srcBuffer1,
+                                dstBuffer, invertX, rowWeight);
+      }
+      else {
+         _mesa_problem(ctx, "Unsupported color channel type in sw blit");
+         break;
+      }
+
+      /* store pixel row in destination */
+      drawRb->PutRow(ctx, drawRb, dstWidth, dstXpos, dstY, dstBuffer, NULL);
+   }
+
+   free(srcBuffer0);
+   free(srcBuffer1);
+   free(dstBuffer);
+}
+
+
+/**
+ * Simple case:  Blit color, depth or stencil with no scaling or flipping.
+ * XXX we could easily support vertical flipping here.
+ */
+static void
+simple_blit(struct gl_context *ctx,
+            GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
+            GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
+            GLbitfield buffer)
+{
+   struct gl_renderbuffer *readRb, *drawRb;
+   const GLint width = srcX1 - srcX0;
+   const GLint height = srcY1 - srcY0;
+   GLint row, srcY, dstY, yStep;
+   GLint comps, bytesPerRow;
+   void *rowBuffer;
+
+   /* only one buffer */
+   ASSERT(_mesa_bitcount(buffer) == 1);
+   /* no flipping checks */
+   ASSERT(srcX0 < srcX1);
+   ASSERT(srcY0 < srcY1);
+   ASSERT(dstX0 < dstX1);
+   ASSERT(dstY0 < dstY1);
+   /* size checks */
+   ASSERT(srcX1 - srcX0 == dstX1 - dstX0);
+   ASSERT(srcY1 - srcY0 == dstY1 - dstY0);
+
+   /* determine if copy should be bottom-to-top or top-to-bottom */
+   if (srcY0 > dstY0) {
+      /* src above dst: copy bottom-to-top */
+      yStep = 1;
+      srcY = srcY0;
+      dstY = dstY0;
+   }
+   else {
+      /* src below dst: copy top-to-bottom */
+      yStep = -1;
+      srcY = srcY1 - 1;
+      dstY = dstY1 - 1;
+   }
+
+   switch (buffer) {
+   case GL_COLOR_BUFFER_BIT:
+      readRb = ctx->ReadBuffer->_ColorReadBuffer;
+      drawRb = ctx->DrawBuffer->_ColorDrawBuffers[0];
+      comps = 4;
+      break;
+   case GL_DEPTH_BUFFER_BIT:
+      readRb = ctx->ReadBuffer->_DepthBuffer;
+      drawRb = ctx->DrawBuffer->_DepthBuffer;
+      comps = 1;
+      break;
+   case GL_STENCIL_BUFFER_BIT:
+      readRb = ctx->ReadBuffer->_StencilBuffer;
+      drawRb = ctx->DrawBuffer->_StencilBuffer;
+      comps = 1;
+      break;
+   default:
+      _mesa_problem(ctx, "unexpected buffer in simple_blit()");
+      return;
+   }
+
+   ASSERT(readRb->DataType == drawRb->DataType);
+
+   /* compute bytes per row */
+   switch (readRb->DataType) {
+   case GL_UNSIGNED_BYTE:
+      bytesPerRow = comps * width * sizeof(GLubyte);
+      break;
+   case GL_UNSIGNED_SHORT:
+      bytesPerRow = comps * width * sizeof(GLushort);
+      break;
+   case GL_UNSIGNED_INT:
+      bytesPerRow = comps * width * sizeof(GLuint);
+      break;
+   case GL_FLOAT:
+      bytesPerRow = comps * width * sizeof(GLfloat);
+      break;
+   default:
+      _mesa_problem(ctx, "unexpected buffer type in simple_blit");
+      return;
+   }
+
+   /* allocate the row buffer */
+   rowBuffer = malloc(bytesPerRow);
+   if (!rowBuffer) {
+      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT");
+      return;
+   }
+
+   for (row = 0; row < height; row++) {
+      readRb->GetRow(ctx, readRb, width, srcX0, srcY, rowBuffer);
+      drawRb->PutRow(ctx, drawRb, width, dstX0, dstY, rowBuffer, NULL);
+      srcY += yStep;
+      dstY += yStep;
+   }
+
+   free(rowBuffer);
+}
+
+
+/**
+ * Software fallback for glBlitFramebufferEXT().
+ */
+void
+_swrast_BlitFramebuffer(struct gl_context *ctx,
+                        GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
+                        GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
+                        GLbitfield mask, GLenum filter)
+{
+   static const GLbitfield buffers[3] = {
+      GL_COLOR_BUFFER_BIT,
+      GL_DEPTH_BUFFER_BIT,
+      GL_STENCIL_BUFFER_BIT
+   };
+   GLint i;
+
+   if (!ctx->DrawBuffer->_NumColorDrawBuffers)
+      return;
+
+   if (!_mesa_clip_blit(ctx, &srcX0, &srcY0, &srcX1, &srcY1,
+                        &dstX0, &dstY0, &dstX1, &dstY1)) {
+      return;
+   }
+
+   swrast_render_start(ctx);
+
+   if (srcX1 - srcX0 == dstX1 - dstX0 &&
+       srcY1 - srcY0 == dstY1 - dstY0 &&
+       srcX0 < srcX1 &&
+       srcY0 < srcY1 &&
+       dstX0 < dstX1 &&
+       dstY0 < dstY1) {
+      /* no stretching or flipping.
+       * filter doesn't matter.
+       */
+      for (i = 0; i < 3; i++) {
+         if (mask & buffers[i]) {
+            simple_blit(ctx, srcX0, srcY0, srcX1, srcY1,
+                        dstX0, dstY0, dstX1, dstY1, buffers[i]);
+         }
+      }
+   }
+   else {
+      if (filter == GL_NEAREST) {
+         for (i = 0; i < 3; i++) {
+            if (mask & buffers[i]) {
+               blit_nearest(ctx,  srcX0, srcY0, srcX1, srcY1,
+                            dstX0, dstY0, dstX1, dstY1, buffers[i]);
+            }
+         }
+      }
+      else {
+         ASSERT(filter == GL_LINEAR);
+         if (mask & GL_COLOR_BUFFER_BIT) {  /* depth/stencil not allowed */
+            blit_linear(ctx,  srcX0, srcY0, srcX1, srcY1,
+                        dstX0, dstY0, dstX1, dstY1);
+         }
+      }
+   }
+
+   swrast_render_finish(ctx);
+}
-- 
cgit v1.2.3