Loading dom/canvas/WebGLTexture.cpp +49 −31 Original line number Diff line number Diff line Loading @@ -664,21 +664,12 @@ static bool ZeroTextureData(const WebGLContext* webgl, GLuint tex, } template <typename T, typename R> static R Clamp(const T val, const R min, const R max) { static constexpr R Clamp(const T val, const R min, const R max) { if (val < min) return min; if (val > max) return max; return static_cast<R>(val); } template <typename T, typename A, typename B> static void ClampSelf(T* const out, const A min, const B max) { if (*out < min) { *out = T{min}; } else if (*out > max) { *out = T{max}; } } void WebGLTexture::ClampLevelBaseAndMax() { if (!mImmutable) return; Loading @@ -687,8 +678,20 @@ void WebGLTexture::ClampLevelBaseAndMax() { // `[0, levels-1]`, `level_max` is then clamped to the range ` // `[level_base, levels-1]`, where `levels` is the parameter passed to // TexStorage* for the texture object." ClampSelf(&mBaseMipmapLevel, 0u, mImmutableLevelCount - 1u); ClampSelf(&mMaxMipmapLevel, mBaseMipmapLevel, mImmutableLevelCount - 1u); MOZ_ASSERT(mImmutableLevelCount > 0); const auto oldBase = mBaseMipmapLevel; const auto oldMax = mMaxMipmapLevel; mBaseMipmapLevel = Clamp(mBaseMipmapLevel, 0u, mImmutableLevelCount - 1u); mMaxMipmapLevel = Clamp(mMaxMipmapLevel, mBaseMipmapLevel, mImmutableLevelCount - 1u); if (oldBase != mBaseMipmapLevel && mBaseMipmapLevelState != MIPMAP_LEVEL_DEFAULT) { mBaseMipmapLevelState = MIPMAP_LEVEL_DIRTY; } if (oldMax != mMaxMipmapLevel && mMaxMipmapLevelState != MIPMAP_LEVEL_DEFAULT) { mMaxMipmapLevelState = MIPMAP_LEVEL_DIRTY; } // Note: This means that immutable textures are *always* texture-complete! } Loading Loading @@ -729,6 +732,10 @@ bool WebGLTexture::BindTexture(TexTarget texTarget) { return true; } static constexpr GLint ClampMipmapLevelForDriver(uint32_t level) { return Clamp(level, uint8_t{0}, WebGLTexture::kMaxLevelCount); } void WebGLTexture::GenerateMipmap() { // GLES 3.0.4 p160: // "Mipmap generation replaces texel array levels level base + 1 through q Loading Loading @@ -806,8 +813,21 @@ void WebGLTexture::GenerateMipmap() { gl::GLContext* gl = mContext->gl; if (gl->WorkAroundDriverBugs()) { // Don't generate mipmaps when the base level is out of range: if (!(mImmutable && mBaseMipmapLevel >= mImmutableLevelCount)) { // If we first set GL_TEXTURE_BASE_LEVEL to a number such as 20, then set // MGL_TEXTURE_MAX_LEVEL to a smaller number like 8, our copy of the // base level will be lowered, but we havn't yet updated the driver, we // should do so now, before calling glGenerateMipmap(). if (mBaseMipmapLevelState == MIPMAP_LEVEL_DIRTY) { gl->fTexParameteri(mTarget.get(), LOCAL_GL_TEXTURE_BASE_LEVEL, ClampMipmapLevelForDriver(mBaseMipmapLevel)); mBaseMipmapLevelState = MIPMAP_LEVEL_CLEAN; } if (mMaxMipmapLevelState == MIPMAP_LEVEL_DIRTY) { gl->fTexParameteri(mTarget.get(), LOCAL_GL_TEXTURE_MAX_LEVEL, ClampMipmapLevelForDriver(mMaxMipmapLevel)); mMaxMipmapLevelState = MIPMAP_LEVEL_CLEAN; } // bug 696495 - to work around failures in the texture-mips.html test on // various drivers, we set the minification filter before calling // glGenerateMipmap. This should not carry a significant performance Loading @@ -820,7 +840,6 @@ void WebGLTexture::GenerateMipmap() { gl->fGenerateMipmap(mTarget.get()); gl->fTexParameteri(mTarget.get(), LOCAL_GL_TEXTURE_MIN_FILTER, mSamplingState.minFilter.get()); } } else { gl->fGenerateMipmap(mTarget.get()); } Loading Loading @@ -1031,18 +1050,17 @@ void WebGLTexture::TexParameter(TexTarget texTarget, GLenum pname, switch (pname) { case LOCAL_GL_TEXTURE_BASE_LEVEL: { mBaseMipmapLevel = clamped.i; mBaseMipmapLevelState = MIPMAP_LEVEL_CLEAN; ClampLevelBaseAndMax(); const auto forDriver = Clamp(mBaseMipmapLevel, uint8_t{0}, kMaxLevelCount); clamped = FloatOrInt(forDriver); clamped = FloatOrInt(ClampMipmapLevelForDriver(mBaseMipmapLevel)); break; } case LOCAL_GL_TEXTURE_MAX_LEVEL: { mMaxMipmapLevel = clamped.i; mMaxMipmapLevelState = MIPMAP_LEVEL_CLEAN; ClampLevelBaseAndMax(); const auto forDriver = Clamp(mMaxMipmapLevel, uint8_t{0}, kMaxLevelCount); clamped = FloatOrInt(forDriver); clamped = FloatOrInt(ClampMipmapLevelForDriver(mMaxMipmapLevel)); break; } Loading dom/canvas/WebGLTexture.h +10 −0 Original line number Diff line number Diff line Loading @@ -120,6 +120,16 @@ class WebGLTexture final : public WebGLContextBoundObject, // You almost certainly don't want to query mMaxMipmapLevel. // You almost certainly want MaxEffectiveMipmapLevel(). // These "dirty" flags are set when the level is updated (eg indirectly by // clamping) and cleared when we tell the driver. enum MipmapLevelState : uint8_t { MIPMAP_LEVEL_DEFAULT, MIPMAP_LEVEL_CLEAN, MIPMAP_LEVEL_DIRTY }; MipmapLevelState mBaseMipmapLevelState = MIPMAP_LEVEL_DEFAULT; MipmapLevelState mMaxMipmapLevelState = MIPMAP_LEVEL_DEFAULT; webgl::SamplingState mSamplingState; mutable const GLint* mCurSwizzle = Loading Loading
dom/canvas/WebGLTexture.cpp +49 −31 Original line number Diff line number Diff line Loading @@ -664,21 +664,12 @@ static bool ZeroTextureData(const WebGLContext* webgl, GLuint tex, } template <typename T, typename R> static R Clamp(const T val, const R min, const R max) { static constexpr R Clamp(const T val, const R min, const R max) { if (val < min) return min; if (val > max) return max; return static_cast<R>(val); } template <typename T, typename A, typename B> static void ClampSelf(T* const out, const A min, const B max) { if (*out < min) { *out = T{min}; } else if (*out > max) { *out = T{max}; } } void WebGLTexture::ClampLevelBaseAndMax() { if (!mImmutable) return; Loading @@ -687,8 +678,20 @@ void WebGLTexture::ClampLevelBaseAndMax() { // `[0, levels-1]`, `level_max` is then clamped to the range ` // `[level_base, levels-1]`, where `levels` is the parameter passed to // TexStorage* for the texture object." ClampSelf(&mBaseMipmapLevel, 0u, mImmutableLevelCount - 1u); ClampSelf(&mMaxMipmapLevel, mBaseMipmapLevel, mImmutableLevelCount - 1u); MOZ_ASSERT(mImmutableLevelCount > 0); const auto oldBase = mBaseMipmapLevel; const auto oldMax = mMaxMipmapLevel; mBaseMipmapLevel = Clamp(mBaseMipmapLevel, 0u, mImmutableLevelCount - 1u); mMaxMipmapLevel = Clamp(mMaxMipmapLevel, mBaseMipmapLevel, mImmutableLevelCount - 1u); if (oldBase != mBaseMipmapLevel && mBaseMipmapLevelState != MIPMAP_LEVEL_DEFAULT) { mBaseMipmapLevelState = MIPMAP_LEVEL_DIRTY; } if (oldMax != mMaxMipmapLevel && mMaxMipmapLevelState != MIPMAP_LEVEL_DEFAULT) { mMaxMipmapLevelState = MIPMAP_LEVEL_DIRTY; } // Note: This means that immutable textures are *always* texture-complete! } Loading Loading @@ -729,6 +732,10 @@ bool WebGLTexture::BindTexture(TexTarget texTarget) { return true; } static constexpr GLint ClampMipmapLevelForDriver(uint32_t level) { return Clamp(level, uint8_t{0}, WebGLTexture::kMaxLevelCount); } void WebGLTexture::GenerateMipmap() { // GLES 3.0.4 p160: // "Mipmap generation replaces texel array levels level base + 1 through q Loading Loading @@ -806,8 +813,21 @@ void WebGLTexture::GenerateMipmap() { gl::GLContext* gl = mContext->gl; if (gl->WorkAroundDriverBugs()) { // Don't generate mipmaps when the base level is out of range: if (!(mImmutable && mBaseMipmapLevel >= mImmutableLevelCount)) { // If we first set GL_TEXTURE_BASE_LEVEL to a number such as 20, then set // MGL_TEXTURE_MAX_LEVEL to a smaller number like 8, our copy of the // base level will be lowered, but we havn't yet updated the driver, we // should do so now, before calling glGenerateMipmap(). if (mBaseMipmapLevelState == MIPMAP_LEVEL_DIRTY) { gl->fTexParameteri(mTarget.get(), LOCAL_GL_TEXTURE_BASE_LEVEL, ClampMipmapLevelForDriver(mBaseMipmapLevel)); mBaseMipmapLevelState = MIPMAP_LEVEL_CLEAN; } if (mMaxMipmapLevelState == MIPMAP_LEVEL_DIRTY) { gl->fTexParameteri(mTarget.get(), LOCAL_GL_TEXTURE_MAX_LEVEL, ClampMipmapLevelForDriver(mMaxMipmapLevel)); mMaxMipmapLevelState = MIPMAP_LEVEL_CLEAN; } // bug 696495 - to work around failures in the texture-mips.html test on // various drivers, we set the minification filter before calling // glGenerateMipmap. This should not carry a significant performance Loading @@ -820,7 +840,6 @@ void WebGLTexture::GenerateMipmap() { gl->fGenerateMipmap(mTarget.get()); gl->fTexParameteri(mTarget.get(), LOCAL_GL_TEXTURE_MIN_FILTER, mSamplingState.minFilter.get()); } } else { gl->fGenerateMipmap(mTarget.get()); } Loading Loading @@ -1031,18 +1050,17 @@ void WebGLTexture::TexParameter(TexTarget texTarget, GLenum pname, switch (pname) { case LOCAL_GL_TEXTURE_BASE_LEVEL: { mBaseMipmapLevel = clamped.i; mBaseMipmapLevelState = MIPMAP_LEVEL_CLEAN; ClampLevelBaseAndMax(); const auto forDriver = Clamp(mBaseMipmapLevel, uint8_t{0}, kMaxLevelCount); clamped = FloatOrInt(forDriver); clamped = FloatOrInt(ClampMipmapLevelForDriver(mBaseMipmapLevel)); break; } case LOCAL_GL_TEXTURE_MAX_LEVEL: { mMaxMipmapLevel = clamped.i; mMaxMipmapLevelState = MIPMAP_LEVEL_CLEAN; ClampLevelBaseAndMax(); const auto forDriver = Clamp(mMaxMipmapLevel, uint8_t{0}, kMaxLevelCount); clamped = FloatOrInt(forDriver); clamped = FloatOrInt(ClampMipmapLevelForDriver(mMaxMipmapLevel)); break; } Loading
dom/canvas/WebGLTexture.h +10 −0 Original line number Diff line number Diff line Loading @@ -120,6 +120,16 @@ class WebGLTexture final : public WebGLContextBoundObject, // You almost certainly don't want to query mMaxMipmapLevel. // You almost certainly want MaxEffectiveMipmapLevel(). // These "dirty" flags are set when the level is updated (eg indirectly by // clamping) and cleared when we tell the driver. enum MipmapLevelState : uint8_t { MIPMAP_LEVEL_DEFAULT, MIPMAP_LEVEL_CLEAN, MIPMAP_LEVEL_DIRTY }; MipmapLevelState mBaseMipmapLevelState = MIPMAP_LEVEL_DEFAULT; MipmapLevelState mMaxMipmapLevelState = MIPMAP_LEVEL_DEFAULT; webgl::SamplingState mSamplingState; mutable const GLint* mCurSwizzle = Loading