WebKit Bugzilla
New
Browse
Search+
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
[patch]
Patch
bug-217198-20201006153519.patch (text/plain), 85.76 KB, created by
James Darpinian
on 2020-10-06 15:35:20 PDT
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
James Darpinian
Created:
2020-10-06 15:35:20 PDT
Size:
85.76 KB
patch
obsolete
>Subversion Revision: 267889 >diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog >index 79b60fe61062325883c60e723ab45d1af29e9240..ba0cd8f726069d081273ac1b30c580bcbfde71af 100644 >--- a/Source/WebCore/ChangeLog >+++ b/Source/WebCore/ChangeLog >@@ -1,3 +1,39 @@ >+2020-10-06 James Darpinian <jdarpinian@chromium.org> >+ >+ Support EXT_texture_compression_rgtc WebGL extension >+ https://bugs.webkit.org/show_bug.cgi?id=217198 >+ >+ Reviewed by Kenneth Russell. >+ >+ Test: webgl/conformance/extensions/ext-texture-compression-rgtc.html >+ >+ * CMakeLists.txt: >+ * DerivedSources-input.xcfilelist: >+ * DerivedSources-output.xcfilelist: >+ * DerivedSources.make: >+ * Sources.txt: >+ * WebCore.xcodeproj/project.pbxproj: >+ * bindings/js/JSDOMConvertWebGL.cpp: >+ (WebCore::convertToJSValue): >+ * html/canvas/EXTTextureCompressionRGTC.cpp: Added. >+ (WebCore::EXTTextureCompressionRGTC::EXTTextureCompressionRGTC): >+ (WebCore::EXTTextureCompressionRGTC::getName const): >+ * html/canvas/EXTTextureCompressionRGTC.h: Added. >+ * html/canvas/EXTTextureCompressionRGTC.idl: Added. >+ * html/canvas/WebGL2RenderingContext.cpp: >+ (WebCore::WebGL2RenderingContext::getExtension): >+ (WebCore::WebGL2RenderingContext::getSupportedExtensions): >+ * html/canvas/WebGLExtension.h: >+ * html/canvas/WebGLRenderingContext.cpp: >+ (WebCore::WebGLRenderingContext::getExtension): >+ (WebCore::WebGLRenderingContext::getSupportedExtensions): >+ * html/canvas/WebGLRenderingContextBase.cpp: >+ (WebCore::WebGLRenderingContextBase::extensionIsEnabled): >+ (WebCore::WebGLRenderingContextBase::validateCompressedTexFuncData): >+ (WebCore::WebGLRenderingContextBase::loseExtensions): >+ * html/canvas/WebGLRenderingContextBase.h: >+ * platform/graphics/ExtensionsGL.h: >+ > 2020-09-30 Antoine Quint <graouts@webkit.org> > > Add non-animated support for the CSS translate property >diff --git a/Source/WebCore/CMakeLists.txt b/Source/WebCore/CMakeLists.txt >index 19438023c4358b0606103c65c47d589f7ee5c34c..94ab598143c1bb28ff2dea0a027dda754c5efc11 100644 >--- a/Source/WebCore/CMakeLists.txt >+++ b/Source/WebCore/CMakeLists.txt >@@ -1448,6 +1448,7 @@ if (ENABLE_WEBGL) > html/canvas/EXTFloatBlend.cpp > html/canvas/EXTFragDepth.cpp > html/canvas/EXTShaderTextureLOD.cpp >+ html/canvas/EXTTextureCompressionRGTC.cpp > html/canvas/EXTTextureFilterAnisotropic.cpp > html/canvas/EXTsRGB.cpp > html/canvas/OESElementIndexUint.cpp >@@ -1506,6 +1507,7 @@ list(APPEND WebCore_IDL_FILES > html/canvas/EXTFloatBlend.idl > html/canvas/EXTFragDepth.idl > html/canvas/EXTShaderTextureLOD.idl >+ html/canvas/EXTTextureCompressionRGTC.idl > html/canvas/EXTTextureFilterAnisotropic.idl > html/canvas/EXTsRGB.idl > html/canvas/OESElementIndexUint.idl >diff --git a/Source/WebCore/DerivedSources-input.xcfilelist b/Source/WebCore/DerivedSources-input.xcfilelist >index a8dcf96982a408299745825834b7160b45d27f5f..0685c5a294dd60521a105ca0e565670a58efc17f 100644 >--- a/Source/WebCore/DerivedSources-input.xcfilelist >+++ b/Source/WebCore/DerivedSources-input.xcfilelist >@@ -932,6 +932,7 @@ $(PROJECT_DIR)/html/canvas/EXTColorBufferHalfFloat.idl > $(PROJECT_DIR)/html/canvas/EXTFloatBlend.idl > $(PROJECT_DIR)/html/canvas/EXTFragDepth.idl > $(PROJECT_DIR)/html/canvas/EXTShaderTextureLOD.idl >+$(PROJECT_DIR)/html/canvas/EXTTextureCompressionRGTC.idl > $(PROJECT_DIR)/html/canvas/EXTTextureFilterAnisotropic.idl > $(PROJECT_DIR)/html/canvas/EXTsRGB.idl > $(PROJECT_DIR)/html/canvas/ImageBitmapRenderingContext.idl >diff --git a/Source/WebCore/DerivedSources-output.xcfilelist b/Source/WebCore/DerivedSources-output.xcfilelist >index 36795ea41338edda84ad2834f688ded3204de0d8..779900f8c2473b41ef9ddd4d4f82b030c7904774 100644 >--- a/Source/WebCore/DerivedSources-output.xcfilelist >+++ b/Source/WebCore/DerivedSources-output.xcfilelist >@@ -671,6 +671,8 @@ $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSEXTFragDepth.cpp > $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSEXTFragDepth.h > $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSEXTShaderTextureLOD.cpp > $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSEXTShaderTextureLOD.h >+$(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSEXTTextureCompressionRGTC.cpp >+$(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSEXTTextureCompressionRGTC.h > $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSEXTTextureFilterAnisotropic.cpp > $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSEXTTextureFilterAnisotropic.h > $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSEXTsRGB.cpp >diff --git a/Source/WebCore/DerivedSources.make b/Source/WebCore/DerivedSources.make >index 2c1c1089ad5ab6b759f506dc1ae903cff20606f6..f4cec86462c32d0bd9e7a6a89d454df721d61ee3 100644 >--- a/Source/WebCore/DerivedSources.make >+++ b/Source/WebCore/DerivedSources.make >@@ -951,6 +951,7 @@ JS_BINDING_IDLS = \ > $(WebCore)/html/canvas/EXTFloatBlend.idl \ > $(WebCore)/html/canvas/EXTFragDepth.idl \ > $(WebCore)/html/canvas/EXTShaderTextureLOD.idl \ >+ $(WebCore)/html/canvas/EXTTextureCompressionRGTC.idl \ > $(WebCore)/html/canvas/EXTTextureFilterAnisotropic.idl \ > $(WebCore)/html/canvas/EXTsRGB.idl \ > $(WebCore)/html/canvas/ImageBitmapRenderingContext.idl \ >diff --git a/Source/WebCore/Sources.txt b/Source/WebCore/Sources.txt >index c7ecfdd155c5280d5854bfb52bebea0284adb7a3..6d3a3e51003c41444df6c151edde6e487a25c771 100644 >--- a/Source/WebCore/Sources.txt >+++ b/Source/WebCore/Sources.txt >@@ -1255,6 +1255,7 @@ html/canvas/EXTColorBufferHalfFloat.cpp > html/canvas/EXTFloatBlend.cpp > html/canvas/EXTFragDepth.cpp > html/canvas/EXTShaderTextureLOD.cpp >+html/canvas/EXTTextureCompressionRGTC.cpp > html/canvas/EXTTextureFilterAnisotropic.cpp > html/canvas/EXTsRGB.cpp > html/canvas/GPUBasedCanvasRenderingContext.cpp >@@ -2863,6 +2864,7 @@ JSEXTColorBufferHalfFloat.cpp > JSEXTFloatBlend.cpp > JSEXTFragDepth.cpp > JSEXTShaderTextureLOD.cpp >+JSEXTTextureCompressionRGTC.cpp > JSEXTTextureFilterAnisotropic.cpp > JSEXTsRGB.cpp > JSEcKeyParams.cpp >diff --git a/Source/WebCore/WebCore.xcodeproj/project.pbxproj b/Source/WebCore/WebCore.xcodeproj/project.pbxproj >index ca00f9e0a26bf21a8bcc9ff551022f74798120dd..1b8f1b3cb6fbc062aa74e7ffcb832d50887038c1 100644 >--- a/Source/WebCore/WebCore.xcodeproj/project.pbxproj >+++ b/Source/WebCore/WebCore.xcodeproj/project.pbxproj >@@ -12113,6 +12113,9 @@ > A37A42CE251EB99600F75AFF /* OESFBORenderMipmap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OESFBORenderMipmap.cpp; sourceTree = "<group>"; }; > A37A42D0251EB99600F75AFF /* OESFBORenderMipmap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OESFBORenderMipmap.h; sourceTree = "<group>"; }; > A37A42D1251EB99700F75AFF /* OESFBORenderMipmap.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = OESFBORenderMipmap.idl; sourceTree = "<group>"; }; >+ A37A42E02527B49C00F75AFF /* EXTTextureCompressionRGTC.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = EXTTextureCompressionRGTC.cpp; sourceTree = "<group>"; }; >+ A37A42E22527B49D00F75AFF /* EXTTextureCompressionRGTC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EXTTextureCompressionRGTC.h; sourceTree = "<group>"; }; >+ A37A42E32527B49E00F75AFF /* EXTTextureCompressionRGTC.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = EXTTextureCompressionRGTC.idl; sourceTree = "<group>"; }; > A3AF9D81203252EE006CAD06 /* UserAgentCocoa.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = UserAgentCocoa.mm; sourceTree = "<group>"; }; > A3AF9D8220325324006CAD06 /* UserAgent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UserAgent.h; sourceTree = "<group>"; }; > A3AF9D8320325691006CAD06 /* UserAgentIOS.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = UserAgentIOS.mm; sourceTree = "<group>"; }; >@@ -19393,6 +19396,9 @@ > 727AFED11A2EA6A0000442E8 /* EXTsRGB.cpp */, > 727AFED21A2EA6A0000442E8 /* EXTsRGB.h */, > 727AFED31A2EA6A0000442E8 /* EXTsRGB.idl */, >+ A37A42E02527B49C00F75AFF /* EXTTextureCompressionRGTC.cpp */, >+ A37A42E22527B49D00F75AFF /* EXTTextureCompressionRGTC.h */, >+ A37A42E32527B49E00F75AFF /* EXTTextureCompressionRGTC.idl */, > 7728694B14F8882500F484DC /* EXTTextureFilterAnisotropic.cpp */, > 7728694C14F8882500F484DC /* EXTTextureFilterAnisotropic.h */, > 7728694D14F8882500F484DC /* EXTTextureFilterAnisotropic.idl */, >diff --git a/Source/WebCore/bindings/js/JSDOMConvertWebGL.cpp b/Source/WebCore/bindings/js/JSDOMConvertWebGL.cpp >index d470d008a49d40a3e7abcba4e26e453647af301e..3d3066311046a7607041299d13e8af755fa264be 100644 >--- a/Source/WebCore/bindings/js/JSDOMConvertWebGL.cpp >+++ b/Source/WebCore/bindings/js/JSDOMConvertWebGL.cpp >@@ -36,6 +36,7 @@ > #include "JSEXTFloatBlend.h" > #include "JSEXTFragDepth.h" > #include "JSEXTShaderTextureLOD.h" >+#include "JSEXTTextureCompressionRGTC.h" > #include "JSEXTTextureFilterAnisotropic.h" > #include "JSEXTsRGB.h" > #include "JSOESElementIndexUint.h" >@@ -171,6 +172,8 @@ JSValue convertToJSValue(JSGlobalObject& lexicalGlobalObject, JSDOMGlobalObject& > return toJS(&lexicalGlobalObject, &globalObject, static_cast<WebGLLoseContext&>(extension)); > case WebGLExtension::EXTShaderTextureLODName: > return toJS(&lexicalGlobalObject, &globalObject, static_cast<EXTShaderTextureLOD&>(extension)); >+ case WebGLExtension::EXTTextureCompressionRGTCName: >+ return toJS(&lexicalGlobalObject, &globalObject, static_cast<EXTTextureCompressionRGTC&>(extension)); > case WebGLExtension::EXTTextureFilterAnisotropicName: > return toJS(&lexicalGlobalObject, &globalObject, static_cast<EXTTextureFilterAnisotropic&>(extension)); > case WebGLExtension::EXTsRGBName: >diff --git a/Source/WebCore/html/canvas/EXTTextureCompressionRGTC.cpp b/Source/WebCore/html/canvas/EXTTextureCompressionRGTC.cpp >new file mode 100644 >index 0000000000000000000000000000000000000000..0a9b57868639146ee2d1b32aa2185c6a569e48ea >--- /dev/null >+++ b/Source/WebCore/html/canvas/EXTTextureCompressionRGTC.cpp >@@ -0,0 +1,57 @@ >+/* >+ * Copyright (C) 2020 Google Inc. All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * >+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY >+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED >+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE >+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY >+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES >+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; >+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND >+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT >+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF >+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. >+ */ >+ >+#include "config.h" >+ >+#if ENABLE(WEBGL) >+#include "EXTTextureCompressionRGTC.h" >+ >+#include <wtf/IsoMallocInlines.h> >+ >+namespace WebCore { >+ >+WTF_MAKE_ISO_ALLOCATED_IMPL(EXTTextureCompressionRGTC); >+ >+EXTTextureCompressionRGTC::EXTTextureCompressionRGTC(WebGLRenderingContextBase& context) >+ : WebGLExtension(context) >+{ >+ context.graphicsContextGL()->getExtensions().ensureEnabled("GL_EXT_texture_compression_rgtc"); >+ >+ context.addCompressedTextureFormat(ExtensionsGL::COMPRESSED_RED_RGTC1_EXT); >+ context.addCompressedTextureFormat(ExtensionsGL::COMPRESSED_SIGNED_RED_RGTC1_EXT); >+ context.addCompressedTextureFormat(ExtensionsGL::COMPRESSED_RED_GREEN_RGTC2_EXT); >+ context.addCompressedTextureFormat(ExtensionsGL::COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT); >+} >+ >+EXTTextureCompressionRGTC::~EXTTextureCompressionRGTC() = default; >+ >+WebGLExtension::ExtensionName EXTTextureCompressionRGTC::getName() const >+{ >+ return EXTTextureCompressionRGTCName; >+} >+ >+} // namespace WebCore >+ >+#endif // ENABLE(WEBGL) >diff --git a/Source/WebCore/html/canvas/EXTTextureCompressionRGTC.h b/Source/WebCore/html/canvas/EXTTextureCompressionRGTC.h >new file mode 100644 >index 0000000000000000000000000000000000000000..1883d93bca1b18d3717efec9e4357c4c48bbe2c4 >--- /dev/null >+++ b/Source/WebCore/html/canvas/EXTTextureCompressionRGTC.h >@@ -0,0 +1,41 @@ >+/* >+ * Copyright (C) 2020 Google Inc. All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * >+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY >+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED >+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE >+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY >+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES >+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; >+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND >+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT >+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF >+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. >+ */ >+ >+#pragma once >+ >+#include "WebGLExtension.h" >+ >+namespace WebCore { >+ >+class EXTTextureCompressionRGTC final : public WebGLExtension { >+ WTF_MAKE_ISO_ALLOCATED(EXTTextureCompressionRGTC); >+public: >+ explicit EXTTextureCompressionRGTC(WebGLRenderingContextBase&); >+ virtual ~EXTTextureCompressionRGTC(); >+ >+ ExtensionName getName() const override; >+}; >+ >+} // namespace WebCore >diff --git a/Source/WebCore/html/canvas/EXTTextureCompressionRGTC.idl b/Source/WebCore/html/canvas/EXTTextureCompressionRGTC.idl >new file mode 100644 >index 0000000000000000000000000000000000000000..dcf96035f6b9248cf01795b188074b757562d562 >--- /dev/null >+++ b/Source/WebCore/html/canvas/EXTTextureCompressionRGTC.idl >@@ -0,0 +1,35 @@ >+/* >+ * Copyright (C) 2020 Google Inc. All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * >+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY >+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED >+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE >+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY >+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES >+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; >+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND >+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT >+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF >+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. >+ */ >+ >+[ >+ Conditional=WEBGL, >+ GenerateIsReachable=ImplWebGLRenderingContext, >+ LegacyNoInterfaceObject, >+] interface EXTTextureCompressionRGTC { >+ const unsigned long COMPRESSED_RED_RGTC1_EXT = 0x8DBB; >+ const unsigned long COMPRESSED_SIGNED_RED_RGTC1_EXT = 0x8DBC; >+ const unsigned long COMPRESSED_RED_GREEN_RGTC2_EXT = 0x8DBD; >+ const unsigned long COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT = 0x8DBE; >+}; >diff --git a/Source/WebCore/html/canvas/WebGL2RenderingContext.cpp b/Source/WebCore/html/canvas/WebGL2RenderingContext.cpp >index 7d4b58fde505b27280be30e4a808c4ab2a353f8f..b5fcf93d872aae35cc8cb686c8694a5fe6ae33b9 100644 >--- a/Source/WebCore/html/canvas/WebGL2RenderingContext.cpp >+++ b/Source/WebCore/html/canvas/WebGL2RenderingContext.cpp >@@ -32,6 +32,7 @@ > #include "EXTColorBufferFloat.h" > #include "EXTColorBufferHalfFloat.h" > #include "EXTFloatBlend.h" >+#include "EXTTextureCompressionRGTC.h" > #include "EXTTextureFilterAnisotropic.h" > #include "EventLoop.h" > #include "ExtensionsGL.h" >@@ -2671,6 +2672,7 @@ WebGLExtension* WebGL2RenderingContext::getExtension(const String& name) > return variable.get(); \ > } > >+ ENABLE_IF_REQUESTED(EXTTextureCompressionRGTC, m_extTextureCompressionRGTC, "EXT_texture_compression_rgtc", enableSupportedExtension("GL_EXT_texture_compression_rgtc"_s)); > ENABLE_IF_REQUESTED(EXTTextureFilterAnisotropic, m_extTextureFilterAnisotropic, "EXT_texture_filter_anisotropic", enableSupportedExtension("GL_EXT_texture_filter_anisotropic"_s)); > ENABLE_IF_REQUESTED(OESTextureFloatLinear, m_oesTextureFloatLinear, "OES_texture_float_linear", enableSupportedExtension("GL_OES_texture_float_linear"_s)); > ENABLE_IF_REQUESTED(WebGLLoseContext, m_webglLoseContext, "WEBGL_lose_context", true); >@@ -2703,6 +2705,8 @@ Optional<Vector<String>> WebGL2RenderingContext::getSupportedExtensions() > auto& extensions = m_context->getExtensions(); > if (extensions.supports("GL_OES_texture_float_linear"_s)) > result.append("OES_texture_float_linear"_s); >+ if (extensions.supports("GL_EXT_texture_compression_rgtc"_s)) >+ result.append("EXT_texture_compression_rgtc"_s); > if (extensions.supports("GL_EXT_texture_filter_anisotropic"_s)) > result.append("EXT_texture_filter_anisotropic"_s); > if (WebGLCompressedTextureASTC::supported(*this)) >diff --git a/Source/WebCore/html/canvas/WebGLExtension.h b/Source/WebCore/html/canvas/WebGLExtension.h >index a78ef15b3912260d1a04fb04b29cc21f091334d1..440d4b95479433cffe19b2ae6145ad09985b6bd7 100644 >--- a/Source/WebCore/html/canvas/WebGLExtension.h >+++ b/Source/WebCore/html/canvas/WebGLExtension.h >@@ -41,6 +41,7 @@ public: > EXTBlendMinMaxName, > EXTFragDepthName, > EXTShaderTextureLODName, >+ EXTTextureCompressionRGTCName, > EXTTextureFilterAnisotropicName, > EXTsRGBName, > OESTextureFloatName, >diff --git a/Source/WebCore/html/canvas/WebGLRenderingContext.cpp b/Source/WebCore/html/canvas/WebGLRenderingContext.cpp >index aab90f92952ca6139e1ba297429fb33ef674545f..35566eb8da57e7e362b840fe864f3591766d2b04 100644 >--- a/Source/WebCore/html/canvas/WebGLRenderingContext.cpp >+++ b/Source/WebCore/html/canvas/WebGLRenderingContext.cpp >@@ -35,6 +35,7 @@ > #include "EXTFloatBlend.h" > #include "EXTFragDepth.h" > #include "EXTShaderTextureLOD.h" >+#include "EXTTextureCompressionRGTC.h" > #include "EXTTextureFilterAnisotropic.h" > #include "EXTsRGB.h" > #include "ExtensionsGL.h" >@@ -153,6 +154,7 @@ WebGLExtension* WebGLRenderingContext::getExtension(const String& name) > return m_extShaderTextureLOD.get(); > } > ENABLE_IF_REQUESTED(EXTTextureFilterAnisotropic, m_extTextureFilterAnisotropic, "EXT_texture_filter_anisotropic", enableSupportedExtension("GL_EXT_texture_filter_anisotropic"_s)); >+ ENABLE_IF_REQUESTED(EXTTextureCompressionRGTC, m_extTextureCompressionRGTC, "EXT_texture_compression_rgtc", enableSupportedExtension("GL_EXT_texture_compression_rgtc"_s)); > ENABLE_IF_REQUESTED(OESStandardDerivatives, m_oesStandardDerivatives, "OES_standard_derivatives", enableSupportedExtension("GL_OES_standard_derivatives"_s)); > ENABLE_IF_REQUESTED(OESTextureFloat, m_oesTextureFloat, "OES_texture_float", OESTextureFloat::supported(*this)); > ENABLE_IF_REQUESTED(OESTextureFloatLinear, m_oesTextureFloatLinear, "OES_texture_float_linear", enableSupportedExtension("GL_OES_texture_float_linear"_s)); >@@ -231,6 +233,8 @@ Optional<Vector<String>> WebGLRenderingContext::getSupportedExtensions() > result.append("OES_standard_derivatives"_s); > if (m_context->getExtensions().supports("GL_EXT_shader_texture_lod"_s) || m_context->getExtensions().supports("GL_ARB_shader_texture_lod"_s)) > result.append("EXT_shader_texture_lod"_s); >+ if (m_context->getExtensions().supports("GL_EXT_texture_compression_rgtc"_s)) >+ result.append("EXT_texture_compression_rgtc"_s); > if (m_context->getExtensions().supports("GL_EXT_texture_filter_anisotropic"_s)) > result.append("EXT_texture_filter_anisotropic"_s); > if (m_context->getExtensions().supports("GL_OES_vertex_array_object"_s)) >diff --git a/Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp b/Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp >index 045d6a6bf916e5af3ba029a1b4656f935d10a5e0..eec53968d2cf8f0046718e2d03092d57702c8a12 100644 >--- a/Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp >+++ b/Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp >@@ -40,6 +40,7 @@ > #include "EXTFloatBlend.h" > #include "EXTFragDepth.h" > #include "EXTShaderTextureLOD.h" >+#include "EXTTextureCompressionRGTC.h" > #include "EXTTextureFilterAnisotropic.h" > #include "EXTsRGB.h" > #include "EventNames.h" >@@ -3714,6 +3715,7 @@ bool WebGLRenderingContextBase::extensionIsEnabled(const String& name) > CHECK_EXTENSION(m_extFragDepth, "EXT_frag_depth"); > CHECK_EXTENSION(m_extBlendMinMax, "EXT_blend_minmax"); > CHECK_EXTENSION(m_extsRGB, "EXT_sRGB"); >+ CHECK_EXTENSION(m_extTextureCompressionRGTC, "EXT_texture_compression_rgtc"); > CHECK_EXTENSION(m_extTextureFilterAnisotropic, "EXT_texture_filter_anisotropic"); > CHECK_EXTENSION(m_extTextureFilterAnisotropic, "WEBKIT_EXT_texture_filter_anisotropic"); > CHECK_EXTENSION(m_extShaderTextureLOD, "EXT_shader_texture_lod"); >@@ -6730,6 +6732,26 @@ bool WebGLRenderingContextBase::validateCompressedTexFuncData(const char* functi > bytesRequired = checkedBytesRequired.unsafeGet(); > break; > } >+ case ExtensionsGL::COMPRESSED_RED_RGTC1_EXT: >+ case ExtensionsGL::COMPRESSED_SIGNED_RED_RGTC1_EXT: { >+ const int kBlockSize = 8; >+ const int kBlockWidth = 4; >+ const int kBlockHeight = 4; >+ int numBlocksAcross = (width + kBlockWidth - 1) / kBlockWidth; >+ int numBlocksDown = (height + kBlockHeight - 1) / kBlockHeight; >+ bytesRequired = numBlocksAcross * numBlocksDown * kBlockSize; >+ break; >+ } >+ case ExtensionsGL::COMPRESSED_RED_GREEN_RGTC2_EXT: >+ case ExtensionsGL::COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT: { >+ const int kBlockSize = 16; >+ const int kBlockWidth = 4; >+ const int kBlockHeight = 4; >+ int numBlocksAcross = (width + kBlockWidth - 1) / kBlockWidth; >+ int numBlocksDown = (height + kBlockHeight - 1) / kBlockHeight; >+ bytesRequired = numBlocksAcross * numBlocksDown * kBlockSize; >+ break; >+ } > default: > synthesizeGLError(GraphicsContextGL::INVALID_ENUM, functionName, "invalid format"); > return false; >@@ -7784,6 +7806,7 @@ void WebGLRenderingContextBase::loseExtensions(LostContextMode mode) > LOSE_EXTENSION(m_extFragDepth); > LOSE_EXTENSION(m_extBlendMinMax); > LOSE_EXTENSION(m_extsRGB); >+ LOSE_EXTENSION(m_extTextureCompressionRGTC); > LOSE_EXTENSION(m_extTextureFilterAnisotropic); > LOSE_EXTENSION(m_extShaderTextureLOD); > LOSE_EXTENSION(m_oesTextureFloat); >diff --git a/Source/WebCore/html/canvas/WebGLRenderingContextBase.h b/Source/WebCore/html/canvas/WebGLRenderingContextBase.h >index 7b218672ac5652884fbd71686ed27e0868615770..206ace3550ab9a1631c535364fac1923f855ebee 100644 >--- a/Source/WebCore/html/canvas/WebGLRenderingContextBase.h >+++ b/Source/WebCore/html/canvas/WebGLRenderingContextBase.h >@@ -72,6 +72,7 @@ class EXTBlendMinMax; > class EXTColorBufferFloat; > class EXTColorBufferHalfFloat; > class EXTFloatBlend; >+class EXTTextureCompressionRGTC; > class EXTTextureFilterAnisotropic; > class EXTShaderTextureLOD; > class EXTsRGB; >@@ -428,6 +429,7 @@ protected: > WebGLRenderingContextBase(CanvasBase&, WebGLContextAttributes); > WebGLRenderingContextBase(CanvasBase&, Ref<GraphicsContextGLOpenGL>&&, WebGLContextAttributes); > >+ friend class EXTTextureCompressionRGTC; > friend class WebGLDrawBuffers; > friend class WebGLFramebuffer; > friend class WebGLObject; >@@ -669,6 +671,7 @@ protected: > RefPtr<EXTFragDepth> m_extFragDepth; > RefPtr<EXTBlendMinMax> m_extBlendMinMax; > RefPtr<EXTsRGB> m_extsRGB; >+ RefPtr<EXTTextureCompressionRGTC> m_extTextureCompressionRGTC; > RefPtr<EXTTextureFilterAnisotropic> m_extTextureFilterAnisotropic; > RefPtr<EXTShaderTextureLOD> m_extShaderTextureLOD; > RefPtr<OESTextureFloat> m_oesTextureFloat; >diff --git a/Source/WebCore/platform/graphics/ExtensionsGL.h b/Source/WebCore/platform/graphics/ExtensionsGL.h >index c07b3c005f42b9cf73bfa061761858d5569714f7..0f5dbbabfb148df0ad2327e04ed310fd718e1ec9 100644 >--- a/Source/WebCore/platform/graphics/ExtensionsGL.h >+++ b/Source/WebCore/platform/graphics/ExtensionsGL.h >@@ -219,6 +219,12 @@ public: > COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR = 0x93DC, > COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR = 0x93DD, > >+ // GL_EXT_texture_compression_rgtc >+ COMPRESSED_RED_RGTC1_EXT = 0x8DBB, >+ COMPRESSED_SIGNED_RED_RGTC1_EXT = 0x8DBC, >+ COMPRESSED_RED_GREEN_RGTC2_EXT = 0x8DBD, >+ COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT = 0x8DBE, >+ > // GL_EXT_texture_filter_anisotropic > TEXTURE_MAX_ANISOTROPY_EXT = 0x84FE, > MAX_TEXTURE_MAX_ANISOTROPY_EXT = 0x84FF, >diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog >index 58df1b1c6f5c423f8e52da08a43d17e15479fee8..0b55f634ebea9e0911afe84e92c979b480cdd1f5 100644 >--- a/LayoutTests/ChangeLog >+++ b/LayoutTests/ChangeLog >@@ -1,3 +1,18 @@ >+2020-10-06 James Darpinian <jdarpinian@chromium.org> >+ >+ Support EXT_texture_compression_rgtc WebGL extension >+ https://bugs.webkit.org/show_bug.cgi?id=217198 >+ >+ Reviewed by Kenneth Russell. >+ >+ * webgl/conformance/extensions/ext-texture-compression-rgtc-expected.txt: Added. >+ * webgl/conformance/extensions/ext-texture-compression-rgtc.html: Added. >+ * webgl/conformance/extensions/s3tc-and-rgtc-expected.txt: Added. >+ * webgl/conformance/extensions/s3tc-and-rgtc.html: Added. >+ * webgl/resources/webgl_test_files/conformance/extensions/ext-texture-compression-rgtc.html: Added. >+ * webgl/resources/webgl_test_files/conformance/extensions/s3tc-and-rgtc.html: Added. >+ * webgl/resources/webgl_test_files/js/tests/compressed-texture-utils.js: Added. >+ > 2020-09-30 Antoine Quint <graouts@webkit.org> > > Add non-animated support for the CSS translate property >diff --git a/LayoutTests/webgl/conformance/extensions/ext-texture-compression-rgtc-expected.txt b/LayoutTests/webgl/conformance/extensions/ext-texture-compression-rgtc-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..5030f62667589e85c4784cf11e3dced99c6ab39a >--- /dev/null >+++ b/LayoutTests/webgl/conformance/extensions/ext-texture-compression-rgtc-expected.txt >@@ -0,0 +1,4 @@ >+This test runs the WebGL Test listed below in an iframe and reports PASS or FAIL. >+ >+Test: ../../resources/webgl_test_files/conformance/extensions/ext-texture-compression-rgtc.html >+PASS >diff --git a/LayoutTests/webgl/conformance/extensions/ext-texture-compression-rgtc.html b/LayoutTests/webgl/conformance/extensions/ext-texture-compression-rgtc.html >new file mode 100644 >index 0000000000000000000000000000000000000000..6e999f5fdfb1cd46b2b2ded191371914262d576a >--- /dev/null >+++ b/LayoutTests/webgl/conformance/extensions/ext-texture-compression-rgtc.html >@@ -0,0 +1,18 @@ >+<!-- This file is auto-generated by generate-webgl-tests.py. DO NOT EDIT --> >+<!DOCTYPE html> >+<html> >+<head> >+<meta charset="utf-8"> >+<title>WebGL Conformance Test Wrapper for ext-texture-compression-rgtc.html</title> >+<script type="text/javascript" src="../../../resources/js-test-pre.js"></script> >+<script type="text/javascript" src="../../resources/webkit-webgl-test-harness.js"></script> >+</head> >+<body> >+<p>This test runs the WebGL Test listed below in an iframe and reports PASS or FAIL.</p> >+Test: <a href="../../resources/webgl_test_files/conformance/extensions/ext-texture-compression-rgtc.html">../../resources/webgl_test_files/conformance/extensions/ext-texture-compression-rgtc.html</a> >+<div id="iframe"> >+<iframe src="../../resources/webgl_test_files/conformance/extensions/ext-texture-compression-rgtc.html" width="800" height="600"></iframe> >+</div> >+<div id="result"></div> >+</body> >+</html> >diff --git a/LayoutTests/webgl/conformance/extensions/s3tc-and-rgtc-expected.txt b/LayoutTests/webgl/conformance/extensions/s3tc-and-rgtc-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..3956a946865dc7a3f165ec718636518bce9786f6 >--- /dev/null >+++ b/LayoutTests/webgl/conformance/extensions/s3tc-and-rgtc-expected.txt >@@ -0,0 +1,4 @@ >+This test runs the WebGL Test listed below in an iframe and reports PASS or FAIL. >+ >+Test: ../../resources/webgl_test_files/conformance/extensions/s3tc-and-rgtc.html >+PASS >diff --git a/LayoutTests/webgl/conformance/extensions/s3tc-and-rgtc.html b/LayoutTests/webgl/conformance/extensions/s3tc-and-rgtc.html >new file mode 100644 >index 0000000000000000000000000000000000000000..9f68058d9c8d3c19bdf51f725bc13b5a7951e00c >--- /dev/null >+++ b/LayoutTests/webgl/conformance/extensions/s3tc-and-rgtc.html >@@ -0,0 +1,18 @@ >+<!-- This file is auto-generated by generate-webgl-tests.py. DO NOT EDIT --> >+<!DOCTYPE html> >+<html> >+<head> >+<meta charset="utf-8"> >+<title>WebGL Conformance Test Wrapper for s3tc-and-rgtc.html</title> >+<script type="text/javascript" src="../../../resources/js-test-pre.js"></script> >+<script type="text/javascript" src="../../resources/webkit-webgl-test-harness.js"></script> >+</head> >+<body> >+<p>This test runs the WebGL Test listed below in an iframe and reports PASS or FAIL.</p> >+Test: <a href="../../resources/webgl_test_files/conformance/extensions/s3tc-and-rgtc.html">../../resources/webgl_test_files/conformance/extensions/s3tc-and-rgtc.html</a> >+<div id="iframe"> >+<iframe src="../../resources/webgl_test_files/conformance/extensions/s3tc-and-rgtc.html" width="800" height="600"></iframe> >+</div> >+<div id="result"></div> >+</body> >+</html> >diff --git a/LayoutTests/webgl/resources/webgl_test_files/conformance/extensions/ext-texture-compression-rgtc.html b/LayoutTests/webgl/resources/webgl_test_files/conformance/extensions/ext-texture-compression-rgtc.html >new file mode 100644 >index 0000000000000000000000000000000000000000..c2a2d41690875526974f0cedf16eccafdf2e0bd3 >--- /dev/null >+++ b/LayoutTests/webgl/resources/webgl_test_files/conformance/extensions/ext-texture-compression-rgtc.html >@@ -0,0 +1,146 @@ >+<!-- >+Copyright (c) 2019 The Khronos Group Inc. >+Use of this source code is governed by an MIT-style license that can be >+found in the LICENSE.txt file. >+--> >+ >+<!DOCTYPE html> >+<html> >+<head> >+<meta charset="utf-8"> >+<title>WebGL EXT_texture_compression_rgtc Conformance Tests</title> >+<LINK rel="stylesheet" href="../../resources/js-test-style.css"/> >+<script src="../../js/js-test-pre.js"></script> >+<script src="../../js/webgl-test-utils.js"></script> >+<script src="../../js/tests/compressed-texture-utils.js"></script> >+</head> >+<body> >+<div id="description"></div> >+<div id="console"></div> >+<script> >+"use strict"; >+description("This test verifies the functionality of the EXT_texture_compression_rgtc extension, if it is available."); >+ >+debug(""); >+ >+var validFormats = { >+ COMPRESSED_RED_RGTC1_EXT: 0x8DBB, >+ COMPRESSED_SIGNED_RED_RGTC1_EXT: 0x8DBC, >+ COMPRESSED_RED_GREEN_RGTC2_EXT: 0x8DBD, >+ COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT: 0x8DBE >+}; >+ >+function expectedByteLength(width, height, format) { >+ if (format == validFormats.COMPRESSED_RED_RGTC1_EXT || format == validFormats.COMPRESSED_SIGNED_RED_RGTC1_EXT) { >+ return Math.ceil(width / 4) * Math.ceil(height / 4) * 8; >+ } >+ else { >+ return Math.ceil(width / 4) * Math.ceil(height / 4) * 16; >+ } >+} >+ >+function getBlockDimensions(format) { >+ return {width: 4, height: 4}; >+} >+ >+var wtu = WebGLTestUtils; >+var ctu = CompressedTextureUtils; >+var contextVersion = wtu.getDefault3DContextVersion(); >+var gl = wtu.create3DContext(); >+var ext; >+ >+var formats = null; >+ >+function runTestExtension() { >+ // Test that enum values are listed correctly in supported formats and in the extension object. >+ ctu.testCompressedFormatsListed(gl, validFormats); >+ ctu.testCorrectEnumValuesInExt(ext, validFormats); >+ // Test that texture upload buffer size is validated correctly. >+ ctu.testFormatRestrictionsOnBufferSize(gl, validFormats, expectedByteLength, getBlockDimensions); >+ // Test TexSubImage validation on dimensions >+ // CompressedTexSubImage* will result in an >+ // INVALID_OPERATION error only if one of the following conditions occurs: >+ // * <width> is not a multiple of four, and <width> plus <xoffset> is not >+ // equal to TEXTURE_WIDTH; >+ // * <height> is not a multiple of four, and <height> plus <yoffset> is >+ // not equal to TEXTURE_HEIGHT; or >+ // * <xoffset> or <yoffset> is not a multiple of four. >+ ctu.testTexSubImageDimensions(gl, validFormats, expectedByteLength, getBlockDimensions, >+ 16, 16, [ >+ { xoffset: 0, yoffset: 0, width: 4, height: 3, >+ expectation: gl.INVALID_OPERATION, message: "height is not a multiple of 4" }, >+ { xoffset: 0, yoffset: 0, width: 3, height: 4, >+ expectation: gl.INVALID_OPERATION, message: "width is not a multiple of 4" }, >+ { xoffset: 1, yoffset: 0, width: 4, height: 4, >+ expectation: gl.INVALID_OPERATION, message: "xoffset is not a multiple of 4" }, >+ { xoffset: 0, yoffset: 1, width: 4, height: 4, >+ expectation: gl.INVALID_OPERATION, message: "yoffset is not a multiple of 4" }, >+ { xoffset: 12, yoffset: 12, width: 4, height: 4, >+ expectation: gl.NO_ERROR, message: "is valid" }, >+ ]); >+ >+ // Test TexImage validation on level dimensions combinations. >+ // When level equals 0, width and height must be a multiple of 4. >+ // When level is larger than 0, this constraint doesn't apply. >+ ctu.testTexImageLevelDimensions(gl, validFormats, expectedByteLength, getBlockDimensions, >+ [ >+ { level: 0, width: 4, height: 3, >+ expectation: gl.INVALID_OPERATION, message: "level is 0, height is not a multiple of 4" }, >+ { level: 0, width: 3, height: 4, >+ expectation: gl.INVALID_OPERATION, message: "level is 0, width is not a multiple of 4" }, >+ { level: 0, width: 2, height: 2, >+ expectation: gl.INVALID_OPERATION, message: "level is 0, width is not a multiple of 4" }, >+ { level: 0, width: 4, height: 4, >+ expectation: gl.NO_ERROR, message: "is valid" }, >+ { level: 1, width: 2, height: 2, >+ expectation: gl.NO_ERROR, message: "level > 0, is valid" }, >+ { level: 2, width: 1, height: 1, >+ expectation: gl.NO_ERROR, message: "level > 0, is valid" }, >+ ]); >+ >+ // Test that RGTC enums are not accepted by texImage2D >+ if (contextVersion >= 2) { >+ var tex = gl.createTexture(); >+ gl.bindTexture(gl.TEXTURE_2D, tex); >+ >+ gl.texImage2D(gl.TEXTURE_2D, 0, ext.COMPRESSED_RED_RGTC1_EXT, 4, 4, 0, gl.RED, gl.UNSIGNED_BYTE, null); >+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "COMPRESSED_RED_RGTC1_EXT fails with texImage2D"); >+ >+ gl.texImage2D(gl.TEXTURE_2D, 0, ext.COMPRESSED_SIGNED_RED_RGTC1_EXT, 4, 4, 0, gl.RED, gl.BYTE, null); >+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "COMPRESSED_SIGNED_RED_RGTC1_EXT fails with texImage2D"); >+ >+ gl.texImage2D(gl.TEXTURE_2D, 0, ext.COMPRESSED_RED_GREEN_RGTC2_EXT, 4, 4, 0, gl.RG, gl.UNSIGNED_BYTE, null); >+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "COMPRESSED_RED_GREEN_RGTC2_EXT fails with texImage2D"); >+ >+ gl.texImage2D(gl.TEXTURE_2D, 0, ext.COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT, 4, 4, 0, gl.RG, gl.BYTE, null); >+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT fails with texImage2D"); >+ >+ gl.deleteTexture(tex); >+ } >+}; >+ >+function runTest() { >+ if (!gl) { >+ testFailed("context does not exist"); >+ } else { >+ testPassed("context exists"); >+ >+ ctu.testCompressedFormatsUnavailableWhenExtensionDisabled(gl, validFormats, expectedByteLength, 4); >+ >+ ext = gl.getExtension("EXT_texture_compression_rgtc"); >+ >+ wtu.runExtensionSupportedTest(gl, "EXT_texture_compression_rgtc", ext !== null); >+ >+ if (ext !== null) { >+ runTestExtension(); >+ } >+ } >+} >+ >+runTest(); >+ >+var successfullyParsed = true; >+</script> >+<script src="../../js/js-test-post.js"></script> >+</body> >+</html> >diff --git a/LayoutTests/webgl/resources/webgl_test_files/conformance/extensions/s3tc-and-rgtc.html b/LayoutTests/webgl/resources/webgl_test_files/conformance/extensions/s3tc-and-rgtc.html >new file mode 100644 >index 0000000000000000000000000000000000000000..80f16d0f10e741c3547b4ba8afc2e23b41ea110d >--- /dev/null >+++ b/LayoutTests/webgl/resources/webgl_test_files/conformance/extensions/s3tc-and-rgtc.html >@@ -0,0 +1,974 @@ >+<!-- >+Copyright (c) 2019 The Khronos Group Inc. >+Use of this source code is governed by an MIT-style license that can be >+found in the LICENSE.txt file. >+--> >+ >+<!DOCTYPE html> >+<html> >+<head> >+<meta charset="utf-8"> >+<link rel="stylesheet" href="../../resources/js-test-style.css"/> >+<script src="../../js/js-test-pre.js"></script> >+<script src="../../js/webgl-test-utils.js"></script> >+<script src="../../js/tests/compressed-texture-utils.js"></script> >+<title>WebGL WEBGL_compressed_texture_s3tc and EXT_texture_compression_rgtc Conformance Tests</title> >+<style> >+img { >+ border: 1px solid black; >+ margin-right: 1em; >+} >+ >+.testimages br { >+ clear: both; >+} >+ >+.testimages > div { >+ float: left; >+ margin: 1em; >+} >+</style> >+</head> >+<body> >+<div id="description"></div> >+<canvas id="canvas" width="8" height="8" style="width: 8px; height: 8px;"></canvas> >+<div id="console"></div> >+<script> >+"use strict"; >+description("This test verifies the functionality of the WEBGL_compressed_texture_s3tc extension, if it is available. It also tests the related formats from the EXT_texture_compression_rgtc extension."); >+ >+debug(""); >+ >+/* >+BC1 (DXT1) block >+e0 = [ 0, 255, 0] >+e1 = [255, 0, 0] >+e0 < e1, so it uses 3-color mode >+ >+local palette >+ 0: [ 0, 255, 0, 255] >+ 1: [255, 0, 0, 255] >+ 2: [128, 128, 0, 255] >+ 3: [ 0, 0, 0, 255] // for BC1 RGB >+ 3: [ 0, 0, 0, 0] // for BC1 RGBA >+selectors >+ 3 2 1 0 >+ 2 2 1 0 >+ 1 1 1 0 >+ 0 0 0 0 >+ >+Extending this block with opaque alpha and uploading as BC2 or BC3 >+will generate wrong colors because BC2 and BC3 do not have 3-color mode. >+*/ >+var img_4x4_rgba_dxt1 = new Uint8Array([ >+ 0xE0, 0x07, 0x00, 0xF8, 0x1B, 0x1A, 0x15, 0x00 >+]); >+ >+/* >+BC2 (DXT3) block >+ >+Quantized alpha values >+ 0 1 2 3 >+ 4 5 6 7 >+ 8 9 A B >+ C D E F >+ >+RGB block >+e0 = [255, 0, 0] >+e1 = [ 0, 255, 0] >+BC2 has only 4-color mode >+ >+local palette >+ 0: [255, 0, 0] >+ 1: [ 0, 255, 0] >+ 2: [170, 85, 0] >+ 3: [ 85, 170, 0] >+selectors >+ 0 1 2 3 >+ 1 1 2 3 >+ 2 2 2 3 >+ 3 3 3 3 >+*/ >+var img_4x4_rgba_dxt3 = new Uint8Array([ >+ 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE, >+ 0x00, 0xF8, 0xE0, 0x07, 0xE4, 0xE5, 0xEA, 0xFF >+]); >+ >+/* >+BC3 (DXT5) block >+ >+Alpha block (aka DXT5A) >+e0 = 255 >+e1 = 0 >+e0 > e1, so using 6 intermediate points >+local palette >+ 255, 0, 219, 182, 146, 109, 73, 36 >+selectors >+ 0 1 2 3 >+ 1 2 3 4 >+ 2 3 4 5 >+ 3 4 5 6 >+ >+RGB block >+e0 = [255, 0, 0] >+e1 = [ 0, 255, 0] >+BC3 has only 4-color mode >+ >+local palette >+ 0: [255, 0, 0] >+ 1: [ 0, 255, 0] >+ 2: [170, 85, 0] >+ 3: [ 85, 170, 0] >+selectors >+ 3 2 1 0 >+ 3 2 1 1 >+ 3 2 2 2 >+ 3 3 3 3 >+*/ >+var img_4x4_rgba_dxt5 = new Uint8Array([ >+ 0xFF, 0x00, 0x88, 0x16, 0x8D, 0x1A, 0x3B, 0xD6, >+ 0x00, 0xF8, 0xE0, 0x07, 0x1B, 0x5B, 0xAB, 0xFF >+]); >+ >+// BC4 - just the alpha block from BC3 above, interpreted as the red channel. >+var img_4x4_r_bc4 = new Uint8Array([ >+ 0xFF, 0x00, 0x88, 0x16, 0x8D, 0x1A, 0x3B, 0xD6, >+]); >+ >+// BC5 - Two BC3 alpha blocks, interpreted as the red and green channels. >+var img_4x4_rg_bc5 = new Uint8Array([ >+ 0xFF, 0x00, 0x88, 0x16, 0x8D, 0x1A, 0x3B, 0xD6, >+ 0x00, 0xFF, 0x88, 0x16, 0x8D, 0x1A, 0x3B, 0xD6, >+]); >+ >+// Signed BC4 - change endpoints to use full -1 to 1 range. >+var img_4x4_signed_r_bc4 = new Uint8Array([ >+ 0x7F, 0x80, 0x88, 0x16, 0x8D, 0x1A, 0x3B, 0xD6, >+]); >+ >+// Signed BC5 - Two BC3 alpha blocks, interpreted as the red and green channels. >+var img_4x4_signed_rg_bc5 = new Uint8Array([ >+ 0x7F, 0x80, 0x88, 0x16, 0x8D, 0x1A, 0x3B, 0xD6, >+ 0x80, 0x7F, 0x88, 0x16, 0x8D, 0x1A, 0x3B, 0xD6, >+]); >+ >+ >+/* >+8x8 block endpoints use half-intensity values (appear darker than 4x4) >+*/ >+var img_8x8_rgba_dxt1 = new Uint8Array([ >+ 0xe0,0x03,0x00,0x78,0x13,0x10,0x15,0x00, >+ 0x0f,0x00,0xe0,0x7b,0x11,0x10,0x15,0x00, >+ 0xe0,0x03,0x0f,0x78,0x44,0x45,0x40,0x55, >+ 0x0f,0x00,0xef,0x03,0x44,0x45,0x40,0x55 >+]); >+var img_8x8_rgba_dxt3 = new Uint8Array([ >+ 0xf6,0xff,0xf6,0xff,0xff,0xff,0xff,0xff,0x00,0x78,0xe0,0x03,0x44,0x45,0x40,0x55, >+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xe0,0x7b,0x0f,0x00,0x44,0x45,0x40,0x55, >+ 0xff,0xff,0xff,0xff,0xf6,0xff,0xf6,0xff,0x0f,0x78,0xe0,0x03,0x11,0x10,0x15,0x00, >+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xef,0x03,0x0f,0x00,0x11,0x10,0x15,0x00 >+]); >+var img_8x8_rgba_dxt5 = new Uint8Array([ >+ 0xff,0x69,0x01,0x10,0x00,0x00,0x00,0x00,0x00,0x78,0xe0,0x03,0x44,0x45,0x40,0x55, >+ 0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x7b,0x0f,0x00,0x44,0x45,0x40,0x55, >+ 0xff,0x69,0x00,0x00,0x00,0x01,0x10,0x00,0x0f,0x78,0xe0,0x03,0x11,0x10,0x15,0x00, >+ 0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xef,0x03,0xef,0x00,0x11,0x10,0x15,0x00 >+]); >+var img_8x8_r_bc4 = new Uint8Array([ >+ 0x7F, 0x00, 0x88, 0x16, 0x8D, 0x1A, 0x3B, 0xD6, >+ 0x7F, 0x00, 0x88, 0x16, 0x8D, 0x1A, 0x3B, 0xD6, >+ 0x7F, 0x00, 0x88, 0x16, 0x8D, 0x1A, 0x3B, 0xD6, >+ 0x7F, 0x00, 0x88, 0x16, 0x8D, 0x1A, 0x3B, 0xD6, >+]); >+var img_8x8_rg_bc5 = new Uint8Array([ >+ 0x7F, 0x00, 0x88, 0x16, 0x8D, 0x1A, 0x3B, 0xD6, 0x00, 0x7F, 0x88, 0x16, 0x8D, 0x1A, 0x3B, 0xD6, >+ 0x7F, 0x00, 0x88, 0x16, 0x8D, 0x1A, 0x3B, 0xD6, 0x00, 0x7F, 0x88, 0x16, 0x8D, 0x1A, 0x3B, 0xD6, >+ 0x7F, 0x00, 0x88, 0x16, 0x8D, 0x1A, 0x3B, 0xD6, 0x00, 0x7F, 0x88, 0x16, 0x8D, 0x1A, 0x3B, 0xD6, >+ 0x7F, 0x00, 0x88, 0x16, 0x8D, 0x1A, 0x3B, 0xD6, 0x00, 0x7F, 0x88, 0x16, 0x8D, 0x1A, 0x3B, 0xD6, >+]); >+ >+var wtu = WebGLTestUtils; >+var ctu = CompressedTextureUtils; >+var contextVersion = wtu.getDefault3DContextVersion(); >+var canvas = document.getElementById("canvas"); >+var gl = wtu.create3DContext(canvas, {antialias: false}); >+var program = wtu.setupTexturedQuad(gl); >+var ext = null; >+var ext_rgtc = {}; >+var vao = null; >+var validFormats = { >+ COMPRESSED_RGB_S3TC_DXT1_EXT : 0x83F0, >+ COMPRESSED_RGBA_S3TC_DXT1_EXT : 0x83F1, >+ COMPRESSED_RGBA_S3TC_DXT3_EXT : 0x83F2, >+ COMPRESSED_RGBA_S3TC_DXT5_EXT : 0x83F3, >+}; >+var name; >+var supportedFormats; >+ >+if (!gl) { >+ testFailed("WebGL context does not exist"); >+} else { >+ testPassed("WebGL context exists"); >+ >+ // Run tests with extension disabled >+ ctu.testCompressedFormatsUnavailableWhenExtensionDisabled(gl, validFormats, expectedByteLength, 4); >+ >+ // Query the extension and store globally so shouldBe can access it >+ ext = wtu.getExtensionWithKnownPrefixes(gl, "WEBGL_compressed_texture_s3tc"); >+ if (!ext) { >+ testPassed("No WEBGL_compressed_texture_s3tc support -- this is legal"); >+ wtu.runExtensionSupportedTest(gl, "WEBGL_compressed_texture_s3tc", false); >+ } else { >+ testPassed("Successfully enabled WEBGL_compressed_texture_s3tc extension"); >+ >+ wtu.runExtensionSupportedTest(gl, "WEBGL_compressed_texture_s3tc", true); >+ runTestExtension(); >+ } >+ ext_rgtc = wtu.getExtensionWithKnownPrefixes(gl, "EXT_texture_compression_rgtc"); >+ if (ext_rgtc.COMPRESSED_RED_RGTC1_EXT) { >+ ext = ext || {}; >+ // Make ctu.formatToString work for rgtc enums. >+ for (const name in ext_rgtc) >+ ext[name] = ext_rgtc[name]; >+ runTestRGTC(); >+ } >+} >+ >+function expectedByteLength(width, height, format) { >+ if (format == validFormats.COMPRESSED_RGBA_S3TC_DXT3_EXT || format == validFormats.COMPRESSED_RGBA_S3TC_DXT5_EXT) { >+ return Math.floor((width + 3) / 4) * Math.floor((height + 3) / 4) * 16; >+ } >+ return Math.floor((width + 3) / 4) * Math.floor((height + 3) / 4) * 8; >+} >+ >+function getBlockDimensions(format) { >+ return {width: 4, height: 4}; >+} >+ >+function runTestExtension() { >+ debug(""); >+ debug("Testing WEBGL_compressed_texture_s3tc"); >+ >+ // Test that enum values are listed correctly in supported formats and in the extension object. >+ ctu.testCompressedFormatsListed(gl, validFormats); >+ ctu.testCorrectEnumValuesInExt(ext, validFormats); >+ // Test that texture upload buffer size is validated correctly. >+ ctu.testFormatRestrictionsOnBufferSize(gl, validFormats, expectedByteLength, getBlockDimensions); >+ >+ // Test each format >+ testDXT1_RGB(); >+ testDXT1_RGBA(); >+ testDXT3_RGBA(); >+ testDXT5_RGBA(); >+ >+ // Test compressed PBOs with a single format >+ if (contextVersion >= 2) { >+ testDXT5_RGBA_PBO(); >+ } >+} >+ >+function runTestRGTC() { >+ var tests = [ >+ { width: 4, >+ height: 4, >+ channels: 1, >+ data: img_4x4_r_bc4, >+ format: ext_rgtc.COMPRESSED_RED_RGTC1_EXT, >+ hasAlpha: false, >+ }, >+ { width: 4, >+ height: 4, >+ channels: 1, >+ data: img_4x4_signed_r_bc4, >+ format: ext_rgtc.COMPRESSED_SIGNED_RED_RGTC1_EXT, >+ hasAlpha: false, >+ }, >+ { width: 4, >+ height: 4, >+ channels: 2, >+ data: img_4x4_rg_bc5, >+ format: ext_rgtc.COMPRESSED_RED_GREEN_RGTC2_EXT, >+ hasAlpha: false, >+ }, >+ { width: 4, >+ height: 4, >+ channels: 2, >+ data: img_4x4_signed_rg_bc5, >+ format: ext_rgtc.COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT, >+ hasAlpha: false, >+ }, >+ { width: 8, >+ height: 8, >+ channels: 2, >+ data: img_8x8_r_bc4, >+ format: ext_rgtc.COMPRESSED_RED_RGTC1_EXT, >+ hasAlpha: false, >+ subX0: 0, >+ subY0: 0, >+ subWidth: 4, >+ subHeight: 4, >+ subData: img_4x4_r_bc4, >+ }, >+ { width: 8, >+ height: 8, >+ channels: 2, >+ data: img_8x8_rg_bc5, >+ format: ext_rgtc.COMPRESSED_RED_GREEN_RGTC2_EXT, >+ hasAlpha: false, >+ subX0: 0, >+ subY0: 0, >+ subWidth: 4, >+ subHeight: 4, >+ subData: img_4x4_rg_bc5, >+ }, >+ ]; >+ testDXTTextures(tests); >+} >+ >+function testDXT1_RGB() { >+ var tests = [ >+ { width: 4, >+ height: 4, >+ channels: 3, >+ data: img_4x4_rgba_dxt1, >+ format: ext.COMPRESSED_RGB_S3TC_DXT1_EXT, >+ hasAlpha: false, >+ }, >+ { width: 8, >+ height: 8, >+ channels: 3, >+ data: img_8x8_rgba_dxt1, >+ format: ext.COMPRESSED_RGB_S3TC_DXT1_EXT, >+ hasAlpha: false, >+ subX0: 0, >+ subY0: 0, >+ subWidth: 4, >+ subHeight: 4, >+ subData: img_4x4_rgba_dxt1 >+ } >+ ]; >+ testDXTTextures(tests); >+} >+ >+function testDXT1_RGBA() { >+ var tests = [ >+ { width: 4, >+ height: 4, >+ channels: 4, >+ data: img_4x4_rgba_dxt1, >+ format: ext.COMPRESSED_RGBA_S3TC_DXT1_EXT, >+ // This is a special case -- the texture is still opaque >+ // though it's RGBA. >+ hasAlpha: false, >+ }, >+ { width: 8, >+ height: 8, >+ channels: 4, >+ data: img_8x8_rgba_dxt1, >+ format: ext.COMPRESSED_RGBA_S3TC_DXT1_EXT, >+ // This is a special case -- the texture is still opaque >+ // though it's RGBA. >+ hasAlpha: false, >+ } >+ ]; >+ testDXTTextures(tests); >+} >+ >+function testDXT3_RGBA() { >+ var tests = [ >+ { width: 4, >+ height: 4, >+ channels: 4, >+ data: img_4x4_rgba_dxt3, >+ format: ext.COMPRESSED_RGBA_S3TC_DXT3_EXT, >+ hasAlpha: true, >+ }, >+ { width: 8, >+ height: 8, >+ channels: 4, >+ data: img_8x8_rgba_dxt3, >+ format: ext.COMPRESSED_RGBA_S3TC_DXT3_EXT, >+ hasAlpha: true, >+ subX0: 0, >+ subY0: 0, >+ subWidth: 4, >+ subHeight: 4, >+ subData: img_4x4_rgba_dxt3 >+ } >+ ]; >+ testDXTTextures(tests); >+} >+ >+function testDXT5_RGBA() { >+ var tests = [ >+ { width: 4, >+ height: 4, >+ channels: 4, >+ data: img_4x4_rgba_dxt5, >+ format: ext.COMPRESSED_RGBA_S3TC_DXT5_EXT, >+ hasAlpha: true, >+ }, >+ { width: 8, >+ height: 8, >+ channels: 4, >+ data: img_8x8_rgba_dxt5, >+ format: ext.COMPRESSED_RGBA_S3TC_DXT5_EXT, >+ hasAlpha: true, >+ subX0: 0, >+ subY0: 0, >+ subWidth: 4, >+ subHeight: 4, >+ subData: img_4x4_rgba_dxt5 >+ } >+ ]; >+ testDXTTextures(tests); >+} >+ >+function testDXTTextures(tests) { >+ debug("<hr/>"); >+ for (var ii = 0; ii < tests.length; ++ii) { >+ testDXTTexture(tests[ii], false); >+ if (contextVersion >= 2) { >+ debug("<br/>"); >+ testDXTTexture(tests[ii], true); >+ } >+ } >+} >+ >+function uncompressDXTBlock( >+ destBuffer, destX, destY, destWidth, src, srcOffset, format) { >+ // Decoding routines follow D3D11 functional spec wrt >+ // endpoints unquantization and interpolation. >+ // Some hardware may produce slightly different values - it's normal. >+ >+ function make565(src, offset) { >+ return src[offset + 0] + (src[offset + 1] << 8); >+ } >+ function make8888From565(c) { >+ // These values exactly match hw decoder when selectors are 0 or 1. >+ function replicateBits(v, w) { >+ return (v << (8 - w)) | (v >> (w + w - 8)); >+ } >+ return [ >+ replicateBits((c >> 11) & 0x1F, 5), >+ replicateBits((c >> 5) & 0x3F, 6), >+ replicateBits((c >> 0) & 0x1F, 5), >+ 255 >+ ]; >+ } >+ function mix(mult, c0, c1, div) { >+ var r = []; >+ for (var ii = 0; ii < c0.length; ++ii) { >+ // For green channel (6 bits), this interpolation exactly matches hw decoders >+ >+ // For red and blue channels (5 bits), this interpolation exactly >+ // matches only some hw decoders and stays within acceptable range for others. >+ r[ii] = Math.floor((c0[ii] * mult + c1[ii]) / div + 0.5); >+ } >+ return r; >+ } >+ var isBC45 = ext_rgtc && >+ (format == ext_rgtc.COMPRESSED_RED_RGTC1_EXT || >+ format == ext_rgtc.COMPRESSED_RED_GREEN_RGTC2_EXT || >+ format == ext_rgtc.COMPRESSED_SIGNED_RED_RGTC1_EXT || >+ format == ext_rgtc.COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT); >+ if (!isBC45) { >+ var isDXT1 = format == ext.COMPRESSED_RGB_S3TC_DXT1_EXT || >+ format == ext.COMPRESSED_RGBA_S3TC_DXT1_EXT; >+ var colorOffset = srcOffset + (isDXT1 ? 0 : 8); >+ var color0 = make565(src, colorOffset + 0); >+ var color1 = make565(src, colorOffset + 2); >+ var c0gtc1 = color0 > color1 || !isDXT1; >+ var rgba0 = make8888From565(color0); >+ var rgba1 = make8888From565(color1); >+ var colors = [ >+ rgba0, >+ rgba1, >+ c0gtc1 ? mix(2, rgba0, rgba1, 3) : mix(1, rgba0, rgba1, 2), >+ c0gtc1 ? mix(2, rgba1, rgba0, 3) : [0, 0, 0, 255] >+ ]; >+ } >+ const isSigned = ext_rgtc && (format == ext_rgtc.COMPRESSED_SIGNED_RED_RGTC1_EXT || format == ext_rgtc.COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT); >+ const signedSrc = new Int8Array(src); >+ >+ // yea I know there is a lot of math in this inner loop. >+ // so sue me. >+ for (var yy = 0; yy < 4; ++yy) { >+ var pixels = src[colorOffset + 4 + yy]; >+ for (var xx = 0; xx < 4; ++xx) { >+ var dstOff = ((destY + yy) * destWidth + destX + xx) * 4; >+ if (!isBC45) { >+ var code = (pixels >> (xx * 2)) & 0x3; >+ var srcColor = colors[code]; >+ } >+ var alpha; >+ var rgChannel2 = 0; >+ let decodeAlpha = (offset) => { >+ let alpha; >+ var alpha0 = (isSigned ? signedSrc : src)[offset + 0]; >+ var alpha1 = (isSigned ? signedSrc : src)[offset + 1]; >+ var alphaOff = (yy >> 1) * 3 + 2; >+ var alphaBits = >+ src[offset + alphaOff + 0] + >+ src[offset + alphaOff + 1] * 256 + >+ src[offset + alphaOff + 2] * 65536; >+ var alphaShift = (yy % 2) * 12 + xx * 3; >+ var alphaCode = (alphaBits >> alphaShift) & 0x7; >+ if (alpha0 > alpha1) { >+ switch (alphaCode) { >+ case 0: >+ alpha = alpha0; >+ break; >+ case 1: >+ alpha = alpha1; >+ break; >+ default: >+ alpha = Math.floor(((8 - alphaCode) * alpha0 + (alphaCode - 1) * alpha1) / 7.0 + 0.5); >+ break; >+ } >+ } else { >+ switch (alphaCode) { >+ case 0: >+ alpha = alpha0; >+ break; >+ case 1: >+ alpha = alpha1; >+ break; >+ case 6: >+ alpha = 0; >+ break; >+ case 7: >+ alpha = 255; >+ break; >+ default: >+ alpha = Math.floor(((6 - alphaCode) * alpha0 + (alphaCode - 1) * alpha1) / 5.0 + 0.5); >+ break; >+ } >+ } >+ return alpha; >+ } >+ >+ switch (format) { >+ case ext.COMPRESSED_RGB_S3TC_DXT1_EXT: >+ alpha = 255; >+ break; >+ case ext.COMPRESSED_RGBA_S3TC_DXT1_EXT: >+ alpha = (code == 3 && !c0gtc1) ? 0 : 255; >+ break; >+ case ext.COMPRESSED_RGBA_S3TC_DXT3_EXT: >+ { >+ var alpha0 = src[srcOffset + yy * 2 + (xx >> 1)]; >+ var alpha1 = (alpha0 >> ((xx % 2) * 4)) & 0xF; >+ alpha = alpha1 | (alpha1 << 4); >+ } >+ break; >+ case ext_rgtc.COMPRESSED_RED_GREEN_RGTC2_EXT: >+ case ext_rgtc.COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT: >+ rgChannel2 = decodeAlpha(srcOffset + 8); >+ // FALLTHROUGH >+ case ext.COMPRESSED_RGBA_S3TC_DXT5_EXT: >+ case ext_rgtc.COMPRESSED_RED_RGTC1_EXT: >+ case ext_rgtc.COMPRESSED_SIGNED_RED_RGTC1_EXT: >+ alpha = decodeAlpha(srcOffset); >+ break; >+ default: >+ throw "bad format"; >+ } >+ if (isBC45) { >+ destBuffer[dstOff + 0] = alpha; >+ destBuffer[dstOff + 1] = rgChannel2; >+ destBuffer[dstOff + 2] = 0; >+ destBuffer[dstOff + 3] = 255; >+ if (isSigned) { >+ destBuffer[dstOff + 0] = Math.max(0, alpha) * 2; >+ destBuffer[dstOff + 1] = Math.max(0, rgChannel2) * 2; >+ } >+ } else { >+ destBuffer[dstOff + 0] = srcColor[0]; >+ destBuffer[dstOff + 1] = srcColor[1]; >+ destBuffer[dstOff + 2] = srcColor[2]; >+ destBuffer[dstOff + 3] = alpha; >+ } >+ } >+ } >+} >+ >+function getBlockSize(format) { >+ var isDXT1 = format == ext.COMPRESSED_RGB_S3TC_DXT1_EXT || >+ format == ext.COMPRESSED_RGBA_S3TC_DXT1_EXT; >+ var isBC4 = ext_rgtc && (format == ext_rgtc.COMPRESSED_RED_RGTC1_EXT || format == ext_rgtc.COMPRESSED_SIGNED_RED_RGTC1_EXT); >+ return isDXT1 || isBC4 ? 8 : 16; >+} >+ >+function uncompressDXT(width, height, data, format) { >+ if (width % 4 || height % 4) throw "bad width or height"; >+ >+ var dest = new Uint8Array(width * height * 4); >+ var blocksAcross = width / 4; >+ var blocksDown = height / 4; >+ var blockSize = getBlockSize(format); >+ for (var yy = 0; yy < blocksDown; ++yy) { >+ for (var xx = 0; xx < blocksAcross; ++xx) { >+ uncompressDXTBlock( >+ dest, xx * 4, yy * 4, width, data, >+ (yy * blocksAcross + xx) * blockSize, format); >+ } >+ } >+ return dest; >+} >+ >+function uncompressDXTIntoSubRegion(width, height, subX0, subY0, subWidth, subHeight, data, format) >+{ >+ if (width % 4 || height % 4 || subX0 % 4 || subY0 % 4 || subWidth % 4 || subHeight % 4) >+ throw "bad dimension"; >+ >+ var dest = new Uint8Array(width * height * 4); >+ // Zero-filled DXT1 or BC4/5 texture represents [0, 0, 0, 255] >+ if (format == ext.COMPRESSED_RGB_S3TC_DXT1_EXT || format == ext.COMPRESSED_RGBA_S3TC_DXT1_EXT || >+ format == ext.COMPRESSED_RED_RGTC1_EXT || format == ext.COMPRESSED_SIGNED_RED_RGTC1_EXT || >+ format == ext.COMPRESSED_RED_GREEN_RGTC2_EXT || format == ext.COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT) { >+ for (var i = 3; i < dest.length; i += 4) dest[i] = 255; >+ } >+ var blocksAcross = subWidth / 4; >+ var blocksDown = subHeight / 4; >+ var blockSize = getBlockSize(format); >+ for (var yy = 0; yy < blocksDown; ++yy) { >+ for (var xx = 0; xx < blocksAcross; ++xx) { >+ uncompressDXTBlock( >+ dest, subX0 + xx * 4, subY0 + yy * 4, width, data, >+ (yy * blocksAcross + xx) * blockSize, format); >+ } >+ } >+ return dest; >+} >+ >+function copyRect(data, srcX, srcY, dstX, dstY, width, height, stride) { >+ var bytesPerLine = width * 4; >+ var srcOffset = srcX * 4 + srcY * stride; >+ var dstOffset = dstX * 4 + dstY * stride; >+ for (; height > 0; --height) { >+ for (var ii = 0; ii < bytesPerLine; ++ii) { >+ data[dstOffset + ii] = data[srcOffset + ii]; >+ } >+ srcOffset += stride; >+ dstOffset += stride; >+ } >+} >+ >+function testDXTTexture(test, useTexStorage) { >+ var data = new Uint8Array(test.data); >+ var width = test.width; >+ var height = test.height; >+ var format = test.format; >+ >+ var uncompressedData = uncompressDXT(width, height, data, format); >+ >+ canvas.width = width; >+ canvas.height = height; >+ gl.viewport(0, 0, width, height); >+ debug("testing " + ctu.formatToString(ext, format) + " " + width + "x" + height + >+ (useTexStorage ? " via texStorage2D" : " via compressedTexImage2D")); >+ >+ var tex = gl.createTexture(); >+ gl.bindTexture(gl.TEXTURE_2D, tex); >+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); >+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); >+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); >+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); >+ if (useTexStorage) { >+ if (test.subData) { >+ var uncompressedDataSub = uncompressDXTIntoSubRegion( >+ width, height, test.subX0, test.subY0, test.subWidth, test.subHeight, test.subData, format); >+ var tex1 = gl.createTexture(); >+ gl.bindTexture(gl.TEXTURE_2D, tex1); >+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); >+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); >+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); >+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); >+ >+ gl.texStorage2D(gl.TEXTURE_2D, 1, format, width, height); >+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "allocating compressed texture via texStorage2D"); >+ gl.compressedTexSubImage2D( >+ gl.TEXTURE_2D, 0, test.subX0, test.subY0, test.subWidth, test.subHeight, format, test.subData); >+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "uploading compressed texture data via compressedTexSubImage2D"); >+ >+ wtu.clearAndDrawUnitQuad(gl); >+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "drawing unit quad 1"); >+ compareRect(width, height, test.channels, uncompressedDataSub, "NEAREST"); >+ >+ // Clean up and recover >+ gl.deleteTexture(tex1); >+ gl.bindTexture(gl.TEXTURE_2D, tex); >+ } >+ >+ gl.texStorage2D(gl.TEXTURE_2D, 1, format, width, height); >+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "allocating compressed texture via texStorage2D"); >+ wtu.clearAndDrawUnitQuad(gl); >+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "drawing unit quad"); >+ var clearColor = (test.hasAlpha ? [0, 0, 0, 0] : [0, 0, 0, 255]); >+ wtu.checkCanvas(gl, clearColor, "texture should be initialized to black"); >+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height, format, data); >+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "uploading compressed texture data via compressedTexSubImage2D"); >+ } else { >+ gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height, 0, data); >+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "uploading compressed texture"); >+ } >+ gl.generateMipmap(gl.TEXTURE_2D); >+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "trying to generate mipmaps from compressed texture"); >+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after clearing generateMipmap error"); >+ wtu.clearAndDrawUnitQuad(gl); >+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "drawing unit quad 1"); >+ compareRect(width, height, test.channels, uncompressedData, "NEAREST"); >+ // Test again with linear filtering. >+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); >+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); >+ wtu.clearAndDrawUnitQuad(gl); >+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "drawing unit quad 2"); >+ compareRect(width, height, test.channels, uncompressedData, "LINEAR"); >+ >+ if (!useTexStorage) { >+ // It's not allowed to redefine textures defined via texStorage2D. >+ gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height, 1, data); >+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "non 0 border"); >+ >+ gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width + 4, height, 0, data); >+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "data size does not match dimensions"); >+ gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height + 4, 0, data); >+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "data size does not match dimensions"); >+ gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width - 4, height, 0, data); >+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "data size does not match dimensions"); >+ gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height - 4, 0, data); >+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "data size does not match dimensions"); >+ >+ gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width - 1, height, 0, data); >+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions"); >+ gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width - 2, height, 0, data); >+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions"); >+ gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height - 1, 0, data); >+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions"); >+ gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height - 2, 0, data); >+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions"); >+ >+ if (width == 4) { >+ gl.compressedTexImage2D(gl.TEXTURE_2D, 1, format, 1, height, 0, data); >+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "valid dimensions for level > 0"); >+ gl.compressedTexImage2D(gl.TEXTURE_2D, 1, format, 2, height, 0, data); >+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "valid dimensions for level > 0"); >+ } >+ if (height == 4) { >+ gl.compressedTexImage2D(gl.TEXTURE_2D, 1, format, width, 1, 0, data); >+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "valid dimensions for level > 0"); >+ gl.compressedTexImage2D(gl.TEXTURE_2D, 1, format, width, 2, 0, data); >+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "valid dimensions for level > 0"); >+ } >+ } >+ >+ // pick a wrong format that uses the same amount of data. >+ var wrongFormat; >+ switch (format) { >+ case ext.COMPRESSED_RGB_S3TC_DXT1_EXT: >+ wrongFormat = ext.COMPRESSED_RGBA_S3TC_DXT1_EXT; >+ break; >+ case ext.COMPRESSED_RGBA_S3TC_DXT1_EXT: >+ wrongFormat = ext.COMPRESSED_RGB_S3TC_DXT1_EXT; >+ break; >+ case ext.COMPRESSED_RGBA_S3TC_DXT3_EXT: >+ wrongFormat = ext.COMPRESSED_RGBA_S3TC_DXT5_EXT; >+ break; >+ case ext.COMPRESSED_RGBA_S3TC_DXT5_EXT: >+ wrongFormat = ext.COMPRESSED_RGBA_S3TC_DXT3_EXT; >+ break; >+ case ext_rgtc.COMPRESSED_RED_RGTC1_EXT: >+ case ext_rgtc.COMPRESSED_SIGNED_RED_RGTC1_EXT: >+ wrongFormat = ext_rgtc.COMPRESSED_RED_GREEN_RGTC2_EXT; >+ break; >+ case ext_rgtc.COMPRESSED_RED_GREEN_RGTC2_EXT: >+ case ext_rgtc.COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT: >+ wrongFormat = ext_rgtc.COMPRESSED_RED_RGTC1_EXT; >+ break; >+ } >+ >+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height, wrongFormat, data); >+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "format does not match"); >+ >+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 4, 0, width, height, format, data); >+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "dimension out of range"); >+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 4, width, height, format, data); >+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "dimension out of range"); >+ >+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width + 4, height, format, data); >+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "data size does not match dimensions"); >+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height + 4, format, data); >+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "data size does not match dimensions"); >+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width - 4, height, format, data); >+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "data size does not match dimensions"); >+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height - 4, format, data); >+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "data size does not match dimensions"); >+ >+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width - 1, height, format, data); >+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions"); >+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width - 2, height, format, data); >+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions"); >+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height - 1, format, data); >+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions"); >+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height - 2, format, data); >+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions"); >+ >+ var subData = new Uint8Array(data.buffer, 0, getBlockSize(format)); >+ >+ if (width == 8 && height == 8) { >+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 1, 0, 4, 4, format, subData); >+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid offset"); >+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 1, 4, 4, format, subData); >+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid offset"); >+ } >+ >+ var stride = width * 4; >+ for (var yoff = 0; yoff < height; yoff += 4) { >+ for (var xoff = 0; xoff < width; xoff += 4) { >+ copyRect(uncompressedData, 0, 0, xoff, yoff, 4, 4, stride); >+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, xoff, yoff, 4, 4, format, subData); >+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "uploading compressed texture"); >+ // First test NEAREST filtering. >+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); >+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); >+ wtu.clearAndDrawUnitQuad(gl); >+ compareRect(width, height, test.channels, uncompressedData, "NEAREST"); >+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "drawing unit quad"); >+ // Next test LINEAR filtering. >+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); >+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); >+ wtu.clearAndDrawUnitQuad(gl); >+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "drawing unit quad"); >+ compareRect(width, height, test.channels, uncompressedData, "LINEAR"); >+ } >+ } >+} >+ >+function testDXT5_RGBA_PBO() { >+ debug(""); >+ debug("testing PBO uploads"); >+ var width = 8; >+ var height = 8; >+ var channels = 4; >+ var data = img_8x8_rgba_dxt5; >+ var format = ext.COMPRESSED_RGBA_S3TC_DXT5_EXT; >+ var uncompressedData = uncompressDXT(width, height, data, format); >+ >+ var tex = gl.createTexture(); >+ >+ // First, PBO size = image size >+ var pbo1 = gl.createBuffer(); >+ gl.bindBuffer(gl.PIXEL_UNPACK_BUFFER, pbo1); >+ gl.bufferData(gl.PIXEL_UNPACK_BUFFER, data, gl.STATIC_DRAW); >+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "uploading a PBO"); >+ >+ gl.bindTexture(gl.TEXTURE_2D, tex); >+ gl.texStorage2D(gl.TEXTURE_2D, 1, format, width, height); >+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height, format, data.length, 0); >+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "uploading a texture from a PBO"); >+ >+ gl.bindBuffer(gl.PIXEL_UNPACK_BUFFER, null); >+ wtu.clearAndDrawUnitQuad(gl); >+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "drawing unit quad"); >+ compareRect(width, height, channels, uncompressedData, "NEAREST"); >+ >+ // Clear the texture before the next test >+ gl.bindBuffer(gl.PIXEL_UNPACK_BUFFER, null); >+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height, format, new Uint8Array(data.length)); >+ >+ // Second, image is just a subrange of the PBO >+ var pbo2 = gl.createBuffer(); >+ gl.bindBuffer(gl.PIXEL_UNPACK_BUFFER, pbo2); >+ gl.bufferData(gl.PIXEL_UNPACK_BUFFER, data.length*3, gl.STATIC_DRAW); >+ gl.bufferSubData(gl.PIXEL_UNPACK_BUFFER, data.length, data); >+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "uploading a PBO subrange"); >+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height, format, data.length, data.length); >+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "uploading a texture from a PBO subrange"); >+ gl.bindBuffer(gl.PIXEL_UNPACK_BUFFER, null); >+ wtu.clearAndDrawUnitQuad(gl); >+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "drawing unit quad"); >+ compareRect(width, height, channels, uncompressedData, "NEAREST"); >+} >+ >+function compareRect(width, height, channels, expectedData, filteringMode) { >+ var actual = new Uint8Array(width * height * 4); >+ gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, actual); >+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "reading back pixels"); >+ >+ var div = document.createElement("div"); >+ div.className = "testimages"; >+ ctu.insertCaptionedImg(div, "expected", ctu.makeScaledImage(width, height, width, expectedData, true)); >+ ctu.insertCaptionedImg(div, "actual", ctu.makeScaledImage(width, height, width, actual, true)); >+ div.appendChild(document.createElement('br')); >+ document.getElementById("console").appendChild(div); >+ >+ var failed = false; >+ for (var yy = 0; yy < height; ++yy) { >+ for (var xx = 0; xx < width; ++xx) { >+ var offset = (yy * width + xx) * 4; >+ var expected = expectedData.slice(offset, offset + 4); >+ // Compare RGB values >+ for (var jj = 0; jj < 3; ++jj) { >+ // Acceptable interpolation error depends on endpoints: >+ // 1.0 / 255.0 + 0.03 * max(abs(endpoint0 - endpoint1), abs(endpoint0_p - endpoint1_p)) >+ // For simplicity, assume the worst case (e0 is 0.0, e1 is 1.0). After conversion to unorm8, it is 9. >+ if (Math.abs(actual[offset + jj] - expected[jj]) > 9) { >+ var was = actual[offset + 0].toString(); >+ for (var j = 1; j < 3; ++j) { >+ was += "," + actual[offset + j]; >+ } >+ failed = true; >+ testFailed('RGB at (' + xx + ', ' + yy + >+ ') expected: ' + expected + ' ± 9 was ' + was); >+ } >+ } >+ >+ if (channels == 3) { >+ // BC1 RGB is allowed to be mapped to BC1 RGBA. >+ // In such a case, 3-color mode black value can be transparent: >+ // [0, 0, 0, 0] instead of [0, 0, 0, 255]. >+ >+ if (actual[offset + 3] != expected[3]) { >+ // Got non-opaque value for opaque format >+ >+ // Check RGB values. Notice, that the condition here >+ // is more permissive than needed since we don't have >+ // compressed data at this point. >+ if (actual[offset] == 0 && >+ actual[offset + 1] == 0 && >+ actual[offset + 2] == 0 && >+ actual[offset + 3] == 0) { >+ debug("<b>DXT1 RGB is mapped to DXT1 RGBA</b>"); >+ } else { >+ failed = true; >+ testFailed('Alpha at (' + xx + ', ' + yy + >+ ') expected: ' + expected[3] + ' was ' + actual[offset + 3]); >+ } >+ } >+ } else { >+ // Compare Alpha values >+ // Acceptable interpolation error depends on endpoints: >+ // 1.0 / 65535.0 + 0.03 * max(abs(endpoint0 - endpoint1), abs(endpoint0_p - endpoint1_p)) >+ // For simplicity, assume the worst case (e0 is 0.0, e1 is 1.0). After conversion to unorm8, it is 8. >+ if (Math.abs(actual[offset + 3] - expected[3]) > 8) { >+ var was = actual[offset + 3].toString(); >+ failed = true; >+ testFailed('Alpha at (' + xx + ', ' + yy + >+ ') expected: ' + expected + ' ± 8 was ' + was); >+ } >+ } >+ } >+ } >+ if (!failed) { >+ testPassed("texture rendered correctly with " + filteringMode + " filtering"); >+ } >+} >+ >+debug(""); >+var successfullyParsed = true; >+</script> >+<script src="../../js/js-test-post.js"></script> >+ >+</body> >+</html> >diff --git a/LayoutTests/webgl/resources/webgl_test_files/js/tests/compressed-texture-utils.js b/LayoutTests/webgl/resources/webgl_test_files/js/tests/compressed-texture-utils.js >new file mode 100644 >index 0000000000000000000000000000000000000000..d6f02c4d43b39f0aa4853e7489f4058fc2d6bcf5 >--- /dev/null >+++ b/LayoutTests/webgl/resources/webgl_test_files/js/tests/compressed-texture-utils.js >@@ -0,0 +1,229 @@ >+/* >+Copyright (c) 2019 The Khronos Group Inc. >+Use of this source code is governed by an MIT-style license that can be >+found in the LICENSE.txt file. >+*/ >+ >+"use strict"; >+ >+let CompressedTextureUtils = (function() { >+ >+let formatToString = function(ext, format) { >+ for (let p in ext) { >+ if (ext[p] == format) { >+ return p; >+ } >+ } >+ return "0x" + format.toString(16); >+}; >+ >+/** >+ * Make an image element from Uint8Array bitmap data. >+ * @param {number} imageHeight Height of the data in pixels. >+ * @param {number} imageWidth Width of the data in pixels. >+ * @param {number} dataWidth Width of each row in the data buffer, in pixels. >+ * @param {Uint8Array} data Image data buffer to display. Each pixel takes up 4 bytes in the array regardless of the alpha parameter. >+ * @param {boolean} alpha True if alpha data should be taken from data. Otherwise alpha channel is set to 255. >+ * @return {HTMLImageElement} The image element. >+ */ >+let makeScaledImage = function(imageWidth, imageHeight, dataWidth, data, alpha, opt_scale) { >+ let scale = opt_scale ? opt_scale : 8; >+ let c = document.createElement("canvas"); >+ c.width = imageWidth * scale; >+ c.height = imageHeight * scale; >+ let ctx = c.getContext("2d"); >+ for (let yy = 0; yy < imageHeight; ++yy) { >+ for (let xx = 0; xx < imageWidth; ++xx) { >+ let offset = (yy * dataWidth + xx) * 4; >+ ctx.fillStyle = "rgba(" + >+ data[offset + 0] + "," + >+ data[offset + 1] + "," + >+ data[offset + 2] + "," + >+ (alpha ? data[offset + 3] / 255 : 1) + ")"; >+ ctx.fillRect(xx * scale, yy * scale, scale, scale); >+ } >+ } >+ return wtu.makeImageFromCanvas(c); >+}; >+ >+let insertCaptionedImg = function(parent, caption, img) { >+ let div = document.createElement("div"); >+ div.appendChild(img); >+ let label = document.createElement("div"); >+ label.appendChild(document.createTextNode(caption)); >+ div.appendChild(label); >+ parent.appendChild(div); >+}; >+ >+/** >+ * @param {WebGLRenderingContextBase} gl >+ * @param {Object} compressedFormats Mapping from format names to format enum values. >+ * @param expectedByteLength A function that takes in width, height and format and returns the expected buffer size in bytes. >+ */ >+let testCompressedFormatsUnavailableWhenExtensionDisabled = function(gl, compressedFormats, expectedByteLength, testSize) { >+ let tex = gl.createTexture(); >+ gl.bindTexture(gl.TEXTURE_2D, tex); >+ for (let name in compressedFormats) { >+ if (compressedFormats.hasOwnProperty(name)) { >+ gl.compressedTexImage2D(gl.TEXTURE_2D, 0, compressedFormats[name], testSize, testSize, 0, new Uint8Array(expectedByteLength(testSize, testSize, compressedFormats[name]))); >+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "Trying to use format " + name + " with extension disabled."); >+ } >+ } >+ gl.bindTexture(gl.TEXTURE_2D, null); >+ gl.deleteTexture(tex); >+}; >+ >+/** >+ * @param {WebGLRenderingContextBase} gl >+ * @param {Object} expectedFormats Mapping from format names to format enum values. >+ */ >+let testCompressedFormatsListed = function(gl, expectedFormats) { >+ debug(""); >+ debug("Testing that every format is listed by the compressed texture formats query"); >+ >+ let supportedFormats = gl.getParameter(gl.COMPRESSED_TEXTURE_FORMATS); >+ >+ let failed; >+ let count = 0; >+ for (let name in expectedFormats) { >+ if (expectedFormats.hasOwnProperty(name)) { >+ ++count; >+ let format = expectedFormats[name]; >+ failed = true; >+ for (let ii = 0; ii < supportedFormats.length; ++ii) { >+ if (format == supportedFormats[ii]) { >+ testPassed("supported format " + name + " exists"); >+ failed = false; >+ break; >+ } >+ } >+ if (failed) { >+ testFailed("supported format " + name + " does not exist"); >+ } >+ } >+ } >+ if (supportedFormats.length != count) { >+ testFailed("Incorrect number of supported formats, was " + supportedFormats.length + " should be " + count); >+ } >+}; >+ >+/** >+ * @param {Object} ext Compressed texture extension object. >+ * @param {Object} expectedFormats Mapping from format names to format enum values. >+ */ >+let testCorrectEnumValuesInExt = function(ext, expectedFormats) { >+ debug(""); >+ debug("Testing that format enum values in the extension object are correct"); >+ >+ for (name in expectedFormats) { >+ if (expectedFormats.hasOwnProperty(name)) { >+ if (isResultCorrect(ext[name], expectedFormats[name])) { >+ testPassed("Enum value for " + name + " matches 0x" + ext[name].toString(16)); >+ } else { >+ testFailed("Enum value for " + name + " mismatch: 0x" + ext[name].toString(16) + " should be 0x" + expectedFormats[name].toString(16)); >+ } >+ } >+ } >+}; >+ >+/** >+ * @param {WebGLRenderingContextBase} gl >+ * @param {Object} validFormats Mapping from format names to format enum values. >+ * @param expectedByteLength A function that takes in width, height and format and returns the expected buffer size in bytes. >+ * @param getBlockDimensions A function that takes in a format and returns block size in pixels. >+ */ >+let testFormatRestrictionsOnBufferSize = function(gl, validFormats, expectedByteLength, getBlockDimensions) { >+ debug(""); >+ debug("Testing format restrictions on texture upload buffer size"); >+ >+ let tex = gl.createTexture(); >+ gl.bindTexture(gl.TEXTURE_2D, tex); >+ for (let formatId in validFormats) { >+ if (validFormats.hasOwnProperty(formatId)) { >+ let format = validFormats[formatId]; >+ let blockSize = getBlockDimensions(format); >+ let expectedSize = expectedByteLength(blockSize.width * 4, blockSize.height * 4, format); >+ let data = new Uint8Array(expectedSize); >+ gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, blockSize.width * 3, blockSize.height * 4, 0, data); >+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, formatId + " data size does not match dimensions (too small width)"); >+ gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, blockSize.width * 5, blockSize.height * 4, 0, data); >+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, formatId + " data size does not match dimensions (too large width)"); >+ gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, blockSize.width * 4, blockSize.height * 3, 0, data); >+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, formatId + " data size does not match dimensions (too small height)"); >+ gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, blockSize.width * 4, blockSize.height * 5, 0, data); >+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, formatId + " data size does not match dimensions (too large height)"); >+ } >+ } >+}; >+ >+/** >+ * @param {WebGLRenderingContextBase} gl >+ * @param {Object} validFormats Mapping from format names to format enum values. >+ * @param expectedByteLength A function that takes in width, height and format and returns the expected buffer size in bytes. >+ * @param getBlockDimensions A function that takes in a format and returns block size in pixels. >+ * @param {number} width Width of the image in pixels. >+ * @param {number} height Height of the image in pixels. >+ * @param {Object} subImageConfigs configs for compressedTexSubImage calls >+ */ >+let testTexSubImageDimensions = function(gl, validFormats, expectedByteLength, getBlockDimensions, width, height, subImageConfigs) { >+ let tex = gl.createTexture(); >+ gl.bindTexture(gl.TEXTURE_2D, tex); >+ >+ for (let formatId in validFormats) { >+ if (validFormats.hasOwnProperty(formatId)) { >+ let format = validFormats[formatId]; >+ let blockSize = getBlockDimensions(format); >+ let expectedSize = expectedByteLength(width, height, format); >+ let data = new Uint8Array(expectedSize); >+ >+ gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height, 0, data); >+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "setting up compressed texture"); >+ >+ for (let i = 0, len = subImageConfigs.length; i < len; ++i) { >+ let c = subImageConfigs[i]; >+ let subData = new Uint8Array(expectedByteLength(c.width, c.height, format)); >+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, c.xoffset, c.yoffset, c.width, c.height, format, subData); >+ wtu.glErrorShouldBe(gl, c.expectation, c.message); >+ } >+ } >+ } >+ >+ gl.bindTexture(gl.TEXTURE_2D, null); >+ gl.deleteTexture(tex); >+}; >+ >+let testTexImageLevelDimensions = function(gl, validFormats, expectedByteLength, getBlockDimensions, imageConfigs) { >+ let tex = gl.createTexture(); >+ gl.bindTexture(gl.TEXTURE_2D, tex); >+ >+ for (let formatId in validFormats) { >+ if (validFormats.hasOwnProperty(formatId)) { >+ let format = validFormats[formatId]; >+ let blockSize = getBlockDimensions(format); >+ >+ for (let i = 0, len = imageConfigs.length; i < len; ++i) { >+ let c = imageConfigs[i]; >+ let data = new Uint8Array(expectedByteLength(c.width, c.height, format)); >+ gl.compressedTexImage2D(gl.TEXTURE_2D, c.level, format, c.width, c.height, 0, data); >+ wtu.glErrorShouldBe(gl, c.expectation, c.message); >+ } >+ } >+ } >+ >+ gl.bindTexture(gl.TEXTURE_2D, null); >+ gl.deleteTexture(tex); >+} >+ >+return { >+ formatToString: formatToString, >+ insertCaptionedImg: insertCaptionedImg, >+ makeScaledImage: makeScaledImage, >+ testCompressedFormatsListed: testCompressedFormatsListed, >+ testCompressedFormatsUnavailableWhenExtensionDisabled: testCompressedFormatsUnavailableWhenExtensionDisabled, >+ testCorrectEnumValuesInExt: testCorrectEnumValuesInExt, >+ testFormatRestrictionsOnBufferSize: testFormatRestrictionsOnBufferSize, >+ testTexSubImageDimensions: testTexSubImageDimensions, >+ testTexImageLevelDimensions: testTexImageLevelDimensions, >+}; >+ >+})(); >\ No newline at end of file
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 217198
:
410284
|
410383
|
410704
|
410784
|
410868