GLuint
_mesa_meta_setup_sampler(struct gl_context *ctx,
                         const struct gl_texture_object *texObj,
                         GLenum target, GLenum filter, GLuint srcLevel)
{
   GLuint sampler;
   GLenum tex_filter = (filter == GL_SCALED_RESOLVE_FASTEST_EXT ||
                        filter == GL_SCALED_RESOLVE_NICEST_EXT) ?
                       GL_NEAREST : filter;

   _mesa_GenSamplers(1, &sampler);
   _mesa_BindSampler(ctx->Texture.CurrentUnit, sampler);

   /* Prepare src texture state */
   _mesa_BindTexture(target, texObj->Name);
   _mesa_SamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, tex_filter);
   _mesa_SamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, tex_filter);
   if (target != GL_TEXTURE_RECTANGLE_ARB) {
      _mesa_TexParameteri(target, GL_TEXTURE_BASE_LEVEL, srcLevel);
      _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, srcLevel);
   }
   _mesa_SamplerParameteri(sampler, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
   _mesa_SamplerParameteri(sampler, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

   return sampler;
}
void
_mesa_meta_fb_tex_blit_end(struct gl_context *ctx, GLenum target,
                           struct fb_tex_blit_state *blit)
{
   /* Restore texture object state, the texture binding will
    * be restored by _mesa_meta_end().
    */
   if (target != GL_TEXTURE_RECTANGLE_ARB) {
      _mesa_TexParameteri(target, GL_TEXTURE_BASE_LEVEL, blit->baseLevelSave);
      _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, blit->maxLevelSave);

      if (ctx->Extensions.ARB_stencil_texturing) {
         const struct gl_texture_object *texObj =
            _mesa_get_current_tex_object(ctx, target);

         if (texObj->StencilSampling != blit->stencilSamplingSave)
            _mesa_TexParameteri(target, GL_DEPTH_STENCIL_TEXTURE_MODE,
                                blit->stencilSamplingSave ?
                                   GL_STENCIL_INDEX : GL_DEPTH_COMPONENT);
      }
   }

   _mesa_BindSampler(ctx->Texture.CurrentUnit, blit->samplerSave);
   _mesa_DeleteSamplers(1, &blit->sampler);
   if (blit->tempTex)
      _mesa_DeleteTextures(1, &blit->tempTex);
}
/**
 * Called via ctx->Driver.GenerateMipmap()
 * Note: We don't yet support 3D textures, 1D/2D array textures or texture
 * borders.
 */
void
_mesa_meta_GenerateMipmap(struct gl_context *ctx, GLenum target,
                          struct gl_texture_object *texObj)
{
   struct gen_mipmap_state *mipmap = &ctx->Meta->Mipmap;
   struct vertex verts[4];
   const GLuint baseLevel = texObj->BaseLevel;
   const GLuint maxLevel = texObj->MaxLevel;
   const GLint maxLevelSave = texObj->MaxLevel;
   const GLboolean genMipmapSave = texObj->GenerateMipmap;
   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;
   GLuint samplerSave;
   GLint swizzle[4];
   GLboolean swizzleSaved = GL_FALSE;

   if (fallback_required(ctx, target, texObj)) {
      _mesa_generate_mipmap(ctx, target, texObj);
      return;
   }

