mesa: move PBO-related functions into a new file
[mesa.git] / src / mesa / drivers / common / meta.c
index ea9e4173916d2ab31ef53066e4919b789ad5451a..2b00e8979d26a7cbcc7f3e614f777ef9a0f6e52f 100644 (file)
 #include "main/glheader.h"
 #include "main/mtypes.h"
 #include "main/imports.h"
+#include "main/arbprogram.h"
 #include "main/arrayobj.h"
 #include "main/blend.h"
 #include "main/bufferobj.h"
 #include "main/buffers.h"
 #include "main/colortab.h"
-#include "main/convolve.h"
 #include "main/depth.h"
 #include "main/enable.h"
 #include "main/fbobject.h"
 #include "main/macros.h"
 #include "main/matrix.h"
 #include "main/mipmap.h"
+#include "main/pbo.h"
 #include "main/polygon.h"
 #include "main/readpix.h"
 #include "main/scissor.h"
-#include "main/shaders.h"
+#include "main/shaderapi.h"
+#include "main/shaderobj.h"
 #include "main/state.h"
 #include "main/stencil.h"
 #include "main/texobj.h"
@@ -61,8 +63,7 @@
 #include "main/texstate.h"
 #include "main/varray.h"
 #include "main/viewport.h"
-#include "shader/program.h"
-#include "shader/arbprogram.h"
+#include "program/program.h"
 #include "swrast/swrast.h"
 #include "drivers/common/meta.h"
 
@@ -104,6 +105,8 @@ struct save_state
 
    /** META_ALPHA_TEST */
    GLboolean AlphaEnabled;
+   GLenum AlphaFunc;
+   GLclampf AlphaRef;
 
    /** META_BLEND */
    GLbitfield BlendEnabled;
@@ -128,9 +131,6 @@ struct save_state
    GLfloat AlphaBias, AlphaScale;
    GLfloat DepthBias, DepthScale;
    GLboolean MapColorFlag;
-   GLboolean Convolution1DEnabled;
-   GLboolean Convolution2DEnabled;
-   GLboolean Separable2DEnabled;
 
    /** META_RASTERIZATION */
    GLenum FrontPolygonMode, BackPolygonMode;
@@ -147,7 +147,10 @@ struct save_state
    struct gl_vertex_program *VertexProgram;
    GLboolean FragmentProgramEnabled;
    struct gl_fragment_program *FragmentProgram;
-   GLuint Shader;
+   struct gl_shader_program *VertexShader;
+   struct gl_shader_program *GeometryShader;
+   struct gl_shader_program *FragmentShader;
+   struct gl_shader_program *ActiveShader;
 
    /** META_STENCIL_TEST */
    struct gl_stencil_attrib Stencil;
@@ -264,13 +267,16 @@ struct gen_mipmap_state
    GLuint FBO;
 };
 
