meta/generate_mipmap: Track framebuffer using gl_framebuffer instead of GL API object...
[mesa.git] / src / mesa / drivers / common / meta_generate_mipmap.c
index d38e6b889530ecdb33956d6ede5c927315ce418d..ffc26164235bbc9faafd3f5a3a843cc8272b84bb 100644 (file)
@@ -35,6 +35,7 @@
 #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,7 +57,6 @@ 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;
@@ -100,16 +100,18 @@ 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(GL_DRAW_FRAMEBUFFER, mipmap->FBO);
+   if (mipmap->fb == NULL) {
+      GLuint FBO;
 
-   _mesa_meta_bind_fbo_image(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, baseImage, 0);
-
-   status = _mesa_CheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);
+      _mesa_CreateFramebuffers(1, &FBO);
+      mipmap->fb = _mesa_lookup_framebuffer(ctx, FBO);
+      assert(mipmap->fb != NULL && mipmap->fb->Name == FBO);
+   }
 
-   _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, fboSave);
+   _mesa_meta_framebuffer_texture_image(ctx, mipmap->fb,
+                                        GL_COLOR_ATTACHMENT0, baseImage, 0);
 
+   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");
@@ -128,12 +130,11 @@ _mesa_meta_glsl_generate_mipmap_cleanup(struct gl_context *ctx,
    _mesa_DeleteVertexArrays(1, &mipmap->VAO);
    mipmap->VAO = 0;
    _mesa_reference_buffer_object(ctx, &mipmap->buf_obj, NULL);
-   _mesa_DeleteSamplers(1, &mipmap->Sampler);
-   mipmap->Sampler = 0;
+   _mesa_reference_sampler_object(ctx, &mipmap->samp_obj, NULL);
 
-   if (mipmap->FBO != 0) {
-      _mesa_DeleteFramebuffers(1, &mipmap->FBO);
-      mipmap->FBO = 0;
+   if (mipmap->fb != NULL) {
+      _mesa_DeleteFramebuffers(1, &mipmap->fb->Name);
+      mipmap->fb = NULL;
    }
 
    _mesa_meta_blit_shader_table_cleanup(&mipmap->shaders);
@@ -173,10 +174,16 @@ _mesa_meta_GenerateMipmap(struct gl_context *ctx, GLenum target,
                                       ctx->Extensions.ARB_fragment_shader;
    GLenum faceTarget;
    GLuint dstLevel;
-   GLuint samplerSave;
+   struct gl_sampler_object *samp_obj_save = NULL;
    GLint swizzle[4];
    GLboolean swizzleSaved = GL_FALSE;
 
+   /* GLint so the compiler won't complain about type signedness mismatch in
+    * the calls to _mesa_texture_parameteriv below.
+    */
+   static const GLint always_false = GL_FALSE;
+   static const GLint always_true = GL_TRUE;
+
    if (fallback_required(ctx, target, texObj)) {
       _mesa_generate_mipmap(ctx, target, texObj);
       return;
@@ -204,8 +211,8 @@ _mesa_meta_GenerateMipmap(struct gl_context *ctx, GLenum target,
       _mesa_set_enable(ctx, target, GL_TRUE);
    }
 
-   samplerSave = ctx->Texture.Unit[ctx->Texture.CurrentUnit].Sampler ?
-      ctx->Texture.Unit[ctx->Texture.CurrentUnit].Sampler->Name : 0;
+   _mesa_reference_sampler_object(ctx, &samp_obj_save,
+                                  ctx->Texture.Unit[ctx->Texture.CurrentUnit].Sampler);
 
    /* We may have been called from glGenerateTextureMipmap with CurrentUnit
     * still set to 0, so we don't know when we can skip binding the texture.
@@ -214,40 +221,40 @@ _mesa_meta_GenerateMipmap(struct gl_context *ctx, GLenum target,
     */
    _mesa_BindTexture(target, texObj->Name);
 
-   if (!mipmap->Sampler) {
-      _mesa_GenSamplers(1, &mipmap->Sampler);
-      _mesa_BindSampler(ctx->Texture.CurrentUnit, mipmap->Sampler);
-
-      _mesa_SamplerParameteri(mipmap->Sampler,
-                              GL_TEXTURE_MIN_FILTER,
-                              GL_LINEAR_MIPMAP_LINEAR);
-      _mesa_SamplerParameteri(mipmap->Sampler, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-      _mesa_SamplerParameteri(mipmap->Sampler, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-      _mesa_SamplerParameteri(mipmap->Sampler, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-      _mesa_SamplerParameteri(mipmap->Sampler, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
-
-      /* We don't want to encode or decode sRGB values; treat them as linear.
-       * This is not technically correct for GLES3 but we don't get any API
-       * error at the moment.
-       */
-      if (ctx->Extensions.EXT_texture_sRGB_decode) {
-         _mesa_SamplerParameteri(mipmap->Sampler, GL_TEXTURE_SRGB_DECODE_EXT,
-               GL_SKIP_DECODE_EXT);
+   if (mipmap->samp_obj == NULL) {
+      mipmap->samp_obj =  ctx->Driver.NewSamplerObject(ctx, 0xDEADBEEF);
+      if (mipmap->samp_obj == NULL) {
+         /* This is a bit lazy.  Flag out of memory, and then don't bother to
+          * clean up.  Once out of memory is flagged, the only realistic next
+          * move is to destroy the context.  That will trigger all the right
+          * clean up.
+          */
+         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenerateMipmap");
+         return;
       }
-   } else {
-      _mesa_BindSampler(ctx->Texture.CurrentUnit, mipmap->Sampler);
+
+      _mesa_set_sampler_filters(ctx, mipmap->samp_obj, GL_LINEAR_MIPMAP_LINEAR,
+                                GL_LINEAR);
+      _mesa_set_sampler_wrap(ctx, mipmap->samp_obj, GL_CLAMP_TO_EDGE,
+                             GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
+
+      /* 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);
    }
 
-   assert(mipmap->FBO != 0);
-   _mesa_BindFramebuffer(GL_FRAMEBUFFER_EXT, mipmap->FBO);
+   _mesa_bind_sampler(ctx, ctx->Texture.CurrentUnit, mipmap->samp_obj);
+
+   assert(mipmap->fb != NULL);
+   _mesa_bind_framebuffers(ctx, mipmap->fb, mipmap->fb);
 
-   _mesa_TexParameteri(target, GL_GENERATE_MIPMAP, GL_FALSE);
+   _mesa_texture_parameteriv(ctx, texObj, GL_GENERATE_MIPMAP, &always_false, 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);
+      _mesa_texture_parameteriv(ctx, texObj, GL_TEXTURE_SWIZZLE_RGBA,
+                                swizzleNoop, false);
    }
 
    /* Silence valgrind warnings about reading uninitialized stack. */
@@ -302,7 +309,8 @@ _mesa_meta_GenerateMipmap(struct gl_context *ctx, GLenum target,
       /* Allocate storage for the destination mipmap image(s) */
 
       /* Set MaxLevel large enough to hold the new level when we allocate it */
-      _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, dstLevel);
+      _mesa_texture_parameteriv(ctx, texObj, GL_TEXTURE_MAX_LEVEL,
+                                (GLint *) &dstLevel, false);
 
       if (!prepare_mipmap_level(ctx, texObj, dstLevel,
                                 dstWidth, dstHeight, dstDepth,
@@ -316,7 +324,8 @@ _mesa_meta_GenerateMipmap(struct gl_context *ctx, GLenum target,
       dstImage = _mesa_select_tex_image(texObj, faceTarget, dstLevel);
 
       /* limit minification to src level */
-      _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, srcLevel);
+      _mesa_texture_parameteriv(ctx, texObj, GL_TEXTURE_MAX_LEVEL,
+                                (GLint *) &srcLevel, false);
 
       /* setup viewport */
       _mesa_set_viewport(ctx, 0, 0, 0, dstWidth, dstHeight);
@@ -338,10 +347,12 @@ _mesa_meta_GenerateMipmap(struct gl_context *ctx, GLenum target,
          _mesa_buffer_data(ctx, mipmap->buf_obj, GL_NONE, sizeof(verts), verts,
                            GL_DYNAMIC_DRAW, __func__);
 
-         _mesa_meta_bind_fbo_image(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, dstImage, layer);
+         _mesa_meta_framebuffer_texture_image(ctx, ctx->DrawBuffer,
+                                              GL_COLOR_ATTACHMENT0, dstImage,
+                                              layer);
 
          /* sanity check */
-         if (_mesa_CheckFramebufferStatus(GL_FRAMEBUFFER) !=
+         if (_mesa_check_framebuffer_status(ctx, ctx->DrawBuffer) !=
              GL_FRAMEBUFFER_COMPLETE) {
             _mesa_problem(ctx, "Unexpected incomplete framebuffer in "
                           "_mesa_meta_GenerateMipmap()");
@@ -361,13 +372,17 @@ _mesa_meta_GenerateMipmap(struct gl_context *ctx, GLenum target,
 
    _mesa_lock_texture(ctx, texObj); /* relock */
 
-   _mesa_BindSampler(ctx->Texture.CurrentUnit, samplerSave);
+   _mesa_bind_sampler(ctx, ctx->Texture.CurrentUnit, samp_obj_save);
+   _mesa_reference_sampler_object(ctx, &samp_obj_save, NULL);
 
    _mesa_meta_end(ctx);
 
-   _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, maxLevelSave);
+   _mesa_texture_parameteriv(ctx, texObj, GL_TEXTURE_MAX_LEVEL, &maxLevelSave,
+                             false);
    if (genMipmapSave)
-      _mesa_TexParameteri(target, GL_GENERATE_MIPMAP, genMipmapSave);
+      _mesa_texture_parameteriv(ctx, texObj, GL_GENERATE_MIPMAP, &always_true,
+                                false);
    if (swizzleSaved)
-      _mesa_TexParameteriv(target, GL_TEXTURE_SWIZZLE_RGBA, swizzle);
+      _mesa_texture_parameteriv(ctx, texObj, GL_TEXTURE_SWIZZLE_RGBA, swizzle,
+                                false);
 }