diff --git a/extensions/CHROMIUM_texture_filtering_hint.txt b/extensions/CHROMIUM_texture_filtering_hint.txt new file mode 100644 index 000000000..38af6e010 --- /dev/null +++ b/extensions/CHROMIUM_texture_filtering_hint.txt @@ -0,0 +1,85 @@ +Name + + CHROMIUM_texture_filtering_hint + +Name Strings + + GL_CHROMIUM_texture_filtering_hint + +Contributors + + Alexis Hetu, Google Inc. + Nicolas Capens, Google Inc. + Shannon Woods, Google Inc. + +Contact + + Alexis Hetu, Google Inc. (sugoi 'at' chromium 'dot' org) + +Version + + Last Modifed Date: July 18, 2017 + +Dependencies + + This extension is written against the OpenGL ES 2.0 specification. + + OpenGL ES 2.0 is required. + +Overview + + This extension defines a way to request high precision texture filtering + using a new value to Hint. + + When this extension is enabled, TEXTURE_FILTERING_HINT_CHROMIUM can be used + by the implementation as a means to distinguish between a performance + focused implementation, using FASTEST, or a precision focused + implementation, using NICEST. + + Like other hints, either option is spec compliant and the behavior of + DONT_CARE is implementation specific. + +New Tokens + + Accepted by the parameter of GetIntegerv, GetFloatv and GetBooleanv + and by the parameter of Hint: + + TEXTURE_FILTERING_HINT_CHROMIUM 0x8AF0 + +New Procedures and Functions + + None. + +Errors + + None. + +New State + + None. + +Issues + + 1) When does the hint take effect? + + At the time of the next draw call, and all subsequent draw calls. + + 2) Does the first draw call after the filtering hint is changed use the + updated filtering method? + + Yes + + 3) Can I switch it back and forth between every draw call, multiple times + during a single frame? + + Yes + + 4) Do program objects which were created before the filtering hint was + changed and which contain sampling instructions use the filtering method + from when they were created, or the method at the time of draw call? + + At the time of draw call. + +Revision History + + 2/7/2014 Documented the extension diff --git a/src/OpenGL/libGLESv2/Context.cpp b/src/OpenGL/libGLESv2/Context.cpp index 2265aa6be..c1390689a 100644 --- a/src/OpenGL/libGLESv2/Context.cpp +++ b/src/OpenGL/libGLESv2/Context.cpp @@ -100,6 +100,7 @@ Context::Context(egl::Display *display, const Context *shareContext, EGLint clie mState.rasterizerDiscardEnabled = false; mState.generateMipmapHint = GL_DONT_CARE; mState.fragmentShaderDerivativeHint = GL_DONT_CARE; + mState.textureFilteringHint = GL_DONT_CARE; mState.lineWidth = 1.0f; @@ -682,6 +683,11 @@ void Context::setFragmentShaderDerivativeHint(GLenum hint) // Ignore for now. It is valid for implementations to ignore hint. } +void Context::setTextureFilteringHint(GLenum hint) +{ + mState.textureFilteringHint = hint; +} + void Context::setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height) { mState.viewportX = x; @@ -1890,6 +1896,7 @@ template bool Context::getIntegerv(GLenum pname, T *params) const case GL_UNPACK_ALIGNMENT: *params = mState.unpackInfo.alignment; return true; case GL_GENERATE_MIPMAP_HINT: *params = mState.generateMipmapHint; return true; case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES: *params = mState.fragmentShaderDerivativeHint; return true; + case GL_TEXTURE_FILTERING_HINT_CHROMIUM: *params = mState.textureFilteringHint; return true; case GL_ACTIVE_TEXTURE: *params = (mState.activeSampler + GL_TEXTURE0); return true; case GL_STENCIL_FUNC: *params = mState.stencilFunc; return true; case GL_STENCIL_REF: *params = mState.stencilRef; return true; @@ -2425,6 +2432,7 @@ bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *nu case GL_UNPACK_ALIGNMENT: case GL_GENERATE_MIPMAP_HINT: case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES: + case GL_TEXTURE_FILTERING_HINT_CHROMIUM: case GL_RED_BITS: case GL_GREEN_BITS: case GL_BLUE_BITS: @@ -3058,6 +3066,7 @@ void Context::applyTextures(sw::SamplerType samplerType) device->setTextureFilter(samplerType, samplerIndex, es2sw::ConvertTextureFilter(minFilter, magFilter, maxAnisotropy)); device->setMipmapFilter(samplerType, samplerIndex, es2sw::ConvertMipMapFilter(minFilter)); device->setMaxAnisotropy(samplerType, samplerIndex, maxAnisotropy); + device->setHighPrecisionFiltering(samplerType, samplerIndex, mState.textureFilteringHint == GL_NICEST); applyTexture(samplerType, samplerIndex, texture); } @@ -4324,6 +4333,7 @@ const GLubyte *Context::getExtensions(GLuint index, GLuint *numExt) const "GL_ANGLE_texture_compression_dxt3", "GL_ANGLE_texture_compression_dxt5", #endif + "GL_CHROMIUM_texture_filtering_hint", "GL_NV_fence", "GL_NV_framebuffer_blit", "GL_NV_read_depth", diff --git a/src/OpenGL/libGLESv2/Context.h b/src/OpenGL/libGLESv2/Context.h index bbe6ddd5c..16e0aa27f 100644 --- a/src/OpenGL/libGLESv2/Context.h +++ b/src/OpenGL/libGLESv2/Context.h @@ -156,6 +156,8 @@ const GLenum compressedTextureFormats[] = #endif }; +const GLenum GL_TEXTURE_FILTERING_HINT_CHROMIUM = 0x8AF0; + const GLint NUM_COMPRESSED_TEXTURE_FORMATS = sizeof(compressedTextureFormats) / sizeof(compressedTextureFormats[0]); const GLint multisampleCount[] = {4, 2, 1}; @@ -376,6 +378,7 @@ struct State GLenum generateMipmapHint; GLenum fragmentShaderDerivativeHint; + GLenum textureFilteringHint; GLint viewportX; GLint viewportY; @@ -489,6 +492,7 @@ public: void setGenerateMipmapHint(GLenum hint); void setFragmentShaderDerivativeHint(GLenum hint); + void setTextureFilteringHint(GLenum hint); void setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height); diff --git a/src/OpenGL/libGLESv2/libGLESv2.cpp b/src/OpenGL/libGLESv2/libGLESv2.cpp index 920e1a0bf..dfe595910 100644 --- a/src/OpenGL/libGLESv2/libGLESv2.cpp +++ b/src/OpenGL/libGLESv2/libGLESv2.cpp @@ -4247,6 +4247,9 @@ void Hint(GLenum target, GLenum mode) case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES: if(context) context->setFragmentShaderDerivativeHint(mode); break; + case GL_TEXTURE_FILTERING_HINT_CHROMIUM: + if(context) context->setTextureFilteringHint(mode); + break; default: return error(GL_INVALID_ENUM); } diff --git a/src/Renderer/PixelProcessor.cpp b/src/Renderer/PixelProcessor.cpp index 172e8efea..db11aeda7 100644 --- a/src/Renderer/PixelProcessor.cpp +++ b/src/Renderer/PixelProcessor.cpp @@ -444,6 +444,15 @@ namespace sw else ASSERT(false); } + void PixelProcessor::setHighPrecisionFiltering(unsigned int sampler, bool highPrecisionFiltering) + { + if(sampler < TEXTURE_IMAGE_UNITS) + { + context->sampler[sampler].setHighPrecisionFiltering(highPrecisionFiltering); + } + else ASSERT(false); + } + void PixelProcessor::setSwizzleR(unsigned int sampler, SwizzleType swizzleR) { if(sampler < TEXTURE_IMAGE_UNITS) diff --git a/src/Renderer/PixelProcessor.hpp b/src/Renderer/PixelProcessor.hpp index 94d52d39c..dd54b7215 100644 --- a/src/Renderer/PixelProcessor.hpp +++ b/src/Renderer/PixelProcessor.hpp @@ -231,6 +231,7 @@ namespace sw void setMipmapLOD(unsigned int sampler, float bias); void setBorderColor(unsigned int sampler, const Color &borderColor); void setMaxAnisotropy(unsigned int sampler, float maxAnisotropy); + void setHighPrecisionFiltering(unsigned int sampler, bool highPrecisionFiltering); void setSwizzleR(unsigned int sampler, SwizzleType swizzleR); void setSwizzleG(unsigned int sampler, SwizzleType swizzleG); void setSwizzleB(unsigned int sampler, SwizzleType swizzleB); diff --git a/src/Renderer/Renderer.cpp b/src/Renderer/Renderer.cpp index a84423df7..a67ba22ff 100644 --- a/src/Renderer/Renderer.cpp +++ b/src/Renderer/Renderer.cpp @@ -2314,6 +2314,18 @@ namespace sw } } + void Renderer::setHighPrecisionFiltering(SamplerType type, int sampler, bool highPrecisionFiltering) + { + if(type == SAMPLER_PIXEL) + { + PixelProcessor::setHighPrecisionFiltering(sampler, highPrecisionFiltering); + } + else + { + VertexProcessor::setHighPrecisionFiltering(sampler, highPrecisionFiltering); + } + } + void Renderer::setSwizzleR(SamplerType type, int sampler, SwizzleType swizzleR) { if(type == SAMPLER_PIXEL) diff --git a/src/Renderer/Renderer.hpp b/src/Renderer/Renderer.hpp index c59dd313f..c29020fa4 100644 --- a/src/Renderer/Renderer.hpp +++ b/src/Renderer/Renderer.hpp @@ -345,6 +345,7 @@ namespace sw void setMipmapLOD(SamplerType type, int sampler, float bias); void setBorderColor(SamplerType type, int sampler, const Color &borderColor); void setMaxAnisotropy(SamplerType type, int sampler, float maxAnisotropy); + void setHighPrecisionFiltering(SamplerType type, int sampler, bool highPrecisionFiltering); void setSwizzleR(SamplerType type, int sampler, SwizzleType swizzleR); void setSwizzleG(SamplerType type, int sampler, SwizzleType swizzleG); void setSwizzleB(SamplerType type, int sampler, SwizzleType swizzleB); diff --git a/src/Renderer/Sampler.cpp b/src/Renderer/Sampler.cpp index e2447e0e7..7d7d47c3a 100644 --- a/src/Renderer/Sampler.cpp +++ b/src/Renderer/Sampler.cpp @@ -60,6 +60,7 @@ namespace sw mipmapFilterState = MIPMAP_NONE; sRGB = false; gather = false; + highPrecisionFiltering = false; swizzleR = SWIZZLE_RED; swizzleG = SWIZZLE_GREEN; @@ -97,6 +98,7 @@ namespace sw state.swizzleG = swizzleG; state.swizzleB = swizzleB; state.swizzleA = swizzleA; + state.highPrecisionFiltering = highPrecisionFiltering; #if PERF_PROFILE state.compressedFormat = Surface::isCompressed(externalTextureFormat); @@ -298,6 +300,11 @@ namespace sw texture.maxAnisotropy = maxAnisotropy; } + void Sampler::setHighPrecisionFiltering(bool highPrecisionFiltering) + { + this->highPrecisionFiltering = highPrecisionFiltering; + } + void Sampler::setSwizzleR(SwizzleType swizzleR) { this->swizzleR = swizzleR; diff --git a/src/Renderer/Sampler.hpp b/src/Renderer/Sampler.hpp index 4c4973db5..288f179a2 100644 --- a/src/Renderer/Sampler.hpp +++ b/src/Renderer/Sampler.hpp @@ -140,6 +140,7 @@ namespace sw SwizzleType swizzleG : BITS(SWIZZLE_LAST); SwizzleType swizzleB : BITS(SWIZZLE_LAST); SwizzleType swizzleA : BITS(SWIZZLE_LAST); + bool highPrecisionFiltering : 1; #if PERF_PROFILE bool compressedFormat : 1; @@ -163,6 +164,7 @@ namespace sw void setReadSRGB(bool sRGB); void setBorderColor(const Color &borderColor); void setMaxAnisotropy(float maxAnisotropy); + void setHighPrecisionFiltering(bool highPrecisionFiltering); void setSwizzleR(SwizzleType swizzleR); void setSwizzleG(SwizzleType swizzleG); void setSwizzleB(SwizzleType swizzleB); @@ -202,6 +204,7 @@ namespace sw MipmapType mipmapFilterState; bool sRGB; bool gather; + bool highPrecisionFiltering; SwizzleType swizzleR; SwizzleType swizzleG; diff --git a/src/Renderer/VertexProcessor.cpp b/src/Renderer/VertexProcessor.cpp index 91c4d3467..6972d94ce 100644 --- a/src/Renderer/VertexProcessor.cpp +++ b/src/Renderer/VertexProcessor.cpp @@ -602,6 +602,15 @@ namespace sw else ASSERT(false); } + void VertexProcessor::setHighPrecisionFiltering(unsigned int sampler, bool highPrecisionFiltering) + { + if(sampler < TEXTURE_IMAGE_UNITS) + { + context->sampler[sampler].setHighPrecisionFiltering(highPrecisionFiltering); + } + else ASSERT(false); + } + void VertexProcessor::setSwizzleR(unsigned int sampler, SwizzleType swizzleR) { if(sampler < VERTEX_TEXTURE_IMAGE_UNITS) diff --git a/src/Renderer/VertexProcessor.hpp b/src/Renderer/VertexProcessor.hpp index 278c9b179..3552f847d 100644 --- a/src/Renderer/VertexProcessor.hpp +++ b/src/Renderer/VertexProcessor.hpp @@ -258,6 +258,7 @@ namespace sw void setMipmapLOD(unsigned int sampler, float bias); void setBorderColor(unsigned int sampler, const Color &borderColor); void setMaxAnisotropy(unsigned int stage, float maxAnisotropy); + void setHighPrecisionFiltering(unsigned int sampler, bool highPrecisionFiltering); void setSwizzleR(unsigned int sampler, SwizzleType swizzleR); void setSwizzleG(unsigned int sampler, SwizzleType swizzleG); void setSwizzleB(unsigned int sampler, SwizzleType swizzleB); diff --git a/src/Shader/SamplerCore.cpp b/src/Shader/SamplerCore.cpp index 8c20f5812..9bd977e93 100644 --- a/src/Shader/SamplerCore.cpp +++ b/src/Shader/SamplerCore.cpp @@ -314,7 +314,7 @@ namespace sw } else { - if(hasFloatTexture()) // FIXME: Mostly identical to integer sampling + if(hasFloatTexture() || state.highPrecisionFiltering) // FIXME: Mostly identical to integer sampling { Float4 uuuu = u; Float4 vvvv = v;