-
+#define MAX_META_OPS_DEPTH      2
 /**
  * All per-context meta state.
  */
 struct gl_meta_state
 {
-   struct save_state Save;    /**< state saved during meta-ops */
+   /** Stack of state saved during meta-ops */
+   struct save_state Save[MAX_META_OPS_DEPTH];
+   /** Save stack depth */
+   GLuint SaveStackDepth;
 
    struct temp_texture TempTex;
 
@@ -288,7 +294,7 @@ struct gl_meta_state
  * To be called once during context creation.
  */
 void
-_mesa_meta_init(GLcontext *ctx)
+_mesa_meta_init(struct gl_context *ctx)
 {
    ASSERT(!ctx->Meta);
 
@@ -301,7 +307,7 @@ _mesa_meta_init(GLcontext *ctx)
  * To be called once during context destruction.
  */
 void
-_mesa_meta_free(GLcontext *ctx)
+_mesa_meta_free(struct gl_context *ctx)
 {
    /* Note: Any textures, VBOs, etc, that we allocate should get
     * freed by the normal context destruction code.  But this would be
@@ -320,14 +326,21 @@ _mesa_meta_free(GLcontext *ctx)
  *               to save and reset to their defaults
  */
 static void
-_mesa_meta_begin(GLcontext *ctx, GLbitfield state)
+_mesa_meta_begin(struct gl_context *ctx, GLbitfield state)
 {
-   struct save_state *save = &ctx->Meta->Save;
+   struct save_state *save;
+
+   /* hope MAX_META_OPS_DEPTH is large enough */
+   assert(ctx->Meta->SaveStackDepth < MAX_META_OPS_DEPTH);
 
+   save = &ctx->Meta->Save[ctx->Meta->SaveStackDepth++];
+   memset(save, 0, sizeof(*save));
    save->SavedState = state;
 
    if (state & META_ALPHA_TEST) {
       save->AlphaEnabled = ctx->Color.AlphaEnabled;
+      save->AlphaFunc = ctx->Color.AlphaFunc;
+      save->AlphaRef = ctx->Color.AlphaRef;
       if (ctx->Color.AlphaEnabled)
          _mesa_set_enable(ctx, GL_ALPHA_TEST, GL_FALSE);
    }
@@ -389,9 +402,6 @@ _mesa_meta_begin(GLcontext *ctx, GLbitfield state)
       save->AlphaScale = ctx->Pixel.AlphaScale;
       save->AlphaBias = ctx->Pixel.AlphaBias;
       save->MapColorFlag = ctx->Pixel.MapColorFlag;
-      save->Convolution1DEnabled = ctx->Pixel.Convolution1DEnabled;
-      save->Convolution2DEnabled = ctx->Pixel.Convolution2DEnabled;
-      save->Separable2DEnabled = ctx->Pixel.Separable2DEnabled;
       ctx->Pixel.RedScale = 1.0F;
       ctx->Pixel.RedBias = 0.0F;
       ctx->Pixel.GreenScale = 1.0F;
@@ -401,9 +411,6 @@ _mesa_meta_begin(GLcontext *ctx, GLbitfield state)
       ctx->Pixel.AlphaScale = 1.0F;
       ctx->Pixel.AlphaBias = 0.0F;
       ctx->Pixel.MapColorFlag = GL_FALSE;
-      ctx->Pixel.Convolution1DEnabled = GL_FALSE;
-      ctx->Pixel.Convolution2DEnabled = GL_FALSE;
-      ctx->Pixel.Separable2DEnabled = GL_FALSE;
       /* XXX more state */
       ctx->NewState |=_NEW_PIXEL;
    }
@@ -443,8 +450,15 @@ _mesa_meta_begin(GLcontext *ctx, GLbitfield state)
       }
 
       if (ctx->Extensions.ARB_shader_objects) {
-         save->Shader = ctx->Shader.CurrentProgram ?
-            ctx->Shader.CurrentProgram->Name : 0;
+        _mesa_reference_shader_program(ctx, &save->VertexShader,
+                                       ctx->Shader.CurrentVertexProgram);
+        _mesa_reference_shader_program(ctx, &save->GeometryShader,
+                                       ctx->Shader.CurrentGeometryProgram);
+        _mesa_reference_shader_program(ctx, &save->FragmentShader,
+                                       ctx->Shader.CurrentFragmentProgram);
+        _mesa_reference_shader_program(ctx, &save->ActiveShader,
+                                       ctx->Shader.CurrentFragmentProgram);
+
          _mesa_UseProgramObjectARB(0);
       }
    }
@@ -473,7 +487,8 @@ _mesa_meta_begin(GLcontext *ctx, GLbitfield state)
             _mesa_set_enable(ctx, GL_TEXTURE_1D, GL_FALSE);
             _mesa_set_enable(ctx, GL_TEXTURE_2D, GL_FALSE);
             _mesa_set_enable(ctx, GL_TEXTURE_3D, GL_FALSE);
-            _mesa_set_enable(ctx, GL_TEXTURE_CUBE_MAP, GL_FALSE);
+            if (ctx->Extensions.ARB_texture_cube_map)
+               _mesa_set_enable(ctx, GL_TEXTURE_CUBE_MAP, GL_FALSE);
             _mesa_set_enable(ctx, GL_TEXTURE_RECTANGLE, GL_FALSE);
             _mesa_set_enable(ctx, GL_TEXTURE_GEN_S, GL_FALSE);
             _mesa_set_enable(ctx, GL_TEXTURE_GEN_T, GL_FALSE);
@@ -567,14 +582,15 @@ _mesa_meta_begin(GLcontext *ctx, GLbitfield state)
  * Leave meta state.  This is like a light-weight version of glPopAttrib().
  */
 static void
-_mesa_meta_end(GLcontext *ctx)
+_mesa_meta_end(struct gl_context *ctx)
 {
-   struct save_state *save = &ctx->Meta->Save;
+   struct save_state *save = &ctx->Meta->Save[--ctx->Meta->SaveStackDepth];
    const GLbitfield state = save->SavedState;
 
    if (state & META_ALPHA_TEST) {
       if (ctx->Color.AlphaEnabled != save->AlphaEnabled)
          _mesa_set_enable(ctx, GL_ALPHA_TEST, save->AlphaEnabled);
+      _mesa_AlphaFunc(save->AlphaFunc, save->AlphaRef);
    }
 
    if (state & META_BLEND) {
@@ -638,9 +654,6 @@ _mesa_meta_end(GLcontext *ctx)
       ctx->Pixel.AlphaScale = save->AlphaScale;
       ctx->Pixel.AlphaBias = save->AlphaBias;
       ctx->Pixel.MapColorFlag = save->MapColorFlag;
-      ctx->Pixel.Convolution1DEnabled = save->Convolution1DEnabled;
-      ctx->Pixel.Convolution2DEnabled = save->Convolution2DEnabled;
-      ctx->Pixel.Separable2DEnabled = save->Separable2DEnabled;
       /* XXX more state */
       ctx->NewState |=_NEW_PIXEL;
    }
@@ -677,9 +690,19 @@ _mesa_meta_end(GLcontext *ctx)
         _mesa_reference_fragprog(ctx, &save->FragmentProgram, NULL);
       }
 
-      if (ctx->Extensions.ARB_shader_objects) {
-         _mesa_UseProgramObjectARB(save->Shader);
-      }
+      if (ctx->Extensions.ARB_vertex_shader)
+        _mesa_use_shader_program(ctx, GL_VERTEX_SHADER, save->VertexShader);
+
+      if (ctx->Extensions.ARB_geometry_shader4)
+        _mesa_use_shader_program(ctx, GL_GEOMETRY_SHADER_ARB,
+                                 save->GeometryShader);
+
+      if (ctx->Extensions.ARB_fragment_shader)
+        _mesa_use_shader_program(ctx, GL_FRAGMENT_SHADER,
+                                 save->FragmentShader);
+
+      _mesa_reference_shader_program(ctx, &ctx->Shader.ActiveProgram,
+                                    save->ActiveShader);
    }
 
    if (state & META_STENCIL_TEST) {
@@ -817,12 +840,27 @@ _mesa_meta_end(GLcontext *ctx)
 }
 
 
