From 71ae69aea85ec8ddb9bf7baa93ae3926990a3693 Mon Sep 17 00:00:00 2001 From: Moonchild Date: Wed, 26 Oct 2022 13:52:42 +0000 Subject: [WebGL] Implement webgl.max-size-per-texture-mib --- dom/canvas/WebGLTextureUpload.cpp | 50 ++++++++++++++++++++++++++++----------- gfx/thebes/gfxPrefs.h | 1 + modules/libpref/init/all.js | 1 + 3 files changed, 38 insertions(+), 14 deletions(-) diff --git a/dom/canvas/WebGLTextureUpload.cpp b/dom/canvas/WebGLTextureUpload.cpp index ae60d2a2b0..ed199cfb43 100644 --- a/dom/canvas/WebGLTextureUpload.cpp +++ b/dom/canvas/WebGLTextureUpload.cpp @@ -303,13 +303,13 @@ WebGLContext::FromDomElem(const char* funcName, TexImageTarget target, uint32_t uint32_t height, uint32_t depth, const dom::Element& elem, ErrorResult* const out_error) { - if (elem.IsHTMLElement(nsGkAtoms::canvas)) { - const dom::HTMLCanvasElement* canvas = static_cast(&elem); - if (canvas->IsWriteOnly()) { - out_error->Throw(NS_ERROR_DOM_SECURITY_ERR); - return nullptr; - } - } + if (elem.IsHTMLElement(nsGkAtoms::canvas)) { + const dom::HTMLCanvasElement* canvas = static_cast(&elem); + if (canvas->IsWriteOnly()) { + out_error->Throw(NS_ERROR_DOM_SECURITY_ERR); + return nullptr; + } + } uint32_t flags = nsLayoutUtils::SFE_WANT_IMAGE_SURFACE | nsLayoutUtils::SFE_USE_ELEMENT_SIZE_IF_VECTOR; @@ -1032,9 +1032,27 @@ ValidateCompressedTexImageRestrictions(const char* funcName, WebGLContext* webgl } static bool -ValidateTargetForFormat(const char* funcName, WebGLContext* webgl, TexImageTarget target, - const webgl::FormatInfo* format) -{ +ValidateFormatAndSize(const char* funcName, + WebGLContext* webgl, + TexImageTarget target, + const webgl::FormatInfo* format, + const uint32_t width, + const uint32_t height, + const uint32_t depth) { + // Check if texture size will likely be rejected by the driver and give a more + // meaningful error message. + auto baseImageSize = CheckedInt(format->estimatedBytesPerPixel) * + width * height * depth; + if (target == LOCAL_GL_TEXTURE_CUBE_MAP) { + baseImageSize *= 6; + } + + if (!baseImageSize.isValid() || + baseImageSize.value() > (uint64_t)gfxPrefs::WebGLMaxSizePerTextureMB * (1024 * 1024)) { + webgl->ErrorOutOfMemory("Texture size too large; base image MB > webgl.max-size-per-texture-mb"); + return false; + } + // GLES 3.0.4 p127: // "Textures with a base internal format of DEPTH_COMPONENT or DEPTH_STENCIL are // supported by texture image specification commands only if `target` is TEXTURE_2D, @@ -1137,7 +1155,8 @@ WebGLTexture::TexStorage(const char* funcName, TexTarget target, GLsizei levels, } auto dstFormat = dstUsage->format; - if (!ValidateTargetForFormat(funcName, mContext, testTarget, dstFormat)) + if (!ValidateFormatAndSize(funcName, mContext, testTarget, dstFormat, + width, height, depth)) return; if (dstFormat->compression) { @@ -1264,7 +1283,8 @@ WebGLTexture::TexImage(const char* funcName, TexImageTarget target, GLint level, // Check that source and dest info are compatible auto dstFormat = dstUsage->format; - if (!ValidateTargetForFormat(funcName, mContext, target, dstFormat)) + if (!ValidateFormatAndSize(funcName, mContext, target, dstFormat, + blob->mWidth, blob->mHeight, blob->mDepth)) return; if (!mContext->IsWebGL2() && dstFormat->d) { @@ -1484,7 +1504,8 @@ WebGLTexture::CompressedTexImage(const char* funcName, TexImageTarget target, GL return; } - if (!ValidateTargetForFormat(funcName, mContext, target, format)) + if (!ValidateFormatAndSize(funcName, mContext, target, format, + blob->mWidth, blob->mHeight, blob->mDepth)) return; //////////////////////////////////// @@ -2143,7 +2164,8 @@ WebGLTexture::CopyTexImage2D(TexImageTarget target, GLint level, GLenum internal return; const auto& dstFormat = dstUsage->format; - if (!ValidateTargetForFormat(funcName, mContext, target, dstFormat)) + if (!ValidateFormatAndSize(funcName, mContext, target, dstFormat, + width, height, depth)) return; if (!mContext->IsWebGL2() && dstFormat->d) { diff --git a/gfx/thebes/gfxPrefs.h b/gfx/thebes/gfxPrefs.h index ac5bdd45a2..389393f8f6 100644 --- a/gfx/thebes/gfxPrefs.h +++ b/gfx/thebes/gfxPrefs.h @@ -591,6 +591,7 @@ private: DECL_GFX_PREF(Once, "webgl.force-layers-readback", WebGLForceLayersReadback, bool, false); DECL_GFX_PREF(Live, "webgl.lose-context-on-memory-pressure", WebGLLoseContextOnMemoryPressure, bool, false); DECL_GFX_PREF(Live, "webgl.max-warnings-per-context", WebGLMaxWarningsPerContext, uint32_t, 32); + DECL_GFX_PREF(Live, "webgl.max-size-per-texture-mb", WebGLMaxSizePerTextureMB, uint32_t, 1024); DECL_GFX_PREF(Live, "webgl.min_capability_mode", WebGLMinCapabilityMode, bool, false); DECL_GFX_PREF(Live, "webgl.msaa-force", WebGLForceMSAA, bool, false); DECL_GFX_PREF(Live, "webgl.prefer-16bpp", WebGLPrefer16bpp, bool, false); diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index 317de736b0..a237cfca57 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -4228,6 +4228,7 @@ pref("webgl.lose-context-on-memory-pressure", false); pref("webgl.can-lose-context-in-foreground", true); pref("webgl.restore-context-when-visible", true); pref("webgl.max-warnings-per-context", 32); +pref("webgl.max-size-per-texture-mb", 1024); pref("webgl.enable-draft-extensions", false); pref("webgl.enable-privileged-extensions", false); pref("webgl.bypass-shader-validation", false); -- cgit v1.2.3