mesa: add gl_coontext::ForceIntegerTexNearest
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>
This commit is contained in:
@@ -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.)
|
||||
|
@@ -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:
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
|
@@ -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 {
|
||||
|
Reference in New Issue
Block a user