+/**
+ * Convert Z from a normalized value in the range [0, 1] to an object-space
+ * Z coordinate in [-1, +1] so that drawing at the new Z position with the
+ * default/identity ortho projection results in the original Z value.
+ * Used by the meta-Clear, Draw/CopyPixels and Bitmap functions where the Z
+ * value comes from the clear value or raster position.
+ */
+static INLINE GLfloat
+invert_z(GLfloat normZ)
+{
+   GLfloat objZ = 1.0 - 2.0 * normZ;
+   return objZ;
+}
+
+
 /**
  * One-time init for a temp_texture object.
  * Choose tex target, compute max tex size, etc.
  */
 static void
-init_temp_texture(GLcontext *ctx, struct temp_texture *tex)
+init_temp_texture(struct gl_context *ctx, struct temp_texture *tex)
 {
    /* prefer texture rectangle */
    if (ctx->Extensions.NV_texture_rectangle) {
@@ -840,7 +878,6 @@ init_temp_texture(GLcontext *ctx, struct temp_texture *tex)
    assert(tex->MaxSize > 0);
 
    _mesa_GenTextures(1, &tex->TexObj);
-   _mesa_BindTexture(tex->Target, tex->TexObj);
 }
 
 
@@ -849,7 +886,7 @@ init_temp_texture(GLcontext *ctx, struct temp_texture *tex)
  * This does some one-time init if needed.
  */
 static struct temp_texture *
-get_temp_texture(GLcontext *ctx)
+get_temp_texture(struct gl_context *ctx)
 {
    struct temp_texture *tex = &ctx->Meta->TempTex;
 
@@ -867,7 +904,7 @@ get_temp_texture(GLcontext *ctx)
  * allocation/deallocation.
  */
 static struct temp_texture *
-get_bitmap_temp_texture(GLcontext *ctx)
+get_bitmap_temp_texture(struct gl_context *ctx)
 {
    struct temp_texture *tex = &ctx->Meta->Bitmap.Tex;
 
@@ -983,7 +1020,7 @@ setup_copypix_texture(struct temp_texture *tex,
  * Setup/load texture for glDrawPixels.
  */
 static void
-setup_drawpix_texture(GLcontext *ctx,
+setup_drawpix_texture(struct gl_context *ctx,
                      struct temp_texture *tex,
                       GLboolean newTex,
                       GLenum texIntFormat,
@@ -1034,7 +1071,7 @@ setup_drawpix_texture(GLcontext *ctx,
  * One-time init for drawing depth pixels.
  */
 static void
-init_blit_depth_pixels(GLcontext *ctx)
+init_blit_depth_pixels(struct gl_context *ctx)
 {
    static const char *program =
       "!!ARBfp1.0\n"
@@ -1071,7 +1108,7 @@ init_blit_depth_pixels(GLcontext *ctx)
  *         normal path.
  */
 static GLbitfield
-blitframebuffer_texture(GLcontext *ctx,
+blitframebuffer_texture(struct gl_context *ctx,
                         GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
                         GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
                         GLbitfield mask, GLenum filter)
@@ -1200,7 +1237,7 @@ blitframebuffer_texture(GLcontext *ctx,
  * of texture mapping and polygon rendering.
  */
 void
-_mesa_meta_BlitFramebuffer(GLcontext *ctx,
+_mesa_meta_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)
@@ -1361,7 +1398,7 @@ _mesa_meta_BlitFramebuffer(GLcontext *ctx,
  * Meta implementation of ctx->Driver.Clear() in terms of polygon rendering.
  */
 void
-_mesa_meta_Clear(GLcontext *ctx, GLbitfield buffers)
+_mesa_meta_Clear(struct gl_context *ctx, GLbitfield buffers)
 {
    struct clear_state *clear = &ctx->Meta->Clear;
    struct vertex {
@@ -1370,6 +1407,7 @@ _mesa_meta_Clear(GLcontext *ctx, GLbitfield buffers)
    struct vertex verts[4];
    /* save all state but scissor, pixel pack/unpack */
    GLbitfield metaSave = META_ALL - META_SCISSOR - META_PIXEL_STORE;
+   const GLuint stencilMax = (1 << ctx->DrawBuffer->Visual.stencilBits) - 1;
 
    if (buffers & BUFFER_BITS_COLOR) {
       /* if clearing color buffers, don't save/restore colormask */
@@ -1425,7 +1463,7 @@ _mesa_meta_Clear(GLcontext *ctx, GLbitfield buffers)
       _mesa_StencilOpSeparate(GL_FRONT_AND_BACK,
                               GL_REPLACE, GL_REPLACE, GL_REPLACE);
       _mesa_StencilFuncSeparate(GL_FRONT_AND_BACK, GL_ALWAYS,
-                                ctx->Stencil.Clear & 0x7fffffff,
+                                ctx->Stencil.Clear & stencilMax,
                                 ctx->Stencil.WriteMask[0]);
    }
    else {
@@ -1438,7 +1476,7 @@ _mesa_meta_Clear(GLcontext *ctx, GLbitfield buffers)
       const GLfloat y0 = (GLfloat) ctx->DrawBuffer->_Ymin;
       const GLfloat x1 = (GLfloat) ctx->DrawBuffer->_Xmax;
       const GLfloat y1 = (GLfloat) ctx->DrawBuffer->_Ymax;
-      const GLfloat z = 1.0 - 2.0 * ctx->Depth.Clear;
+      const GLfloat z = invert_z(ctx->Depth.Clear);
       GLuint i;
 
       verts[0].x = x0;
@@ -1479,7 +1517,7 @@ _mesa_meta_Clear(GLcontext *ctx, GLbitfield buffers)
  * of texture mapping and polygon rendering.
  */
 void
-_mesa_meta_CopyPixels(GLcontext *ctx, GLint srcX, GLint srcY,
+_mesa_meta_CopyPixels(struct gl_context *ctx, GLint srcX, GLint srcY,
                       GLsizei width, GLsizei height,
                       GLint dstX, GLint dstY, GLenum type)
 {
@@ -1544,7 +1582,7 @@ _mesa_meta_CopyPixels(GLcontext *ctx, GLint srcX, GLint srcY,
       const GLfloat dstY0 = (GLfloat) dstY;
       const GLfloat dstX1 = dstX + width * ctx->Pixel.ZoomX;
       const GLfloat dstY1 = dstY + height * ctx->Pixel.ZoomY;
-      const GLfloat z = ctx->Current.RasterPos[2];
+      const GLfloat z = invert_z(ctx->Current.RasterPos[2]);
 
       verts[0].x = dstX0;
       verts[0].y = dstY0;
@@ -1593,7 +1631,7 @@ _mesa_meta_CopyPixels(GLcontext *ctx, GLint srcX, GLint srcY,
  * into tiles which fit into the max texture size.
  */
 static void
-tiled_draw_pixels(GLcontext *ctx,
+tiled_draw_pixels(struct gl_context *ctx,
                   GLint tileSize,
                   GLint x, GLint y, GLsizei width, GLsizei height,
                   GLenum format, GLenum type,
@@ -1629,7 +1667,7 @@ tiled_draw_pixels(GLcontext *ctx,
  * One-time init for drawing stencil pixels.
  */
 static void
-init_draw_stencil_pixels(GLcontext *ctx)
+init_draw_stencil_pixels(struct gl_context *ctx)
 {
    /* This program is run eight times, once for each stencil bit.
     * The stencil values to draw are found in an 8-bit alpha texture.
@@ -1693,7 +1731,7 @@ init_draw_stencil_pixels(GLcontext *ctx)
  * One-time init for drawing depth pixels.
  */
 static void
-init_draw_depth_pixels(GLcontext *ctx)
+init_draw_depth_pixels(struct gl_context *ctx)
 {
    static const char *program =
       "!!ARBfp1.0\n"
@@ -1728,7 +1766,7 @@ init_draw_depth_pixels(GLcontext *ctx)
  * of texture mapping and polygon rendering.
  */
 void
-_mesa_meta_DrawPixels(GLcontext *ctx,
+_mesa_meta_DrawPixels(struct gl_context *ctx,
                       GLint x, GLint y, GLsizei width, GLsizei height,
                       GLenum format, GLenum type,
                       const struct gl_pixelstore_attrib *unpack,
@@ -1833,7 +1871,7 @@ _mesa_meta_DrawPixels(GLcontext *ctx,
       const GLfloat y0 = (GLfloat) y;
       const GLfloat x1 = x + width * ctx->Pixel.ZoomX;
       const GLfloat y1 = y + height * ctx->Pixel.ZoomY;
-      const GLfloat z = ctx->Current.RasterPos[2];
+      const GLfloat z = invert_z(ctx->Current.RasterPos[2]);
 
       verts[0].x = x0;
       verts[0].y = y0;
@@ -1952,16 +1990,42 @@ _mesa_meta_DrawPixels(GLcontext *ctx,
    _mesa_meta_end(ctx);
 }
 
+static GLboolean
+alpha_test_raster_color(struct gl_context *ctx)
+{
+   GLfloat alpha = ctx->Current.RasterColor[ACOMP];
+   GLfloat ref = ctx->Color.AlphaRef;
+
+   switch (ctx->Color.AlphaFunc) {
+      case GL_NEVER:
+        return GL_FALSE;
+      case GL_LESS:
+        return alpha < ref;
+      case GL_EQUAL:
+        return alpha == ref;
+      case GL_LEQUAL:
+        return alpha <= ref;
+      case GL_GREATER:
+        return alpha > ref;
+      case GL_NOTEQUAL:
+        return alpha != ref;
+      case GL_GEQUAL:
+        return alpha >= ref;
+      case GL_ALWAYS:
+        return GL_TRUE;
+      default:
+        assert(0);
+        return GL_FALSE;
+   }
+}
 
 /**
- * Do glBitmap with a alpha texture quad.  Use the alpha test to
- * cull the 'off' bits.  If alpha test is already enabled, fall back
- * to swrast (should be a rare case).
- * A bitmap cache as in the gallium/mesa state tracker would
- * improve performance a lot.
+ * Do glBitmap with a alpha texture quad.  Use the alpha test to cull
+ * the 'off' bits.  A bitmap cache as in the gallium/mesa state
+ * tracker would improve performance a lot.
  */
 void
-_mesa_meta_Bitmap(GLcontext *ctx,
+_mesa_meta_Bitmap(struct gl_context *ctx,
                   GLint x, GLint y, GLsizei width, GLsizei height,
                   const struct gl_pixelstore_attrib *unpack,
                   const GLubyte *bitmap1)
@@ -1970,6 +2034,7 @@ _mesa_meta_Bitmap(GLcontext *ctx,
    struct temp_texture *tex = get_bitmap_temp_texture(ctx);
    const GLenum texIntFormat = GL_ALPHA;
    const struct gl_pixelstore_attrib unpackSave = *unpack;
+   GLubyte fg, bg;
    struct vertex {
       GLfloat x, y, z, s, t, r, g, b, a;
    };
@@ -1981,7 +2046,7 @@ _mesa_meta_Bitmap(GLcontext *ctx,
     * Check if swrast fallback is needed.
     */
    if (ctx->_ImageTransferState ||
-       ctx->Color.AlphaEnabled ||
+       ctx->FragmentProgram._Enabled ||
        ctx->Fog.Enabled ||
        ctx->Texture._EnabledUnits ||
        width > tex->MaxSize ||
@@ -1990,6 +2055,9 @@ _mesa_meta_Bitmap(GLcontext *ctx,
       return;
    }
 
+   if (ctx->Color.AlphaEnabled && !alpha_test_raster_color(ctx))
+      return;
+
    /* Most GL state applies to glBitmap (like blending, stencil, etc),
     * but a there's a few things we need to override:
     */
@@ -2036,7 +2104,7 @@ _mesa_meta_Bitmap(GLcontext *ctx,
       const GLfloat y0 = (GLfloat) y;
       const GLfloat x1 = (GLfloat) (x + width);
       const GLfloat y1 = (GLfloat) (y + height);
-      const GLfloat z = ctx->Current.RasterPos[2];
+      const GLfloat z = invert_z(ctx->Current.RasterPos[2]);
       GLuint i;
 
       verts[0].x = x0;
@@ -2071,21 +2139,26 @@ _mesa_meta_Bitmap(GLcontext *ctx,
       _mesa_BufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, sizeof(verts), verts);
    }
 
+   /* choose different foreground/background alpha values */
+   CLAMPED_FLOAT_TO_UBYTE(fg, ctx->Current.RasterColor[ACOMP]);
+   bg = (fg > 127 ? 0 : 255);
+
    bitmap1 = _mesa_map_pbo_source(ctx, &unpackSave, bitmap1);
    if (!bitmap1) {
       _mesa_meta_end(ctx);
       return;
    }
 
-   bitmap8 = (GLubyte *) calloc(1, width * height);
+   bitmap8 = (GLubyte *) malloc(width * height);
    if (bitmap8) {
+      memset(bitmap8, bg, width * height);
       _mesa_expand_bitmap(width, height, &unpackSave, bitmap1,
-                          bitmap8, width, 0xff);
+                          bitmap8, width, fg);
 
       _mesa_set_enable(ctx, tex->Target, GL_TRUE);
 
       _mesa_set_enable(ctx, GL_ALPHA_TEST, GL_TRUE);
-      _mesa_AlphaFunc(GL_GREATER, 0.0);
+      _mesa_AlphaFunc(GL_NOTEQUAL, UBYTE_TO_FLOAT(bg));
 
       setup_drawpix_texture(ctx, tex, newTex, texIntFormat, width, height,
                             GL_ALPHA, GL_UNSIGNED_BYTE, bitmap8);
@@ -2110,7 +2183,7 @@ _mesa_meta_Bitmap(GLcontext *ctx,
  * \return GL_TRUE if a fallback is needed, GL_FALSE otherwise
  */
 GLboolean
-_mesa_meta_check_generate_mipmap_fallback(GLcontext *ctx, GLenum target,
+_mesa_meta_check_generate_mipmap_fallback(struct gl_context *ctx, GLenum target,
                                           struct gl_texture_object *texObj)
 {
    const GLuint fboSave = ctx->DrawBuffer->Name;
@@ -2176,7 +2249,7 @@ _mesa_meta_check_generate_mipmap_fallback(GLcontext *ctx, GLenum target,
  * Note: texture borders and 3D texture support not yet complete.
  */
 void
-_mesa_meta_GenerateMipmap(GLcontext *ctx, GLenum target,
+_mesa_meta_GenerateMipmap(struct gl_context *ctx, GLenum target,
                           struct gl_texture_object *texObj)
 {
    struct gen_mipmap_state *mipmap = &ctx->Meta->Mipmap;
@@ -2188,7 +2261,6 @@ _mesa_meta_GenerateMipmap(GLcontext *ctx, GLenum target,
    const GLuint maxLevel = texObj->MaxLevel;
    const GLenum minFilterSave = texObj->MinFilter;
    const GLenum magFilterSave = texObj->MagFilter;
-   const GLint baseLevelSave = texObj->BaseLevel;
    const GLint maxLevelSave = texObj->MaxLevel;
    const GLboolean genMipmapSave = texObj->GenerateMipmap;
    const GLenum wrapSSave = texObj->WrapS;
@@ -2248,7 +2320,7 @@ _mesa_meta_GenerateMipmap(GLcontext *ctx, GLenum target,
    }
    _mesa_BindFramebufferEXT(GL_FRAMEBUFFER_EXT, mipmap->FBO);
 
-   _mesa_TexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+   _mesa_TexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    _mesa_TexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    _mesa_TexParameteri(target, GL_GENERATE_MIPMAP, GL_FALSE);
    _mesa_TexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
@@ -2385,6 +2457,9 @@ _mesa_meta_GenerateMipmap(GLcontext *ctx, GLenum target,
          break;
       }
 
+      /* Set MaxLevel large enough to hold the new level when we allocate it  */
+      _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, dstLevel);
+
       /* Create empty dest image */
       if (target == GL_TEXTURE_1D) {
          _mesa_TexImage1D(target, dstLevel, srcImage->InternalFormat,
@@ -2421,8 +2496,7 @@ _mesa_meta_GenerateMipmap(GLcontext *ctx, GLenum target,
          }
       }
 
-      /* limit sampling to src level */
-      _mesa_TexParameteri(target, GL_TEXTURE_BASE_LEVEL, srcLevel);
+      /* limit minification to src level */
       _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, srcLevel);
 
       /* Set to draw into the current dstLevel */
@@ -2474,7 +2548,6 @@ _mesa_meta_GenerateMipmap(GLcontext *ctx, GLenum target,
 
    _mesa_TexParameteri(target, GL_TEXTURE_MIN_FILTER, minFilterSave);
    _mesa_TexParameteri(target, GL_TEXTURE_MAG_FILTER, magFilterSave);
-   _mesa_TexParameteri(target, GL_TEXTURE_BASE_LEVEL, baseLevelSave);
    _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, maxLevelSave);
    _mesa_TexParameteri(target, GL_GENERATE_MIPMAP, genMipmapSave);
    _mesa_TexParameteri(target, GL_TEXTURE_WRAP_S, wrapSSave);
@@ -2490,7 +2563,7 @@ _mesa_meta_GenerateMipmap(GLcontext *ctx, GLenum target,
  * ReadPixels() and passed to Tex[Sub]Image().
  */
 static GLenum
-get_temp_image_type(GLcontext *ctx, GLenum baseFormat)
+get_temp_image_type(struct gl_context *ctx, GLenum baseFormat)
 {
    switch (baseFormat) {
    case GL_RGBA:
@@ -2521,13 +2594,12 @@ get_temp_image_type(GLcontext *ctx, GLenum baseFormat)
  * Have to be careful with locking and meta state for pixel transfer.
  */
 static void
-copy_tex_image(GLcontext *ctx, GLuint dims, GLenum target, GLint level,
+copy_tex_image(struct gl_context *ctx, GLuint dims, GLenum target, GLint level,
                GLenum internalFormat, GLint x, GLint y,
                GLsizei width, GLsizei height, GLint border)
 {
    struct gl_texture_object *texObj;
    struct gl_texture_image *texImage;
-   GLsizei postConvWidth = width, postConvHeight = height;
    GLenum format, type;
    GLint bpp;
    void *buf;
@@ -2535,6 +2607,7 @@ copy_tex_image(GLcontext *ctx, GLuint dims, GLenum target, GLint level,
    texObj = _mesa_get_current_tex_object(ctx, target);
    texImage = _mesa_get_tex_image(ctx, texObj, target, level);
 
+   /* Choose format/type for temporary image buffer */
    format = _mesa_base_tex_format(ctx, internalFormat);
    type = get_temp_image_type(ctx, format);
    bpp = _mesa_bytes_per_pixel(format, type);
@@ -2552,12 +2625,6 @@ copy_tex_image(GLcontext *ctx, GLuint dims, GLenum target, GLint level,
       return;
    }
 
-   if (texImage->TexFormat == MESA_FORMAT_NONE)
-      texImage->TexFormat = ctx->Driver.ChooseTextureFormat(ctx,
-                                                            internalFormat,
-                                                            format,
-                                                            type);
-
    _mesa_unlock_texture(ctx, texObj); /* need to unlock first */
 
    /*
@@ -2568,23 +2635,12 @@ copy_tex_image(GLcontext *ctx, GLuint dims, GLenum target, GLint level,
                          format, type, &ctx->Pack, buf);
    _mesa_meta_end(ctx);
 
-   /*
-    * Prepare for new texture image size/data
-    */
-#if FEATURE_convolve
-   if (_mesa_is_color_format(internalFormat)) {
-      _mesa_adjust_image_for_convolution(ctx, 2,
-                                         &postConvWidth, &postConvHeight);
-   }
-#endif
-
    if (texImage->Data) {
       ctx->Driver.FreeTexImageData(ctx, texImage);
    }
 
-   _mesa_init_teximage_fields(ctx, target, texImage,
-                              postConvWidth, postConvHeight, 1,
-                              border, internalFormat);
+   /* The texture's format was already chosen in _mesa_CopyTexImage() */
+   ASSERT(texImage->TexFormat != MESA_FORMAT_NONE);
 
    /*
     * Store texture data (with pixel transfer ops)
@@ -2612,7 +2668,7 @@ copy_tex_image(GLcontext *ctx, GLuint dims, GLenum target, GLint level,
 
 
 void
-_mesa_meta_CopyTexImage1D(GLcontext *ctx, GLenum target, GLint level,
+_mesa_meta_CopyTexImage1D(struct gl_context *ctx, GLenum target, GLint level,
                           GLenum internalFormat, GLint x, GLint y,
                           GLsizei width, GLint border)
 {
@@ -2622,7 +2678,7 @@ _mesa_meta_CopyTexImage1D(GLcontext *ctx, GLenum target, GLint level,
 
 
 void
-_mesa_meta_CopyTexImage2D(GLcontext *ctx, GLenum target, GLint level,
+_mesa_meta_CopyTexImage2D(struct gl_context *ctx, GLenum target, GLint level,
                           GLenum internalFormat, GLint x, GLint y,
                           GLsizei width, GLsizei height, GLint border)
 {
@@ -2637,7 +2693,8 @@ _mesa_meta_CopyTexImage2D(GLcontext *ctx, GLenum target, GLint level,
  * Have to be careful with locking and meta state for pixel transfer.
  */
 static void
-copy_tex_sub_image(GLcontext *ctx, GLuint dims, GLenum target, GLint level,
+copy_tex_sub_image(struct gl_context *ctx,
+                   GLuint dims, GLenum target, GLint level,
                    GLint xoffset, GLint yoffset, GLint zoffset,
                    GLint x, GLint y,
                    GLsizei width, GLsizei height)
@@ -2651,6 +2708,7 @@ copy_tex_sub_image(GLcontext *ctx, GLuint dims, GLenum target, GLint level,
    texObj = _mesa_get_current_tex_object(ctx, target);
    texImage = _mesa_select_tex_image(ctx, texObj, target, level);
 
+   /* Choose format/type for temporary image buffer */
    format = _mesa_get_format_base_format(texImage->TexFormat);
    type = get_temp_image_type(ctx, format);
    bpp = _mesa_bytes_per_pixel(format, type);
@@ -2708,7 +2766,7 @@ copy_tex_sub_image(GLcontext *ctx, GLuint dims, GLenum target, GLint level,
 
 
 void
-_mesa_meta_CopyTexSubImage1D(GLcontext *ctx, GLenum target, GLint level,
+_mesa_meta_CopyTexSubImage1D(struct gl_context *ctx, GLenum target, GLint level,
                              GLint xoffset,
                              GLint x, GLint y, GLsizei width)
 {
@@ -2718,7 +2776,7 @@ _mesa_meta_CopyTexSubImage1D(GLcontext *ctx, GLenum target, GLint level,
 
 
 void
-_mesa_meta_CopyTexSubImage2D(GLcontext *ctx, GLenum target, GLint level,
+_mesa_meta_CopyTexSubImage2D(struct gl_context *ctx, GLenum target, GLint level,
                              GLint xoffset, GLint yoffset,
                              GLint x, GLint y,
                              GLsizei width, GLsizei height)
@@ -2729,7 +2787,7 @@ _mesa_meta_CopyTexSubImage2D(GLcontext *ctx, GLenum target, GLint level,
 
 
 void
-_mesa_meta_CopyTexSubImage3D(GLcontext *ctx, GLenum target, GLint level,
+_mesa_meta_CopyTexSubImage3D(struct gl_context *ctx, GLenum target, GLint level,
                              GLint xoffset, GLint yoffset, GLint zoffset,
                              GLint x, GLint y,
                              GLsizei width, GLsizei height)
@@ -2740,7 +2798,7 @@ _mesa_meta_CopyTexSubImage3D(GLcontext *ctx, GLenum target, GLint level,
 
 
 void
-_mesa_meta_CopyColorTable(GLcontext *ctx,
+_mesa_meta_CopyColorTable(struct gl_context *ctx,
                           GLenum target, GLenum internalformat,
                           GLint x, GLint y, GLsizei width)
 {
@@ -2768,7 +2826,7 @@ _mesa_meta_CopyColorTable(GLcontext *ctx,
 
 
 void
-_mesa_meta_CopyColorSubTable(GLcontext *ctx,GLenum target, GLsizei start,
+_mesa_meta_CopyColorSubTable(struct gl_context *ctx,GLenum target, GLsizei start,
                              GLint x, GLint y, GLsizei width)
 {
    GLfloat *buf;
@@ -2792,64 +2850,3 @@ _mesa_meta_CopyColorSubTable(GLcontext *ctx,GLenum target, GLsizei start,
 
    free(buf);
 }
-
-
-void
-_mesa_meta_CopyConvolutionFilter1D(GLcontext *ctx, GLenum target,
-                                   GLenum internalFormat,
-                                   GLint x, GLint y, GLsizei width)
-{
-   GLfloat *buf;
-
-   buf = (GLfloat *) malloc(width * 4 * sizeof(GLfloat));
-   if (!buf) {
-      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyConvolutionFilter2D");
-      return;
-   }
-
-   /*
-    * Read image from framebuffer (disable pixel transfer ops)
-    */
-   _mesa_meta_begin(ctx, META_PIXEL_STORE | META_PIXEL_TRANSFER);
-   _mesa_update_state(ctx);
-   ctx->Driver.ReadPixels(ctx, x, y, width, 1,
-                          GL_RGBA, GL_FLOAT, &ctx->Pack, buf);
-
-   _mesa_ConvolutionFilter1D(target, internalFormat, width,
-                             GL_RGBA, GL_FLOAT, buf);
-
-   _mesa_meta_end(ctx);
-
-   free(buf);
-}
-
-
-void
-_mesa_meta_CopyConvolutionFilter2D(GLcontext *ctx, GLenum target,
-                                   GLenum internalFormat, GLint x, GLint y,
-                                   GLsizei width, GLsizei height)
-{
-   GLfloat *buf;
-
-   buf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat));
-   if (!buf) {
-      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyConvolutionFilter2D");
-      return;
-   }
-
-   /*
-    * Read image from framebuffer (disable pixel transfer ops)
-    */
-   _mesa_meta_begin(ctx, META_PIXEL_STORE | META_PIXEL_TRANSFER);
-   _mesa_update_state(ctx);
-
-   ctx->Driver.ReadPixels(ctx, x, y, width, height,
-                          GL_RGBA, GL_FLOAT, &ctx->Pack, buf);
-
-   _mesa_ConvolutionFilter2D(target, internalFormat, width, height,
-                             GL_RGBA, GL_FLOAT, buf);
-
-   _mesa_meta_end(ctx);
-
-   free(buf);
-}