drivers/meta: Accept GL_TEXTURE_3D as target for tex image decompression
[mesa.git] / src / mesa / drivers / common / meta_generate_mipmap.c
index 9369e845c178f4b9b08a39b7a06b0f354d408421..bbe9d6d8863116712c4741431f0c3aa758fbe6f8 100644 (file)
  */
 
 #include "main/arrayobj.h"
+#include "main/blend.h"
 #include "main/buffers.h"
 #include "main/enums.h"
 #include "main/enable.h"
 #include "main/fbobject.h"
+#include "main/framebuffer.h"
 #include "main/macros.h"
 #include "main/mipmap.h"
 #include "main/teximage.h"
@@ -56,21 +58,11 @@ static bool
 fallback_required(struct gl_context *ctx, GLenum target,
                   struct gl_texture_object *texObj)
 {
-   const GLuint fboSave = ctx->DrawBuffer->Name;
    struct gen_mipmap_state *mipmap = &ctx->Meta->Mipmap;
    struct gl_texture_image *baseImage;
    GLuint srcLevel;
    GLenum status;
 
-   /* GL_DRAW_FRAMEBUFFER does not exist in OpenGL ES 1.x, and since
-    * _mesa_meta_begin hasn't been called yet, we have to work-around API
-    * difficulties.  The whole reason that GL_DRAW_FRAMEBUFFER is used instead
-    * of GL_FRAMEBUFFER is that the read framebuffer may be different.  This
-    * is moot in OpenGL ES 1.x.
-    */
-   const GLenum fbo_target = ctx->API == API_OPENGLES
-      ? GL_FRAMEBUFFER : GL_DRAW_FRAMEBUFFER;
-
    /* check for fallbacks */
    if (target == GL_TEXTURE_3D) {
       _mesa_perf_debug(ctx, MESA_DEBUG_SEVERITY_HIGH,
@@ -109,17 +101,19 @@ fallback_required(struct gl_context *ctx, GLenum target,
    /*
     * Test that we can actually render in the texture's format.
     */
-   if (!mipmap->FBO)
-      _mesa_GenFramebuffers(1, &mipmap->FBO);
-   _mesa_BindFramebuffer(fbo_target, mipmap->FBO);
+   if (mipmap->fb == NULL) {
+      mipmap->fb = ctx->Driver.NewFramebuffer(ctx, 0xDEADBEEF);
+      if (mipmap->fb == NULL) {
+         _mesa_perf_debug(ctx, MESA_DEBUG_SEVERITY_HIGH,
+                          "glGenerateMipmap() ran out of memory\n");
+         return true;
+      }
+   }
 
-   _mesa_meta_framebuffer_texture_image(ctx, ctx->DrawBuffer,
+   _mesa_meta_framebuffer_texture_image(ctx, mipmap->fb,
                                         GL_COLOR_ATTACHMENT0, baseImage, 0);
 
-   status = _mesa_check_framebuffer_status(ctx, ctx->DrawBuffer);
-
-   _mesa_BindFramebuffer(fbo_target, fboSave);
-
+   status = _mesa_check_framebuffer_status(ctx, mipmap->fb);
    if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
       _mesa_perf_debug(ctx, MESA_DEBUG_SEVERITY_HIGH,
                        "glGenerateMipmap() got incomplete FBO\n");
@@ -139,30 +133,11 @@ _mesa_meta_glsl_generate_mipmap_cleanup(struct gl_context *ctx,
    mipmap->VAO = 0;
    _mesa_reference_buffer_object(ctx, &mipmap->buf_obj, NULL);
    _mesa_reference_sampler_object(ctx, &mipmap->samp_obj, NULL);
+   _mesa_reference_framebuffer(&mipmap->fb, NULL);
 
-   if (mipmap->FBO != 0) {
-      _mesa_DeleteFramebuffers(1, &mipmap->FBO);
-      mipmap->FBO = 0;
-   }
-
-   _mesa_meta_blit_shader_table_cleanup(&mipmap->shaders);
+   _mesa_meta_blit_shader_table_cleanup(ctx, &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()
@@ -206,6 +181,7 @@ _mesa_meta_GenerateMipmap(struct gl_context *ctx, GLenum target,
    }
 
    _mesa_meta_begin(ctx, MESA_META_ALL & ~MESA_META_DRAW_BUFFERS);
+   _mesa_ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
 
    /* Choose between glsl version and fixed function version of
     * GenerateMipmap function.
@@ -245,15 +221,23 @@ _mesa_meta_GenerateMipmap(struct gl_context *ctx, GLenum target,
                                 GL_LINEAR);
       _mesa_set_sampler_wrap(ctx, mipmap->samp_obj, GL_CLAMP_TO_EDGE,
                              GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
+   }
+
+   if (ctx->Extensions.EXT_texture_sRGB_decode) {
+      const struct gl_texture_image *baseImage =
+         _mesa_select_tex_image(texObj, target, texObj->BaseLevel);
+      const bool srgb =
+         _mesa_get_format_color_encoding(baseImage->TexFormat) == GL_SRGB;
 
-      /* We don't want to encode or decode sRGB values; treat them as linear. */
-      _mesa_set_sampler_srgb_decode(ctx, mipmap->samp_obj, GL_SKIP_DECODE_EXT);
+      _mesa_set_sampler_srgb_decode(ctx, mipmap->samp_obj,
+                                    srgb ? GL_DECODE_EXT : GL_SKIP_DECODE_EXT);
+      _mesa_set_framebuffer_srgb(ctx, srgb);
    }
 
    _mesa_bind_sampler(ctx, ctx->Texture.CurrentUnit, mipmap->samp_obj);
 
-   assert(mipmap->FBO != 0);
-   _mesa_BindFramebuffer(GL_FRAMEBUFFER_EXT, mipmap->FBO);
+   assert(mipmap->fb != NULL);
+   _mesa_bind_framebuffers(ctx, mipmap->fb, mipmap->fb);
 
    _mesa_texture_parameteriv(ctx, texObj, GL_GENERATE_MIPMAP, &always_false, false);
 
@@ -281,6 +265,8 @@ _mesa_meta_GenerateMipmap(struct gl_context *ctx, GLenum target,
    /* texture is already locked, unlock now */
    _mesa_unlock_texture(ctx, texObj);
 
+   _mesa_prepare_mipmap_levels(ctx, texObj, baseLevel, maxLevel);
+
    for (dstLevel = baseLevel + 1; dstLevel <= maxLevel; dstLevel++) {
       const struct gl_texture_image *srcImage;
       struct gl_texture_image *dstImage;
@@ -320,17 +306,14 @@ _mesa_meta_GenerateMipmap(struct gl_context *ctx, GLenum target,
       _mesa_texture_parameteriv(ctx, texObj, GL_TEXTURE_MAX_LEVEL,
                                 (GLint *) &dstLevel, false);
 
-      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(texObj, faceTarget, dstLevel);
 
+      /* All done.  We either ran out of memory or we would go beyond the last
+       * valid level of an immutable texture if we continued.
+       */
+      if (dstImage == NULL)
+         break;
+
       /* limit minification to src level */
       _mesa_texture_parameteriv(ctx, texObj, GL_TEXTURE_MAX_LEVEL,
                                 (GLint *) &srcLevel, false);