i965/gen6_surface_state.c: Remove (gen < 6) code path
[mesa.git] / src / mesa / drivers / common / meta_generate_mipmap.c
index 6a0ccbdb7dd1469eab3c41da9d822d7b824623ef..8ffd8da3bdeda693100bcacbfad3c64eb779e266 100644 (file)
@@ -43,6 +43,8 @@
 #include "main/varray.h"
 #include "main/viewport.h"
 #include "drivers/common/meta.h"
+#include "program/prog_instruction.h"
+
 
 /**
  * Check if the call to _mesa_meta_GenerateMipmap() will require a
@@ -61,9 +63,7 @@ fallback_required(struct gl_context *ctx, GLenum target,
    GLenum status;
 
    /* check for fallbacks */
-   if (target == GL_TEXTURE_3D ||
-       target == GL_TEXTURE_1D_ARRAY ||
-       target == GL_TEXTURE_2D_ARRAY) {
+   if (target == GL_TEXTURE_3D) {
       _mesa_perf_debug(ctx, MESA_DEBUG_SEVERITY_HIGH,
                        "glGenerateMipmap() to %s target\n",
                        _mesa_lookup_enum_by_nr(target));
@@ -104,26 +104,7 @@ fallback_required(struct gl_context *ctx, GLenum target,
       _mesa_GenFramebuffers(1, &mipmap->FBO);
    _mesa_BindFramebuffer(GL_FRAMEBUFFER_EXT, mipmap->FBO);
 
-   if (target == GL_TEXTURE_1D) {
-      _mesa_FramebufferTexture1D(GL_FRAMEBUFFER_EXT,
-                                    GL_COLOR_ATTACHMENT0_EXT,
-                                    target, texObj->Name, srcLevel);
-   }
-#if 0
-   /* other work is needed to enable 3D mipmap generation */
-   else if (target == GL_TEXTURE_3D) {
-      GLint zoffset = 0;
-      _mesa_FramebufferTexture3D(GL_FRAMEBUFFER_EXT,
-                                    GL_COLOR_ATTACHMENT0_EXT,
-                                    target, texObj->Name, srcLevel, zoffset);
-   }
-#endif
-   else {
-      /* 2D / cube */
-      _mesa_FramebufferTexture2D(GL_FRAMEBUFFER_EXT,
-                                    GL_COLOR_ATTACHMENT0_EXT,
-                                    target, texObj->Name, srcLevel);
-   }
+   _mesa_meta_bind_fbo_image(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, baseImage, 0);
 
    status = _mesa_CheckFramebufferStatus(GL_FRAMEBUFFER_EXT);
 
@@ -151,6 +132,22 @@ _mesa_meta_glsl_generate_mipmap_cleanup(struct gen_mipmap_state *mipmap)
    _mesa_meta_blit_shader_table_cleanup(&mipmap->shaders);
 }
 
+static GLboolean
+prepare_mipmap_level(struct gl_context *ctx,
+                     struct gl_texture_object *texObj, GLuint level,
+                     GLsizei width, GLsizei height, GLsizei depth,
+                     GLenum intFormat, mesa_format format)
+{
+   if (texObj->Target == GL_TEXTURE_1D_ARRAY) {
+      /* Work around Mesa expecting the number of array slices in "height". */
+      height = depth;
+      depth = 1;
+   }
+
+   return _mesa_prepare_mipmap_level(ctx, texObj, level, width, height, depth,
+                                     0, intFormat, format);
+}
+
 /**
  * Called via ctx->Driver.GenerateMipmap()
  * Note: We don't yet support 3D textures, 1D/2D array textures or texture
@@ -166,14 +163,14 @@ _mesa_meta_GenerateMipmap(struct gl_context *ctx, GLenum target,
    const GLuint maxLevel = texObj->MaxLevel;
    const GLint maxLevelSave = texObj->MaxLevel;
    const GLboolean genMipmapSave = texObj->GenerateMipmap;
-   const GLuint fboSave = ctx->DrawBuffer->Name;
    const GLuint currentTexUnitSave = ctx->Texture.CurrentUnit;
    const GLboolean use_glsl_version = ctx->Extensions.ARB_vertex_shader &&
                                       ctx->Extensions.ARB_fragment_shader;
    GLenum faceTarget;
    GLuint dstLevel;
-   const GLint slice = 0;
    GLuint samplerSave;
+   GLint swizzle[4];
+   GLboolean swizzleSaved = GL_FALSE;
 
    if (fallback_required(ctx, target, texObj)) {
       _mesa_generate_mipmap(ctx, target, texObj);
@@ -188,14 +185,14 @@ _mesa_meta_GenerateMipmap(struct gl_context *ctx, GLenum target,
       faceTarget = target;
    }
 
-   _mesa_meta_begin(ctx, MESA_META_ALL);
+   _mesa_meta_begin(ctx, MESA_META_ALL & ~MESA_META_DRAW_BUFFERS);
 
    /* Choose between glsl version and fixed function version of
     * GenerateMipmap function.
     */
    if (use_glsl_version) {
       _mesa_meta_setup_vertex_objects(&mipmap->VAO, &mipmap->VBO, true,
-                                      2, 3, 0);
+                                      2, 4, 0);
       _mesa_meta_setup_blit_shader(ctx, target, &mipmap->shaders);
    } else {
       _mesa_meta_setup_ff_tnl_for_blit(&mipmap->VAO, &mipmap->VBO, 3);
@@ -237,18 +234,16 @@ _mesa_meta_GenerateMipmap(struct gl_context *ctx, GLenum target,
 
    _mesa_TexParameteri(target, GL_GENERATE_MIPMAP, GL_FALSE);
 
+   if (texObj->_Swizzle != SWIZZLE_NOOP) {
+      static const GLint swizzleNoop[4] = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA };
+      memcpy(swizzle, texObj->Swizzle, sizeof(swizzle));
+      swizzleSaved = GL_TRUE;
+      _mesa_TexParameteriv(target, GL_TEXTURE_SWIZZLE_RGBA, swizzleNoop);
+   }
+
    /* Silence valgrind warnings about reading uninitialized stack. */
    memset(verts, 0, sizeof(verts));
 
-   /* Setup texture coordinates */
-   _mesa_meta_setup_texture_coords(faceTarget,
-                                   slice,
-                                   0, 0, 1, /* width, height never used here */
-                                   verts[0].tex,
-                                   verts[1].tex,
-                                   verts[2].tex,
-                                   verts[3].tex);
-
    /* setup vertex positions */
    verts[0].x = -1.0F;
    verts[0].y = -1.0F;
@@ -259,36 +254,38 @@ _mesa_meta_GenerateMipmap(struct gl_context *ctx, GLenum target,
    verts[3].x = -1.0F;
    verts[3].y =  1.0F;
 
-   /* upload vertex data */
-   _mesa_BufferData(GL_ARRAY_BUFFER_ARB, sizeof(verts),
-                       verts, GL_DYNAMIC_DRAW_ARB);
-
    /* texture is already locked, unlock now */
    _mesa_unlock_texture(ctx, texObj);
 
    for (dstLevel = baseLevel + 1; dstLevel <= maxLevel; dstLevel++) {
       const struct gl_texture_image *srcImage;
+      struct gl_texture_image *dstImage;
       const GLuint srcLevel = dstLevel - 1;
+      GLuint layer;
       GLsizei srcWidth, srcHeight, srcDepth;
       GLsizei dstWidth, dstHeight, dstDepth;
-      GLenum status;
 
       srcImage = _mesa_select_tex_image(ctx, texObj, faceTarget, srcLevel);
       assert(srcImage->Border == 0);
 
       /* src size */
       srcWidth = srcImage->Width;
-      srcHeight = srcImage->Height;
-      srcDepth = srcImage->Depth;
+      if (target == GL_TEXTURE_1D_ARRAY) {
+         srcHeight = 1;
+         srcDepth = srcImage->Height;
+      } else {
+         srcHeight = srcImage->Height;
+         srcDepth = srcImage->Depth;
+      }
 
       /* new dst size */
-      dstWidth = MAX2(1, srcWidth / 2);
-      dstHeight = MAX2(1, srcHeight / 2);
-      dstDepth = MAX2(1, srcDepth / 2);
+      dstWidth = minify(srcWidth, 1);
+      dstHeight = minify(srcHeight, 1);
+      dstDepth = target == GL_TEXTURE_3D ? minify(srcDepth, 1) : srcDepth;
 
-      if (dstWidth == srcImage->Width &&
-          dstHeight == srcImage->Height &&
-          dstDepth == srcImage->Depth) {
+      if (dstWidth == srcWidth &&
+          dstHeight == srcHeight &&
+          dstDepth == srcDepth) {
          /* all done */
          break;
       }
@@ -298,61 +295,57 @@ _mesa_meta_GenerateMipmap(struct gl_context *ctx, GLenum target,
       /* Set MaxLevel large enough to hold the new level when we allocate it */
       _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, dstLevel);
 
-      if (!_mesa_prepare_mipmap_level(ctx, texObj, dstLevel,
-                                      dstWidth, dstHeight, dstDepth,
-                                      srcImage->Border,
-                                      srcImage->InternalFormat,
-                                      srcImage->TexFormat)) {
+      if (!prepare_mipmap_level(ctx, texObj, dstLevel,
+                                dstWidth, dstHeight, dstDepth,
+                                srcImage->InternalFormat,
+                                srcImage->TexFormat)) {
          /* All done.  We either ran out of memory or we would go beyond the
           * last valid level of an immutable texture if we continued.
           */
          break;
       }
+      dstImage = _mesa_select_tex_image(ctx, texObj, faceTarget, dstLevel);
 
       /* limit minification to src level */
       _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, srcLevel);
 
-      /* Set to draw into the current dstLevel */
-      if (target == GL_TEXTURE_1D) {
-         _mesa_FramebufferTexture1D(GL_FRAMEBUFFER_EXT,
-                                       GL_COLOR_ATTACHMENT0_EXT,
-                                       target,
-                                       texObj->Name,
-                                       dstLevel);
-      }
-      else if (target == GL_TEXTURE_3D) {
-         GLint zoffset = 0; /* XXX unfinished */
-         _mesa_FramebufferTexture3D(GL_FRAMEBUFFER_EXT,
-                                       GL_COLOR_ATTACHMENT0_EXT,
-                                       target,
-                                       texObj->Name,
-                                       dstLevel, zoffset);
-      } else {
-         /* 2D / cube */
-         _mesa_FramebufferTexture2D(GL_FRAMEBUFFER_EXT,
-                                       GL_COLOR_ATTACHMENT0_EXT,
-                                       faceTarget,
-                                       texObj->Name,
-                                       dstLevel);
-      }
-
-      _mesa_DrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
-
-      /* sanity check */
-      status = _mesa_CheckFramebufferStatus(GL_FRAMEBUFFER_EXT);
-      if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
-         _mesa_problem(ctx, "Unexpected incomplete framebuffer in "
-                       "_mesa_meta_GenerateMipmap()");
-         break;
-      }
-
-      assert(dstWidth == ctx->DrawBuffer->Width);
-      assert(dstHeight == ctx->DrawBuffer->Height);
-
       /* setup viewport */
       _mesa_set_viewport(ctx, 0, 0, 0, dstWidth, dstHeight);
-
-      _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
+      _mesa_DrawBuffer(GL_COLOR_ATTACHMENT0);
+
+      for (layer = 0; layer < dstDepth; ++layer) {
+         /* Setup texture coordinates */
+         _mesa_meta_setup_texture_coords(faceTarget,
+                                         layer,
+                                         0, 0, 1, /* width, height never used here */
+                                         verts[0].tex,
+                                         verts[1].tex,
+                                         verts[2].tex,
+                                         verts[3].tex);
+
+         /* upload vertex data */
+         _mesa_BufferData(GL_ARRAY_BUFFER_ARB, sizeof(verts),
+                          verts, GL_DYNAMIC_DRAW_ARB);
+
+         _mesa_meta_bind_fbo_image(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, dstImage, layer);
+
+         /* sanity check */
+         if (_mesa_CheckFramebufferStatus(GL_FRAMEBUFFER) !=
+             GL_FRAMEBUFFER_COMPLETE) {
+            _mesa_problem(ctx, "Unexpected incomplete framebuffer in "
+                          "_mesa_meta_GenerateMipmap()");
+            break;
+         }
+
+         assert(dstWidth == ctx->DrawBuffer->Width);
+         if (target == GL_TEXTURE_1D_ARRAY) {
+            assert(dstHeight == 1);
+         } else {
+            assert(dstHeight == ctx->DrawBuffer->Height);
+         }
+
+         _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
+      }
    }
 
    _mesa_lock_texture(ctx, texObj); /* relock */
@@ -364,6 +357,6 @@ _mesa_meta_GenerateMipmap(struct gl_context *ctx, GLenum target,
    _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, maxLevelSave);
    if (genMipmapSave)
       _mesa_TexParameteri(target, GL_GENERATE_MIPMAP, genMipmapSave);
-
-   _mesa_BindFramebuffer(GL_FRAMEBUFFER_EXT, fboSave);
+   if (swizzleSaved)
+      _mesa_TexParameteriv(target, GL_TEXTURE_SWIZZLE_RGBA, swizzle);
 }