mesa: add gl_coontext::ForceIntegerTexNearest
authorPierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com>
Mon, 20 Apr 2020 12:17:53 +0000 (14:17 +0200)
committerPierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com>
Tue, 5 May 2020 07:40:29 +0000 (09:40 +0200)
Some applications incorrectly use GL_LINEAR* values for integers texture.
copyimage.c already implemented a tolerance for such app in prepare_target_err.

This commit adds a boolean that will treat GL_LINEAR* filters as
GL_NEAREST for integer textures.

CC: 20.1 <mesa-stable@lists.freedesktop.org>
Reviewed-by: Timothy Arceri <tarceri@itsqueeze.com>
Reviewed-by: Marek Olšák <marek.olsak@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4647>

src/mesa/main/mtypes.h
src/mesa/main/texobj.h
src/mesa/main/texstate.c
src/mesa/main/texturebindless.c
src/mesa/state_tracker/st_atom_sampler.c
src/mesa/swrast/s_texfilter.c

index 7e31adcfaad7bedcf3d55b34d291e42bb206d16e..e334de0672dc53349b9d507181b508d48717b162 100644 (file)
@@ -3871,6 +3871,11 @@ struct gl_constants
     */
    GLboolean GLSLZeroInit;
 
+   /**
+    * Treat integer textures using GL_LINEAR filters as GL_NEAREST.
+    */
+   GLboolean ForceIntegerTexNearest;
+
    /**
     * Does the driver support real 32-bit integers?  (Otherwise, integers are
     * simulated via floats.)
index be8c6e4e6c2ceb4bc8efe1baef2313e05717e589..91901617c683e77c4fcde1fd2f6ab644d3da4a65 100644 (file)
@@ -122,7 +122,8 @@ _mesa_unlock_texture(struct gl_context *ctx, struct gl_texture_object *texObj)
 /** Is the texture "complete" with respect to the given sampler state? */
 static inline GLboolean
 _mesa_is_texture_complete(const struct gl_texture_object *texObj,
-                          const struct gl_sampler_object *sampler)
+                          const struct gl_sampler_object *sampler,
+                          bool linear_as_nearest_for_int_tex)
 {
    struct gl_texture_image *img = texObj->Image[0][texObj->BaseLevel];
    bool isMultisample = img && img->NumSamples >= 2;
@@ -149,8 +150,16 @@ _mesa_is_texture_complete(const struct gl_texture_object *texObj,
        (sampler->MagFilter != GL_NEAREST ||
         (sampler->MinFilter != GL_NEAREST &&
          sampler->MinFilter != GL_NEAREST_MIPMAP_NEAREST))) {
-      /* If the format is integer, only nearest filtering is allowed */
-      return GL_FALSE;
+      /* If the format is integer, only nearest filtering is allowed,
+       * but some applications (eg: Grid Autosport) uses the default
+       * filtering values.
+       */
+      if (texObj->_IsIntegerFormat &&
+          linear_as_nearest_for_int_tex) {
+         /* Skip return */
+      } else {
+         return GL_FALSE;
+      }
    }
 
    /* Section 8.17 (texture completeness) of the OpenGL 4.6 core profile spec:
index dfcfc4e8015f0d5d0e9a64aee3e72dcab0f3fdf6..f21f83edba5cad6ce3921f6fc9a7a68b4a7dcfcb 100644 (file)
@@ -670,11 +670,13 @@ update_single_program_texture(struct gl_context *ctx, struct gl_program *prog,
       texUnit->Sampler : &texObj->Sampler;
 
    if (likely(texObj)) {
-      if (_mesa_is_texture_complete(texObj, sampler))
+      if (_mesa_is_texture_complete(texObj, sampler,
+                                    ctx->Const.ForceIntegerTexNearest))
          return texObj;
 
       _mesa_test_texobj_completeness(ctx, texObj);
-      if (_mesa_is_texture_complete(texObj, sampler))
+      if (_mesa_is_texture_complete(texObj, sampler,
+                                    ctx->Const.ForceIntegerTexNearest))
          return texObj;
    }
 
@@ -816,10 +818,12 @@ update_ff_texture_state(struct gl_context *ctx,
          struct gl_sampler_object *sampler = texUnit->Sampler ?
             texUnit->Sampler : &texObj->Sampler;
 
-         if (!_mesa_is_texture_complete(texObj, sampler)) {
+         if (!_mesa_is_texture_complete(texObj, sampler,
+                                        ctx->Const.ForceIntegerTexNearest)) {
             _mesa_test_texobj_completeness(ctx, texObj);
          }
-         if (_mesa_is_texture_complete(texObj, sampler)) {
+         if (_mesa_is_texture_complete(texObj, sampler,
+                                       ctx->Const.ForceIntegerTexNearest)) {
             _mesa_reference_texobj(&texUnit->_Current, texObj);
             complete = true;
             break;
index c1cef4b1e4660ba87bca697b25f9385cb47d47c8..a4d700e6362e4909bbfcc45df8021973333e77b1 100644 (file)
@@ -546,7 +546,8 @@ _mesa_GetTextureHandleARB_no_error(GLuint texture)
    GET_CURRENT_CONTEXT(ctx);
 
    texObj = _mesa_lookup_texture(ctx, texture);
-   if (!_mesa_is_texture_complete(texObj, &texObj->Sampler))
+   if (!_mesa_is_texture_complete(texObj, &texObj->Sampler,
+                                  ctx->Const.ForceIntegerTexNearest))
       _mesa_test_texobj_completeness(ctx, texObj);
 
    return get_texture_handle(ctx, texObj, &texObj->Sampler);
@@ -585,9 +586,11 @@ _mesa_GetTextureHandleARB(GLuint texture)
     *  GetTextureSamplerHandleARB if the texture object specified by <texture>
     *  is not complete."
     */
-   if (!_mesa_is_texture_complete(texObj, &texObj->Sampler)) {
+   if (!_mesa_is_texture_complete(texObj, &texObj->Sampler,
+                                  ctx->Const.ForceIntegerTexNearest)) {
       _mesa_test_texobj_completeness(ctx, texObj);
-      if (!_mesa_is_texture_complete(texObj, &texObj->Sampler)) {
+      if (!_mesa_is_texture_complete(texObj, &texObj->Sampler,
+                                     ctx->Const.ForceIntegerTexNearest)) {
          _mesa_error(ctx, GL_INVALID_OPERATION,
                      "glGetTextureHandleARB(incomplete texture)");
          return 0;
@@ -614,7 +617,8 @@ _mesa_GetTextureSamplerHandleARB_no_error(GLuint texture, GLuint sampler)
    texObj = _mesa_lookup_texture(ctx, texture);
    sampObj = _mesa_lookup_samplerobj(ctx, sampler);
 
-   if (!_mesa_is_texture_complete(texObj, sampObj))
+   if (!_mesa_is_texture_complete(texObj, sampObj,
+                                  ctx->Const.ForceIntegerTexNearest))
       _mesa_test_texobj_completeness(ctx, texObj);
 
    return get_texture_handle(ctx, texObj, sampObj);
@@ -667,9 +671,11 @@ _mesa_GetTextureSamplerHandleARB(GLuint texture, GLuint sampler)
     *  GetTextureSamplerHandleARB if the texture object specified by <texture>
     *  is not complete."
     */
-   if (!_mesa_is_texture_complete(texObj, sampObj)) {
+   if (!_mesa_is_texture_complete(texObj, sampObj,
+                                  ctx->Const.ForceIntegerTexNearest)) {
       _mesa_test_texobj_completeness(ctx, texObj);
-      if (!_mesa_is_texture_complete(texObj, sampObj)) {
+      if (!_mesa_is_texture_complete(texObj, sampObj,
+                                     ctx->Const.ForceIntegerTexNearest)) {
          _mesa_error(ctx, GL_INVALID_OPERATION,
                      "glGetTextureSamplerHandleARB(incomplete texture)");
          return 0;
@@ -786,7 +792,8 @@ _mesa_GetImageHandleARB_no_error(GLuint texture, GLint level, GLboolean layered,
    GET_CURRENT_CONTEXT(ctx);
 
    texObj = _mesa_lookup_texture(ctx, texture);
-   if (!_mesa_is_texture_complete(texObj, &texObj->Sampler))
+   if (!_mesa_is_texture_complete(texObj, &texObj->Sampler,
+                                  ctx->Const.ForceIntegerTexNearest))
       _mesa_test_texobj_completeness(ctx, texObj);
 
    return get_image_handle(ctx, texObj, level, layered, layer, format);
@@ -845,9 +852,11 @@ _mesa_GetImageHandleARB(GLuint texture, GLint level, GLboolean layered,
     *  <texture> is not a three-dimensional, one-dimensional array, two
     *  dimensional array, cube map, or cube map array texture."
     */
-   if (!_mesa_is_texture_complete(texObj, &texObj->Sampler)) {
+   if (!_mesa_is_texture_complete(texObj, &texObj->Sampler,
+                                  ctx->Const.ForceIntegerTexNearest)) {
       _mesa_test_texobj_completeness(ctx, texObj);
-      if (!_mesa_is_texture_complete(texObj, &texObj->Sampler)) {
+      if (!_mesa_is_texture_complete(texObj, &texObj->Sampler,
+                                     ctx->Const.ForceIntegerTexNearest)) {
          _mesa_error(ctx, GL_INVALID_OPERATION,
                      "glGetImageHandleARB(incomplete texture)");
          return 0;
index b74d47b691fed88ca8f981942bd97bb42fb6aa8d..7ae981b71b4c7c37d69184f29564a006846a9d07 100644 (file)
@@ -114,9 +114,14 @@ st_convert_sampler(const struct st_context *st,
    sampler->wrap_t = gl_wrap_xlate(msamp->WrapT);
    sampler->wrap_r = gl_wrap_xlate(msamp->WrapR);
 
-   sampler->min_img_filter = gl_filter_to_img_filter(msamp->MinFilter);
+   if (texobj->_IsIntegerFormat && st->ctx->Const.ForceIntegerTexNearest) {
+      sampler->min_img_filter = gl_filter_to_img_filter(GL_NEAREST);
+      sampler->mag_img_filter = gl_filter_to_img_filter(GL_NEAREST);
+   } else {
+      sampler->min_img_filter = gl_filter_to_img_filter(msamp->MinFilter);
+      sampler->mag_img_filter = gl_filter_to_img_filter(msamp->MagFilter);
+   }
    sampler->min_mip_filter = gl_filter_to_mip_filter(msamp->MinFilter);
-   sampler->mag_img_filter = gl_filter_to_img_filter(msamp->MagFilter);
 
    if (texobj->Target != GL_TEXTURE_RECTANGLE_ARB)
       sampler->normalized_coords = 1;
index 7f1354785a4d9e783b0935ebe2f2ba8e8ca99c8d..381eb343812dc76056b59ac82b5e53c6a980c361 100644 (file)
@@ -3712,7 +3712,8 @@ _swrast_choose_texture_sample_func( struct gl_context *ctx,
                                    const struct gl_texture_object *t,
                                     const struct gl_sampler_object *sampler)
 {
-   if (!t || !_mesa_is_texture_complete(t, sampler)) {
+   if (!t || !_mesa_is_texture_complete(t, sampler,
+                                        ctx->Const.ForceIntegerTexNearest)) {
       return null_sample_func;
    }
    else {