   if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X &&
       target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z) {
      faceTarget = target;
      target = GL_TEXTURE_CUBE_MAP;
   } else {
      faceTarget = target;
   }

   _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, 4, 0);
      _mesa_meta_setup_blit_shader(ctx, target, false, &mipmap->shaders);
   } else {
      _mesa_meta_setup_ff_tnl_for_blit(&mipmap->VAO, &mipmap->VBO, 3);
      _mesa_set_enable(ctx, target, GL_TRUE);
   }

   samplerSave = ctx->Texture.Unit[ctx->Texture.CurrentUnit].Sampler ?
      ctx->Texture.Unit[ctx->Texture.CurrentUnit].Sampler->Name : 0;

   if (currentTexUnitSave != 0)
      _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);
      }
   } else {
      _mesa_BindSampler(ctx->Texture.CurrentUnit, mipmap->Sampler);
   }

   assert(mipmap->FBO != 0);
   _mesa_BindFramebuffer(GL_FRAMEBUFFER_EXT, mipmap->FBO);

   _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 vertex positions */
   verts[0].x = -1.0F;
   verts[0].y = -1.0F;
   verts[1].x =  1.0F;
   verts[1].y = -1.0F;
   verts[2].x =  1.0F;
   verts[2].y =  1.0F;
   verts[3].x = -1.0F;
   verts[3].y =  1.0F;

   /* 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;

      srcImage = _mesa_select_tex_image(texObj, faceTarget, srcLevel);
      assert(srcImage->Border == 0);

      /* src size */
      srcWidth = srcImage->Width;
      if (target == GL_TEXTURE_1D_ARRAY) {
         srcHeight = 1;
         srcDepth = srcImage->Height;
      } else {
         srcHeight = srcImage->Height;
         srcDepth = srcImage->Depth;
      }

      /* new dst size */
      dstWidth = minify(srcWidth, 1);
      dstHeight = minify(srcHeight, 1);
      dstDepth = target == GL_TEXTURE_3D ? minify(srcDepth, 1) : srcDepth;

      if (dstWidth == srcWidth &&
          dstHeight == srcHeight &&
          dstDepth == srcDepth) {
         /* all done */
         break;
      }

      /* 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);

      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);

      /* limit minification to src level */
      _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, srcLevel);

      /* setup viewport */
      _mesa_set_viewport(ctx, 0, 0, 0, dstWidth, dstHeight);
      _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 */

   _mesa_BindSampler(ctx->Texture.CurrentUnit, samplerSave);

   _mesa_meta_end(ctx);

   _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, maxLevelSave);
   if (genMipmapSave)
      _mesa_TexParameteri(target, GL_GENERATE_MIPMAP, genMipmapSave);
   if (swizzleSaved)
      _mesa_TexParameteriv(target, GL_TEXTURE_SWIZZLE_RGBA, swizzle);
}
Beispiel #4
0
static void
pop_texture_group(GLcontext *ctx, const struct gl_texture_attrib *texAttrib)
{
   GLuint u;

   for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
      const struct gl_texture_unit *unit = &texAttrib->Unit[u];
      GLuint i;

      _mesa_ActiveTextureARB(GL_TEXTURE0_ARB + u);
      _mesa_set_enable(ctx, GL_TEXTURE_1D,
              (GLboolean) (unit->Enabled & TEXTURE0_1D ? GL_TRUE : GL_FALSE));
      _mesa_set_enable(ctx, GL_TEXTURE_2D,
              (GLboolean) (unit->Enabled & TEXTURE0_2D ? GL_TRUE : GL_FALSE));
      _mesa_set_enable(ctx, GL_TEXTURE_3D,
              (GLboolean) (unit->Enabled & TEXTURE0_3D ? GL_TRUE : GL_FALSE));
      if (ctx->Extensions.ARB_texture_cube_map) {
         _mesa_set_enable(ctx, GL_TEXTURE_CUBE_MAP_ARB,
             (GLboolean) (unit->Enabled & TEXTURE0_CUBE ? GL_TRUE : GL_FALSE));
      }
      if (ctx->Extensions.NV_texture_rectangle) {
         _mesa_set_enable(ctx, GL_TEXTURE_RECTANGLE_NV,
             (GLboolean) (unit->Enabled & TEXTURE0_RECT ? GL_TRUE : GL_FALSE));
      }
      _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, unit->EnvMode);
      _mesa_TexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, unit->EnvColor);
      _mesa_TexGeni(GL_S, GL_TEXTURE_GEN_MODE, unit->GenModeS);
      _mesa_TexGeni(GL_T, GL_TEXTURE_GEN_MODE, unit->GenModeT);
      _mesa_TexGeni(GL_R, GL_TEXTURE_GEN_MODE, unit->GenModeR);
      _mesa_TexGeni(GL_Q, GL_TEXTURE_GEN_MODE, unit->GenModeQ);
      _mesa_TexGenfv(GL_S, GL_OBJECT_PLANE, unit->ObjectPlaneS);
      _mesa_TexGenfv(GL_T, GL_OBJECT_PLANE, unit->ObjectPlaneT);
      _mesa_TexGenfv(GL_R, GL_OBJECT_PLANE, unit->ObjectPlaneR);
      _mesa_TexGenfv(GL_Q, GL_OBJECT_PLANE, unit->ObjectPlaneQ);
      _mesa_TexGenfv(GL_S, GL_EYE_PLANE, unit->EyePlaneS);
      _mesa_TexGenfv(GL_T, GL_EYE_PLANE, unit->EyePlaneT);
      _mesa_TexGenfv(GL_R, GL_EYE_PLANE, unit->EyePlaneR);
      _mesa_TexGenfv(GL_Q, GL_EYE_PLANE, unit->EyePlaneQ);
      if (ctx->Extensions.EXT_texture_lod_bias) {
         _mesa_TexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
                       GL_TEXTURE_LOD_BIAS_EXT, unit->LodBias);
      }
      if (ctx->Extensions.EXT_texture_env_combine ||
          ctx->Extensions.ARB_texture_env_combine) {
         _mesa_TexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT,
                       unit->CombineModeRGB);
         _mesa_TexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT,
                       unit->CombineModeA);
         _mesa_TexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT,
                       unit->CombineSourceRGB[0]);
         _mesa_TexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT,
                       unit->CombineSourceRGB[1]);
         _mesa_TexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT,
                       unit->CombineSourceRGB[2]);
         _mesa_TexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT,
                       unit->CombineSourceA[0]);
         _mesa_TexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_EXT,
                       unit->CombineSourceA[1]);
         _mesa_TexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_EXT,
                       unit->CombineSourceA[2]);
         _mesa_TexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT,
                       unit->CombineOperandRGB[0]);
         _mesa_TexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT,
                       unit->CombineOperandRGB[1]);
         _mesa_TexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT,
                       unit->CombineOperandRGB[2]);
         _mesa_TexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT,
                       unit->CombineOperandA[0]);
         _mesa_TexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_EXT,
                       unit->CombineOperandA[1]);
         _mesa_TexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_EXT,
                       unit->CombineOperandA[2]);
         _mesa_TexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT,
                       1 << unit->CombineScaleShiftRGB);
         _mesa_TexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE,
                       1 << unit->CombineScaleShiftA);
      }

      /* Restore texture object state */
      for (i = 0; i < NUM_TEXTURE_TARGETS; i++) {
         GLenum target = 0;
         const struct gl_texture_object *obj = NULL;
         GLfloat bordColor[4];

         switch (i) {
         case 0:
            target = GL_TEXTURE_1D;
            obj = &unit->Saved1D;
            break;
         case 1:
            target = GL_TEXTURE_2D;
            obj = &unit->Saved2D;
            break;
         case 2:
            target = GL_TEXTURE_3D;
            obj = &unit->Saved3D;
            break;
         case 3:
            if (!ctx->Extensions.ARB_texture_cube_map)
               continue;
            target = GL_TEXTURE_CUBE_MAP_ARB;
            obj = &unit->SavedCubeMap;
            break;
         case 4:
            if (!ctx->Extensions.NV_texture_rectangle)
               continue;
            target = GL_TEXTURE_RECTANGLE_NV;
            obj = &unit->SavedRect;
            break;
         default:
            ; /* silence warnings */
         }

         _mesa_BindTexture(target, obj->Name);

         bordColor[0] = CHAN_TO_FLOAT(obj->BorderColor[0]);
         bordColor[1] = CHAN_TO_FLOAT(obj->BorderColor[1]);
         bordColor[2] = CHAN_TO_FLOAT(obj->BorderColor[2]);
         bordColor[3] = CHAN_TO_FLOAT(obj->BorderColor[3]);

         _mesa_TexParameterf(target, GL_TEXTURE_PRIORITY, obj->Priority);
         _mesa_TexParameterfv(target, GL_TEXTURE_BORDER_COLOR, bordColor);
         _mesa_TexParameteri(target, GL_TEXTURE_WRAP_S, obj->WrapS);
         _mesa_TexParameteri(target, GL_TEXTURE_WRAP_T, obj->WrapT);
         _mesa_TexParameteri(target, GL_TEXTURE_WRAP_R, obj->WrapR);
         _mesa_TexParameteri(target, GL_TEXTURE_MIN_FILTER, obj->MinFilter);
         _mesa_TexParameteri(target, GL_TEXTURE_MAG_FILTER, obj->MagFilter);
         _mesa_TexParameterf(target, GL_TEXTURE_MIN_LOD, obj->MinLod);
         _mesa_TexParameterf(target, GL_TEXTURE_MAX_LOD, obj->MaxLod);
         _mesa_TexParameteri(target, GL_TEXTURE_BASE_LEVEL, obj->BaseLevel);
         _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, obj->MaxLevel);
         if (ctx->Extensions.EXT_texture_filter_anisotropic) {
            _mesa_TexParameterf(target, GL_TEXTURE_MAX_ANISOTROPY_EXT,
                                obj->MaxAnisotropy);
         }
         if (ctx->Extensions.SGIX_shadow) {
            _mesa_TexParameteri(target, GL_TEXTURE_COMPARE_SGIX,
                                obj->CompareFlag);
            _mesa_TexParameteri(target, GL_TEXTURE_COMPARE_OPERATOR_SGIX,
                                obj->CompareOperator);
         }
         if (ctx->Extensions.SGIX_shadow_ambient) {
            _mesa_TexParameterf(target, GL_SHADOW_AMBIENT_SGIX,
                                CHAN_TO_FLOAT(obj->ShadowAmbient));
         }

      }
   }
   _mesa_ActiveTextureARB(GL_TEXTURE0_ARB
                          + texAttrib->CurrentUnit);

   /* "un-bump" the texture object reference counts.  We did that so they
    * wouldn't inadvertantly get deleted while they were still referenced
    * inside the attribute state stack.
    */
   for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
      ctx->Texture.Unit[u].Current1D->RefCount--;
      ctx->Texture.Unit[u].Current2D->RefCount--;
      ctx->Texture.Unit[u].Current3D->RefCount--;
      ctx->Texture.Unit[u].CurrentCubeMap->RefCount--;
      ctx->Texture.Unit[u].CurrentRect->RefCount--;
   }
}