Diff
Modified: trunk/LayoutTests/ChangeLog (208909 => 208910)
--- trunk/LayoutTests/ChangeLog 2016-11-19 00:58:54 UTC (rev 208909)
+++ trunk/LayoutTests/ChangeLog 2016-11-19 01:00:16 UTC (rev 208910)
@@ -1,3 +1,13 @@
+2016-11-18 Myles C. Maxfield <mmaxfi...@apple.com>
+
+ [WebGL2] Implement texStorage2D()
+ https://bugs.webkit.org/show_bug.cgi?id=164493
+
+ Reviewed by Dean Jackson.
+
+ * fast/canvas/webgl/webgl2-texStorage-expected.txt: Added.
+ * fast/canvas/webgl/webgl2-texStorage.html: Added.
+
2016-11-17 Alex Christensen <achristen...@webkit.org>
Support IDN2008 with UTS #46 instead of IDN2003
Added: trunk/LayoutTests/fast/canvas/webgl/webgl2-texStorage-expected.txt (0 => 208910)
--- trunk/LayoutTests/fast/canvas/webgl/webgl2-texStorage-expected.txt (rev 0)
+++ trunk/LayoutTests/fast/canvas/webgl/webgl2-texStorage-expected.txt 2016-11-19 01:00:16 UTC (rev 208910)
@@ -0,0 +1,159 @@
+CONSOLE MESSAGE: line 58: WebGL: INVALID_OPERATION: texStorage2D: texStorage2D already called on this texture
+CONSOLE MESSAGE: line 61: WebGL: INVALID_OPERATION: texImage2D: texStorage() called on this texture previously
+Test that texStorage2D() works.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+asdf
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.checkFramebufferStatus(gl.FRAMEBUFFER) is gl.FRAMEBUFFER_COMPLETE
+PASS gl.getError() is gl.NO_ERROR
+PASS receiver[i] is 0
+PASS receiver[i] is 0
+PASS receiver[i] is 0
+PASS receiver[i] is 0
+PASS receiver[i] is 0
+PASS receiver[i] is 0
+PASS receiver[i] is 0
+PASS receiver[i] is 0
+PASS receiver[i] is 0
+PASS receiver[i] is 0
+PASS receiver[i] is 0
+PASS receiver[i] is 0
+PASS receiver[i] is 0
+PASS receiver[i] is 0
+PASS receiver[i] is 0
+PASS receiver[i] is 0
+PASS receiver[i] is 0
+PASS receiver[i] is 0
+PASS receiver[i] is 0
+PASS receiver[i] is 0
+PASS receiver[i] is 0
+PASS receiver[i] is 0
+PASS receiver[i] is 0
+PASS receiver[i] is 0
+PASS receiver[i] is 0
+PASS receiver[i] is 0
+PASS receiver[i] is 0
+PASS receiver[i] is 0
+PASS receiver[i] is 0
+PASS receiver[i] is 0
+PASS receiver[i] is 0
+PASS receiver[i] is 0
+PASS receiver[i] is 0
+PASS receiver[i] is 0
+PASS receiver[i] is 0
+PASS receiver[i] is 0
+PASS receiver[i] is 0
+PASS receiver[i] is 0
+PASS receiver[i] is 0
+PASS receiver[i] is 0
+PASS receiver[i] is 0
+PASS receiver[i] is 0
+PASS receiver[i] is 0
+PASS receiver[i] is 0
+PASS receiver[i] is 0
+PASS receiver[i] is 0
+PASS receiver[i] is 0
+PASS receiver[i] is 0
+PASS receiver[i] is 0
+PASS receiver[i] is 0
+PASS receiver[i] is 0
+PASS receiver[i] is 0
+PASS receiver[i] is 0
+PASS receiver[i] is 0
+PASS receiver[i] is 0
+PASS receiver[i] is 0
+PASS receiver[i] is 0
+PASS receiver[i] is 0
+PASS receiver[i] is 0
+PASS receiver[i] is 0
+PASS receiver[i] is 0
+PASS receiver[i] is 0
+PASS receiver[i] is 0
+PASS receiver[i] is 0
+PASS gl.getError() is not gl.NO_ERROR
+PASS gl.getError() is not gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS receiver[i] is 1
+PASS receiver[i] is 1
+PASS receiver[i] is 1
+PASS receiver[i] is 1
+PASS receiver[i] is 1
+PASS receiver[i] is 1
+PASS receiver[i] is 1
+PASS receiver[i] is 1
+PASS receiver[i] is 1
+PASS receiver[i] is 1
+PASS receiver[i] is 1
+PASS receiver[i] is 1
+PASS receiver[i] is 1
+PASS receiver[i] is 1
+PASS receiver[i] is 1
+PASS receiver[i] is 1
+PASS receiver[i] is 1
+PASS receiver[i] is 1
+PASS receiver[i] is 1
+PASS receiver[i] is 1
+PASS receiver[i] is 1
+PASS receiver[i] is 1
+PASS receiver[i] is 1
+PASS receiver[i] is 1
+PASS receiver[i] is 1
+PASS receiver[i] is 1
+PASS receiver[i] is 1
+PASS receiver[i] is 1
+PASS receiver[i] is 1
+PASS receiver[i] is 1
+PASS receiver[i] is 1
+PASS receiver[i] is 1
+PASS receiver[i] is 1
+PASS receiver[i] is 1
+PASS receiver[i] is 1
+PASS receiver[i] is 1
+PASS receiver[i] is 1
+PASS receiver[i] is 1
+PASS receiver[i] is 1
+PASS receiver[i] is 1
+PASS receiver[i] is 1
+PASS receiver[i] is 1
+PASS receiver[i] is 1
+PASS receiver[i] is 1
+PASS receiver[i] is 1
+PASS receiver[i] is 1
+PASS receiver[i] is 1
+PASS receiver[i] is 1
+PASS receiver[i] is 1
+PASS receiver[i] is 1
+PASS receiver[i] is 1
+PASS receiver[i] is 1
+PASS receiver[i] is 1
+PASS receiver[i] is 1
+PASS receiver[i] is 1
+PASS receiver[i] is 1
+PASS receiver[i] is 1
+PASS receiver[i] is 1
+PASS receiver[i] is 1
+PASS receiver[i] is 1
+PASS receiver[i] is 1
+PASS receiver[i] is 1
+PASS receiver[i] is 1
+PASS receiver[i] is 1
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: trunk/LayoutTests/fast/canvas/webgl/webgl2-texStorage.html (0 => 208910)
--- trunk/LayoutTests/fast/canvas/webgl/webgl2-texStorage.html (rev 0)
+++ trunk/LayoutTests/fast/canvas/webgl/webgl2-texStorage.html 2016-11-19 01:00:16 UTC (rev 208910)
@@ -0,0 +1,88 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<canvas id="canvas" width="40" height="40"></canvas>
+<script>
+description("Test that texStorage2D() works.");
+
+if (window.internals)
+ internals.setWebGL2Enabled(true);
+
+var canvas = document.getElementById("canvas");
+var width = canvas.width;
+var height = canvas.height;
+var gl = canvas.getContext("webgl2");
+shouldBe("gl.getError()", "gl.NO_ERROR");
+
+var texture = gl.createTexture();
+shouldBe("gl.getError()", "gl.NO_ERROR");
+gl.bindTexture(gl.TEXTURE_2D, texture);
+shouldBe("gl.getError()", "gl.NO_ERROR");
+gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+shouldBe("gl.getError()", "gl.NO_ERROR");
+gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+shouldBe("gl.getError()", "gl.NO_ERROR");
+gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
+shouldBe("gl.getError()", "gl.NO_ERROR");
+gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
+shouldBe("gl.getError()", "gl.NO_ERROR");
+
+var width = 4;
+var height = 4;
+debug("asdf");
+gl.texStorage2D(gl.TEXTURE_2D, 1, gl.RGBA8, width, height);
+shouldBe("gl.getError()", "gl.NO_ERROR");
+
+var framebuffer = gl.createFramebuffer();
+shouldBe("gl.getError()", "gl.NO_ERROR");
+gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
+shouldBe("gl.getError()", "gl.NO_ERROR");
+gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
+shouldBe("gl.getError()", "gl.NO_ERROR");
+shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
+
+var receiver = new Uint8Array(width * height * 4);
+for (var i = 0; i < width * height * 4; ++i) {
+ receiver[i] = 1;
+}
+
+gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, receiver);
+shouldBe("gl.getError()", "gl.NO_ERROR");
+for (var i = 0; i < width * height * 4; ++i) {
+ shouldBe("receiver[i]", "0");
+}
+
+gl.texStorage2D(gl.TEXTURE_2D, 1, gl.RGBA8, width, height);
+shouldNotBe("gl.getError()", "gl.NO_ERROR");
+
+gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA8, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, receiver);
+shouldNotBe("gl.getError()", "gl.NO_ERROR");
+
+for (var i = 0; i < width * height * 4; ++i) {
+ receiver[i] = 1;
+}
+gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, receiver);
+shouldBe("gl.getError()", "gl.NO_ERROR");
+
+for (var i = 0; i < width * height * 4; ++i) {
+ receiver[i] = 0;
+}
+gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, receiver);
+shouldBe("gl.getError()", "gl.NO_ERROR");
+
+for (var i = 0; i < width * height * 4; ++i) {
+ shouldBe("receiver[i]", "1");
+}
+
+gl.deleteFramebuffer(framebuffer);
+shouldBe("gl.getError()", "gl.NO_ERROR");
+
+gl.deleteTexture(texture);
+shouldBe("gl.getError()", "gl.NO_ERROR");
+</script>
+<script src=""
+</body>
+</html>
\ No newline at end of file
Modified: trunk/Source/WebCore/ChangeLog (208909 => 208910)
--- trunk/Source/WebCore/ChangeLog 2016-11-19 00:58:54 UTC (rev 208909)
+++ trunk/Source/WebCore/ChangeLog 2016-11-19 01:00:16 UTC (rev 208910)
@@ -1,3 +1,61 @@
+2016-11-18 Myles C. Maxfield <mmaxfi...@apple.com>
+
+ [WebGL2] Implement texStorage2D()
+ https://bugs.webkit.org/show_bug.cgi?id=164493
+
+ Reviewed by Dean Jackson.
+
+ Create a new validation function which only accepts sized internalFormats.
+ After running texStorage2D(), we also texSubImage2D() to zero-fill it. This
+ is to compensate for potentially buggy drivers.
+
+ Because glTexStorage2D() was only added to OpenGL in version 4.2, not all
+ OpenGL 3.2+ contexts can implement this command. However, according to
+ https://developer.apple.com/opengl/capabilities/ all Apple GPUs have the
+ GL_ARB_texture_storage which implements this call. In the future, we could
+ implement texStorage2D() on top of texImage2D() if there are any ports which
+ want WebGL2 but don't have 4.2 and don't have the extension.
+
+ Also, when calling texStorage2D, callers specify an internalFormat but not a
+ type/format pair. This means that storing the texture's type is only valid
+ for WebGL 1 contexts. This patch surrounds all calls to reading the texture
+ type with guards and adds an ASSERT() at the read site to make sure the
+ right thing is happening.
+
+ Test: fast/canvas/webgl/webgl2-texStorage.html
+
+ * html/canvas/WebGL2RenderingContext.cpp:
+ (WebCore::WebGL2RenderingContext::validateTexStorageFuncParameters):
+ (WebCore::WebGL2RenderingContext::texStorage2D):
+ * html/canvas/WebGL2RenderingContext.h:
+ * html/canvas/WebGLRenderingContext.cpp:
+ (WebCore::WebGLRenderingContext::validateIndexArrayConservative):
+ * html/canvas/WebGLRenderingContextBase.cpp:
+ (WebCore::WebGLRenderingContextBase::create):
+ (WebCore::WebGLRenderingContextBase::copyTexSubImage2D):
+ (WebCore::WebGLRenderingContextBase::validateTexFunc):
+ (WebCore::WebGLRenderingContextBase::validateTexFuncData):
+ (WebCore::WebGLRenderingContextBase::texImage2D):
+ * html/canvas/WebGLTexture.cpp:
+ (WebCore::WebGLTexture::WebGLTexture):
+ (WebCore::WebGLTexture::getType):
+ (WebCore::WebGLTexture::needToUseBlackTexture):
+ (WebCore::WebGLTexture::canGenerateMipmaps):
+ (WebCore::internalFormatIsFloatType):
+ (WebCore::internalFormatIsHalfFloatType):
+ (WebCore::WebGLTexture::update):
+ * html/canvas/WebGLTexture.h:
+ * platform/graphics/GraphicsContext3D.cpp:
+ (WebCore::GraphicsContext3D::texImage2DResourceSafe):
+ (WebCore::GraphicsContext3D::packImageData):
+ (WebCore::GraphicsContext3D::extractImageData):
+ * platform/graphics/GraphicsContext3D.h:
+ * platform/graphics/opengl/Extensions3DOpenGLCommon.cpp:
+ (WebCore::Extensions3DOpenGLCommon::initializeAvailableExtensions):
+ * platform/graphics/opengl/GraphicsContext3DOpenGLCommon.cpp:
+ (WebCore::GraphicsContext3D::texStorage2D):
+ (WebCore::GraphicsContext3D::texStorage3D):
+
2016-11-18 Alex Christensen <achristen...@webkit.org>
TextDecoder constructor should not accept replacement encodings
Modified: trunk/Source/WebCore/html/canvas/WebGL2RenderingContext.cpp (208909 => 208910)
--- trunk/Source/WebCore/html/canvas/WebGL2RenderingContext.cpp 2016-11-19 00:58:54 UTC (rev 208909)
+++ trunk/Source/WebCore/html/canvas/WebGL2RenderingContext.cpp 2016-11-19 01:00:16 UTC (rev 208910)
@@ -312,10 +312,169 @@
{
}
-void WebGL2RenderingContext::texStorage2D(GC3Denum, GC3Dsizei, GC3Denum, GC3Dsizei, GC3Dsizei)
+bool WebGL2RenderingContext::validateTexStorageFuncParameters(GC3Denum target, GC3Dsizei levels, GC3Denum internalFormat, GC3Dsizei width, GC3Dsizei height, const char* functionName)
{
+ if (width < 0 || height < 0) {
+ synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "width or height < 0");
+ return false;
+ }
+
+ if (width > m_maxTextureSize || height > m_maxTextureSize) {
+ synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "texture dimensions are larger than the maximum texture size");
+ return false;
+ }
+
+ if (target == GraphicsContext3D::TEXTURE_CUBE_MAP) {
+ if (width != height) {
+ synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "width != height for cube map");
+ return false;
+ }
+ } else if (target != GraphicsContext3D::TEXTURE_2D) {
+ synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid target");
+ return false;
+ }
+
+ if (levels < 0 || levels > m_maxTextureLevel) {
+ synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "number of levels is out of bounds");
+ return false;
+ }
+
+ switch (internalFormat) {
+ case GraphicsContext3D::R8:
+ case GraphicsContext3D::R8_SNORM:
+ case GraphicsContext3D::R16F:
+ case GraphicsContext3D::R32F:
+ case GraphicsContext3D::R8UI:
+ case GraphicsContext3D::R8I:
+ case GraphicsContext3D::R16UI:
+ case GraphicsContext3D::R16I:
+ case GraphicsContext3D::R32UI:
+ case GraphicsContext3D::R32I:
+ case GraphicsContext3D::RG8:
+ case GraphicsContext3D::RG8_SNORM:
+ case GraphicsContext3D::RG16F:
+ case GraphicsContext3D::RG32F:
+ case GraphicsContext3D::RG8UI:
+ case GraphicsContext3D::RG8I:
+ case GraphicsContext3D::RG16UI:
+ case GraphicsContext3D::RG16I:
+ case GraphicsContext3D::RG32UI:
+ case GraphicsContext3D::RG32I:
+ case GraphicsContext3D::RGB8:
+ case GraphicsContext3D::SRGB8:
+ case GraphicsContext3D::RGB565:
+ case GraphicsContext3D::RGB8_SNORM:
+ case GraphicsContext3D::R11F_G11F_B10F:
+ case GraphicsContext3D::RGB9_E5:
+ case GraphicsContext3D::RGB16F:
+ case GraphicsContext3D::RGB32F:
+ case GraphicsContext3D::RGB8UI:
+ case GraphicsContext3D::RGB8I:
+ case GraphicsContext3D::RGB16UI:
+ case GraphicsContext3D::RGB16I:
+ case GraphicsContext3D::RGB32UI:
+ case GraphicsContext3D::RGB32I:
+ case GraphicsContext3D::RGBA8:
+ case GraphicsContext3D::SRGB8_ALPHA8:
+ case GraphicsContext3D::RGBA8_SNORM:
+ case GraphicsContext3D::RGB5_A1:
+ case GraphicsContext3D::RGBA4:
+ case GraphicsContext3D::RGB10_A2:
+ case GraphicsContext3D::RGBA16F:
+ case GraphicsContext3D::RGBA32F:
+ case GraphicsContext3D::RGBA8UI:
+ case GraphicsContext3D::RGBA8I:
+ case GraphicsContext3D::RGB10_A2UI:
+ case GraphicsContext3D::RGBA16UI:
+ case GraphicsContext3D::RGBA16I:
+ case GraphicsContext3D::RGBA32I:
+ case GraphicsContext3D::RGBA32UI:
+ case GraphicsContext3D::DEPTH_COMPONENT16:
+ case GraphicsContext3D::DEPTH_COMPONENT24:
+ case GraphicsContext3D::DEPTH_COMPONENT32F:
+ case GraphicsContext3D::DEPTH24_STENCIL8:
+ case GraphicsContext3D::DEPTH32F_STENCIL8:
+ break;
+ default:
+ synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "Unknown internalFormat");
+ return false;
+ }
+
+ return true;
}
+void WebGL2RenderingContext::texStorage2D(GC3Denum target, GC3Dsizei levels, GC3Denum internalFormat, GC3Dsizei width, GC3Dsizei height)
+{
+ if (isContextLostOrPending())
+ return;
+
+ WebGLTexture* texture = validateTextureBinding("texStorage2D", target, false);
+ if (!texture)
+ return;
+
+ if (!validateTexStorageFuncParameters(target, levels, internalFormat, width, height, "texStorage2D"))
+ return;
+
+ if (!validateNPOTTextureLevel(width, height, levels, "texStorage2D"))
+ return;
+
+ if (texture->immutable()) {
+ synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "texStorage2D", "texStorage2D already called on this texture");
+ return;
+ }
+ texture->setImmutable();
+
+ m_context->texStorage2D(target, levels, internalFormat, width, height);
+
+ {
+ GC3Denum format;
+ GC3Denum type;
+ if (!GraphicsContext3D::possibleFormatAndTypeForInternalFormat(internalFormat, format, type)) {
+ synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "texStorage2D", "Texture has unknown internal format");
+ return;
+ }
+
+ GC3Dsizei levelWidth = width;
+ GC3Dsizei levelHeight = height;
+
+ unsigned size;
+ GC3Denum error = m_context->computeImageSizeInBytes(format, type, width, height, m_unpackAlignment, &size, nullptr);
+ if (error != GraphicsContext3D::NO_ERROR) {
+ synthesizeGLError(error, "texStorage2D", "bad dimensions");
+ return;
+ }
+
+ Vector<char> data(size);
+ memset(data.data(), 0, size);
+
+ for (GC3Dsizei level = 0; level < levels; ++level) {
+ if (target == GraphicsContext3D::TEXTURE_CUBE_MAP) {
+ m_context->texSubImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_X, level, 0, 0, levelWidth, levelHeight, format, type, data.data());
+ m_context->texSubImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_X, level, 0, 0, levelWidth, levelHeight, format, type, data.data());
+ m_context->texSubImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Y, level, 0, 0, levelWidth, levelHeight, format, type, data.data());
+ m_context->texSubImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Y, level, 0, 0, levelWidth, levelHeight, format, type, data.data());
+ m_context->texSubImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Z, level, 0, 0, levelWidth, levelHeight, format, type, data.data());
+ m_context->texSubImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Z, level, 0, 0, levelWidth, levelHeight, format, type, data.data());
+ } else
+ m_context->texSubImage2D(target, level, 0, 0, levelWidth, levelHeight, format, type, data.data());
+ levelWidth = std::max(1, levelWidth / 2);
+ levelHeight = std::max(1, levelHeight / 2);
+ }
+ }
+
+ for (GC3Dsizei level = 0; level < levels; ++level) {
+ if (target == GraphicsContext3D::TEXTURE_CUBE_MAP) {
+ texture->setLevelInfo(GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_X, level, internalFormat, width, height, GraphicsContext3D::UNSIGNED_BYTE);
+ texture->setLevelInfo(GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_X, level, internalFormat, width, height, GraphicsContext3D::UNSIGNED_BYTE);
+ texture->setLevelInfo(GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Y, level, internalFormat, width, height, GraphicsContext3D::UNSIGNED_BYTE);
+ texture->setLevelInfo(GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Y, level, internalFormat, width, height, GraphicsContext3D::UNSIGNED_BYTE);
+ texture->setLevelInfo(GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Z, level, internalFormat, width, height, GraphicsContext3D::UNSIGNED_BYTE);
+ texture->setLevelInfo(GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Z, level, internalFormat, width, height, GraphicsContext3D::UNSIGNED_BYTE);
+ } else
+ texture->setLevelInfo(target, level, internalFormat, width, height, GraphicsContext3D::UNSIGNED_BYTE);
+ }
+}
+
void WebGL2RenderingContext::texStorage3D(GC3Denum, GC3Dsizei, GC3Denum, GC3Dsizei, GC3Dsizei, GC3Dsizei)
{
}
Modified: trunk/Source/WebCore/html/canvas/WebGL2RenderingContext.h (208909 => 208910)
--- trunk/Source/WebCore/html/canvas/WebGL2RenderingContext.h 2016-11-19 00:58:54 UTC (rev 208909)
+++ trunk/Source/WebCore/html/canvas/WebGL2RenderingContext.h 2016-11-19 01:00:16 UTC (rev 208910)
@@ -64,8 +64,8 @@
void renderbufferStorageMultisample(GC3Denum target, GC3Dsizei samples, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height);
/* Texture objects */
- void texStorage2D(GC3Denum target, GC3Dsizei levels, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height);
- void texStorage3D(GC3Denum target, GC3Dsizei levels, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dsizei depth);
+ void texStorage2D(GC3Denum target, GC3Dsizei levels, GC3Denum internalFormat, GC3Dsizei width, GC3Dsizei height);
+ void texStorage3D(GC3Denum target, GC3Dsizei levels, GC3Denum internalFormat, GC3Dsizei width, GC3Dsizei height, GC3Dsizei depth);
void texImage3D(GC3Denum target, GC3Dint level, GC3Dint internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dsizei depth, GC3Dint border, GC3Denum format, GC3Denum type, RefPtr<ArrayBufferView>&& pixels);
void texSubImage3D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dint zoffset, GC3Dsizei width, GC3Dsizei height, GC3Dsizei depth, GC3Denum format, GC3Denum type, RefPtr<ArrayBufferView>&& pixels);
@@ -191,6 +191,8 @@
GC3Denum baseInternalFormatFromInternalFormat(GC3Denum internalformat);
bool isIntegerFormat(GC3Denum internalformat);
void initializeShaderExtensions();
+
+ bool validateTexStorageFuncParameters(GC3Denum target, GC3Dsizei levels, GC3Denum internalFormat, GC3Dsizei width, GC3Dsizei height, const char* functionName);
};
} // namespace WebCore
Modified: trunk/Source/WebCore/html/canvas/WebGLRenderingContext.cpp (208909 => 208910)
--- trunk/Source/WebCore/html/canvas/WebGLRenderingContext.cpp 2016-11-19 00:58:54 UTC (rev 208909)
+++ trunk/Source/WebCore/html/canvas/WebGLRenderingContext.cpp 2016-11-19 01:00:16 UTC (rev 208910)
@@ -772,9 +772,9 @@
}
default:
return false;
+ }
+ elementArrayBuffer->setCachedMaxIndex(type, maxIndex);
}
- elementArrayBuffer->setCachedMaxIndex(type, maxIndex);
- }
if (maxIndex >= 0) {
// The number of required elements is one more than the maximum
Modified: trunk/Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp (208909 => 208910)
--- trunk/Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp 2016-11-19 00:58:54 UTC (rev 208909)
+++ trunk/Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp 2016-11-19 01:00:16 UTC (rev 208910)
@@ -434,6 +434,13 @@
if (extensions.supports("GL_EXT_debug_marker"))
extensions.pushGroupMarkerEXT("WebGLRenderingContext");
+#if ENABLE(WEBGL2) && PLATFORM(MAC)
+ // glTexStorage() was only added to Core in OpenGL 4.2.
+ // However, according to https://developer.apple.com/opengl/capabilities/ all Apple GPUs support this extension.
+ if (attributes.useGLES3 && !extensions.supports("GL_ARB_texture_storage"))
+ return nullptr;
+#endif
+
std::unique_ptr<WebGLRenderingContextBase> renderingContext = nullptr;
#if ENABLE(WEBGL2)
if (type == "webgl2")
@@ -1365,7 +1372,7 @@
std::unique_ptr<unsigned char[]> zero;
if (width && height) {
unsigned size;
- GC3Denum error = m_context->computeImageSizeInBytes(format, type, width, height, m_unpackAlignment, &size, 0);
+ GC3Denum error = m_context->computeImageSizeInBytes(format, type, width, height, m_unpackAlignment, &size, nullptr);
if (error != GraphicsContext3D::NO_ERROR) {
synthesizeGLError(error, "copyTexSubImage2D", "bad dimensions");
return;
@@ -3311,6 +3318,10 @@
return false;
if (functionType != TexSubImage) {
+ if (functionType == TexImage && texture->immutable()) {
+ synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "texStorage() called on this texture previously");
+ return false;
+ }
if (!validateNPOTTextureLevel(width, height, level, functionName))
return false;
// For SourceArrayBufferView, function validateTexFuncData() would handle whether to validate the SettableTexFormat
@@ -3333,7 +3344,7 @@
synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "dimensions out of range");
return false;
}
- if (texture->getInternalFormat(target, level) != internalFormat || texture->getType(target, level) != type) {
+ if (texture->getInternalFormat(target, level) != internalFormat || (isWebGL1() && texture->getType(target, level) != type)) {
synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "type and format do not match texture");
return false;
}
@@ -3629,7 +3640,7 @@
return false;
unsigned totalBytesRequired;
- GC3Denum error = m_context->computeImageSizeInBytes(format, type, width, height, m_unpackAlignment, &totalBytesRequired, 0);
+ GC3Denum error = m_context->computeImageSizeInBytes(format, type, width, height, m_unpackAlignment, &totalBytesRequired, nullptr);
if (error != GraphicsContext3D::NO_ERROR) {
synthesizeGLError(error, functionName, "invalid texture dimensions");
return false;
@@ -3963,6 +3974,14 @@
tex->setLevelInfo(target, level, internalFormat, width, height, GraphicsContext3D::UNSIGNED_BYTE);
}
+static bool isRGBFormat(GC3Denum internalFormat)
+{
+ return internalFormat == GraphicsContext3D::RGB
+ || internalFormat == GraphicsContext3D::RGBA
+ || internalFormat == GraphicsContext3D::RGB8
+ || internalFormat == GraphicsContext3D::RGBA8;
+}
+
ExceptionOr<void> WebGLRenderingContextBase::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Denum format, GC3Denum type, Optional<TexImageSource> source)
{
if (!source) {
@@ -4023,12 +4042,14 @@
// ImageBuffer::copyToPlatformTexture implementations are fully functional.
if (texture
&& (format == GraphicsContext3D::RGB || format == GraphicsContext3D::RGBA)
- && type == GraphicsContext3D::UNSIGNED_BYTE
- && (texture->getType(target, level) == GraphicsContext3D::UNSIGNED_BYTE || !texture->isValid(target, level))) {
- ImageBuffer* buffer = canvas->buffer();
- if (buffer && buffer->copyToPlatformTexture(*m_context.get(), target, texture->object(), internalformat, m_unpackPremultiplyAlpha, m_unpackFlipY)) {
- texture->setLevelInfo(target, level, internalformat, canvas->width(), canvas->height(), type);
- return { };
+ && type == GraphicsContext3D::UNSIGNED_BYTE) {
+ auto textureInternalFormat = texture->getInternalFormat(target, level);
+ if (isRGBFormat(textureInternalFormat) || !texture->isValid(target, level)) {
+ ImageBuffer* buffer = canvas->buffer();
+ if (buffer && buffer->copyToPlatformTexture(*m_context.get(), target, texture->object(), internalformat, m_unpackPremultiplyAlpha, m_unpackFlipY)) {
+ texture->setLevelInfo(target, level, internalformat, canvas->width(), canvas->height(), type);
+ return { };
+ }
}
}
@@ -4053,11 +4074,13 @@
if (GraphicsContext3D::TEXTURE_2D == target && texture
&& (format == GraphicsContext3D::RGB || format == GraphicsContext3D::RGBA)
&& type == GraphicsContext3D::UNSIGNED_BYTE
- && (texture->getType(target, level) == GraphicsContext3D::UNSIGNED_BYTE || !texture->isValid(target, level))
&& !level) {
- if (video->copyVideoTextureToPlatformTexture(m_context.get(), texture->object(), target, level, internalformat, format, type, m_unpackPremultiplyAlpha, m_unpackFlipY)) {
- texture->setLevelInfo(target, level, internalformat, video->videoWidth(), video->videoHeight(), type);
- return { };
+ auto textureInternalFormat = texture->getInternalFormat(target, level);
+ if (isRGBFormat(textureInternalFormat) || !texture->isValid(target, level)) {
+ if (video->copyVideoTextureToPlatformTexture(m_context.get(), texture->object(), target, level, internalformat, format, type, m_unpackPremultiplyAlpha, m_unpackFlipY)) {
+ texture->setLevelInfo(target, level, internalformat, video->videoWidth(), video->videoHeight(), type);
+ return { };
+ }
}
}
Modified: trunk/Source/WebCore/html/canvas/WebGLTexture.cpp (208909 => 208910)
--- trunk/Source/WebCore/html/canvas/WebGLTexture.cpp 2016-11-19 00:58:54 UTC (rev 208909)
+++ trunk/Source/WebCore/html/canvas/WebGLTexture.cpp 2016-11-19 01:00:16 UTC (rev 208910)
@@ -53,6 +53,7 @@
, m_isCompressed(false)
, m_isFloatType(false)
, m_isHalfFloatType(false)
+ , m_isForWebGL1(ctx.isWebGL1())
{
setObject(ctx.graphicsContext3D()->createTexture());
}
@@ -188,6 +189,7 @@
GC3Denum WebGLTexture::getType(GC3Denum target, GC3Dint level) const
{
+ ASSERT(m_isForWebGL1);
const LevelInfo* info = getLevelInfo(target, level);
if (!info)
return 0;
@@ -250,10 +252,12 @@
return false;
if (m_needToUseBlackTexture)
return true;
- if ((m_isFloatType && !(extensions & TextureExtensionFloatLinearEnabled)) || (m_isHalfFloatType && !(extensions & TextureExtensionHalfFloatLinearEnabled))) {
- if (m_magFilter != GraphicsContext3D::NEAREST || (m_minFilter != GraphicsContext3D::NEAREST && m_minFilter != GraphicsContext3D::NEAREST_MIPMAP_NEAREST))
- return true;
- }
+ if (m_magFilter == GraphicsContext3D::NEAREST && (m_minFilter == GraphicsContext3D::NEAREST || m_minFilter == GraphicsContext3D::NEAREST_MIPMAP_NEAREST))
+ return false;
+ if (m_isForWebGL1 && m_isHalfFloatType && !(extensions & TextureExtensionHalfFloatLinearEnabled))
+ return true;
+ if (m_isFloatType && !(extensions & TextureExtensionFloatLinearEnabled))
+ return true;
return false;
}
@@ -308,7 +312,7 @@
const LevelInfo& info = m_info[ii][0];
if (!info.valid
|| info.width != first.width || info.height != first.height
- || info.internalFormat != first.internalFormat || info.type != first.type)
+ || info.internalFormat != first.internalFormat || (m_isForWebGL1 && info.type != first.type))
return false;
}
return true;
@@ -334,6 +338,36 @@
return log + 1;
}
+static bool internalFormatIsFloatType(GC3Denum internalFormat)
+{
+ switch (internalFormat) {
+ case GraphicsContext3D::R32F:
+ case GraphicsContext3D::RG32F:
+ case GraphicsContext3D::RGB32F:
+ case GraphicsContext3D::RGBA32F:
+ case GraphicsContext3D::DEPTH_COMPONENT32F:
+ case GraphicsContext3D::DEPTH32F_STENCIL8:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool internalFormatIsHalfFloatType(GC3Denum internalFormat)
+{
+ switch (internalFormat) {
+ case GraphicsContext3D::R16F:
+ case GraphicsContext3D::RG16F:
+ case GraphicsContext3D::R11F_G11F_B10F:
+ case GraphicsContext3D::RGB9_E5:
+ case GraphicsContext3D::RGB16F:
+ case GraphicsContext3D::RGBA16F:
+ return true;
+ default:
+ return false;
+ }
+}
+
void WebGLTexture::update()
{
m_isNPOT = false;
@@ -353,7 +387,7 @@
const LevelInfo& info0 = m_info[ii][0];
if (!info0.valid
|| info0.width != first.width || info0.height != first.height
- || info0.internalFormat != first.internalFormat || info0.type != first.type) {
+ || info0.internalFormat != first.internalFormat || (m_isForWebGL1 && info0.type != first.type)) {
m_isComplete = false;
break;
}
@@ -365,7 +399,7 @@
const LevelInfo& info = m_info[ii][level];
if (!info.valid
|| info.width != width || info.height != height
- || info.internalFormat != info0.internalFormat || info.type != info0.type) {
+ || info.internalFormat != info0.internalFormat || (m_isForWebGL1 && info.type != info0.type)) {
m_isComplete = false;
break;
}
@@ -375,25 +409,37 @@
}
m_isFloatType = false;
- if (m_isComplete)
- m_isFloatType = m_info[0][0].type == GraphicsContext3D::FLOAT;
- else {
- for (size_t ii = 0; ii < m_info.size(); ++ii) {
- if (m_info[ii][0].type == GraphicsContext3D::FLOAT) {
- m_isFloatType = true;
- break;
+ if (m_isForWebGL1) {
+ if (m_isComplete) {
+ if (m_isForWebGL1)
+ m_isFloatType = m_info[0][0].type == GraphicsContext3D::FLOAT;
+ else
+ m_isFloatType = internalFormatIsFloatType(m_info[0][0].internalFormat);
+ } else {
+ for (size_t ii = 0; ii < m_info.size(); ++ii) {
+ if ((m_isForWebGL1 && m_info[ii][0].type == GraphicsContext3D::FLOAT)
+ || (!m_isForWebGL1 && internalFormatIsFloatType(m_info[ii][0].internalFormat))) {
+ m_isFloatType = true;
+ break;
+ }
}
}
}
m_isHalfFloatType = false;
- if (m_isComplete)
- m_isHalfFloatType = m_info[0][0].type == GraphicsContext3D::HALF_FLOAT_OES;
- else {
- for (size_t ii = 0; ii < m_info.size(); ++ii) {
- if (m_info[ii][0].type == GraphicsContext3D::HALF_FLOAT_OES) {
- m_isHalfFloatType = true;
- break;
+ if (m_isForWebGL1) {
+ if (m_isComplete) {
+ if (m_isForWebGL1)
+ m_isHalfFloatType = internalFormatIsHalfFloatType(m_info[0][0].internalFormat);
+ else
+ m_isHalfFloatType = m_info[0][0].type == GraphicsContext3D::HALF_FLOAT_OES;
+ } else {
+ for (size_t ii = 0; ii < m_info.size(); ++ii) {
+ if ((m_isForWebGL1 && m_info[ii][0].type == GraphicsContext3D::HALF_FLOAT_OES)
+ || (!m_isForWebGL1 && internalFormatIsHalfFloatType(m_info[ii][0].internalFormat))) {
+ m_isHalfFloatType = true;
+ break;
+ }
}
}
}
Modified: trunk/Source/WebCore/html/canvas/WebGLTexture.h (208909 => 208910)
--- trunk/Source/WebCore/html/canvas/WebGLTexture.h 2016-11-19 00:58:54 UTC (rev 208909)
+++ trunk/Source/WebCore/html/canvas/WebGLTexture.h 2016-11-19 01:00:16 UTC (rev 208910)
@@ -78,6 +78,9 @@
static GC3Dint computeLevelCount(GC3Dsizei width, GC3Dsizei height);
+ bool immutable() const { return m_immutable; }
+ void setImmutable() { m_immutable = true; }
+
private:
WebGLTexture(WebGLRenderingContextBase&);
@@ -133,6 +136,8 @@
bool m_isCompressed;
bool m_isFloatType;
bool m_isHalfFloatType;
+ bool m_isForWebGL1;
+ bool m_immutable { false };
};
} // namespace WebCore
Modified: trunk/Source/WebCore/platform/graphics/GraphicsContext3D.cpp (208909 => 208910)
--- trunk/Source/WebCore/platform/graphics/GraphicsContext3D.cpp 2016-11-19 00:58:54 UTC (rev 208909)
+++ trunk/Source/WebCore/platform/graphics/GraphicsContext3D.cpp 2016-11-19 01:00:16 UTC (rev 208910)
@@ -149,7 +149,7 @@
std::unique_ptr<unsigned char[]> zero;
if (width > 0 && height > 0) {
unsigned int size;
- GC3Denum error = computeImageSizeInBytes(format, type, width, height, unpackAlignment, &size, 0);
+ GC3Denum error = computeImageSizeInBytes(format, type, width, height, unpackAlignment, &size, nullptr);
if (error != GraphicsContext3D::NO_ERROR) {
synthesizeGLError(error);
return false;
@@ -373,7 +373,7 @@
unsigned packedSize;
// Output data is tightly packed (alignment == 1).
- if (computeImageSizeInBytes(format, type, width, height, 1, &packedSize, 0) != GraphicsContext3D::NO_ERROR)
+ if (computeImageSizeInBytes(format, type, width, height, 1, &packedSize, nullptr) != GraphicsContext3D::NO_ERROR)
return false;
data.resize(packedSize);
@@ -393,7 +393,7 @@
unsigned int packedSize;
// Output data is tightly packed (alignment == 1).
- if (computeImageSizeInBytes(format, type, width, height, 1, &packedSize, 0) != GraphicsContext3D::NO_ERROR)
+ if (computeImageSizeInBytes(format, type, width, height, 1, &packedSize, nullptr) != GraphicsContext3D::NO_ERROR)
return false;
data.resize(packedSize);
Modified: trunk/Source/WebCore/platform/graphics/GraphicsContext3D.h (208909 => 208910)
--- trunk/Source/WebCore/platform/graphics/GraphicsContext3D.h 2016-11-19 00:58:54 UTC (rev 208909)
+++ trunk/Source/WebCore/platform/graphics/GraphicsContext3D.h 2016-11-19 01:00:16 UTC (rev 208910)
@@ -984,6 +984,9 @@
GC3Dboolean unmapBuffer(GC3Denum target);
void copyBufferSubData(GC3Denum readTarget, GC3Denum writeTarget, GC3Dintptr readOffset, GC3Dintptr writeOffset, GC3Dsizeiptr);
+ void texStorage2D(GC3Denum target, GC3Dsizei levels, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height);
+ void texStorage3D(GC3Denum target, GC3Dsizei levels, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dsizei depth);
+
GC3Denum checkFramebufferStatus(GC3Denum target);
void clear(GC3Dbitfield mask);
void clearColor(GC3Dclampf red, GC3Dclampf green, GC3Dclampf blue, GC3Dclampf alpha);
Modified: trunk/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGLCommon.cpp (208909 => 208910)
--- trunk/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGLCommon.cpp 2016-11-19 00:58:54 UTC (rev 208909)
+++ trunk/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGLCommon.cpp 2016-11-19 01:00:16 UTC (rev 208910)
@@ -215,6 +215,15 @@
::glGetIntegerv(GL_NUM_EXTENSIONS, &numExtensions);
for (GLint i = 0; i < numExtensions; ++i)
m_availableExtensions.add(glGetStringi(GL_EXTENSIONS, i));
+
+ if (!m_availableExtensions.contains(ASCIILiteral("GL_ARB_texture_storage"))) {
+ GLint majorVersion;
+ glGetIntegerv(GL_MAJOR_VERSION, &majorVersion);
+ GLint minorVersion;
+ glGetIntegerv(GL_MINOR_VERSION, &minorVersion);
+ if (majorVersion > 4 || (majorVersion == 4 && minorVersion >= 2))
+ m_availableExtensions.add(ASCIILiteral("GL_ARB_texture_storage"));
+ }
} else
#endif
{
Modified: trunk/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGLCommon.cpp (208909 => 208910)
--- trunk/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGLCommon.cpp 2016-11-19 00:58:54 UTC (rev 208909)
+++ trunk/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGLCommon.cpp 2016-11-19 01:00:16 UTC (rev 208910)
@@ -70,6 +70,7 @@
#define GL_DO_NOT_WARN_IF_MULTI_GL_VERSION_HEADERS_INCLUDED
#include <OpenGL/gl.h>
#include <OpenGL/gl3.h>
+#include <OpenGL/gl3ext.h>
#undef GL_DO_NOT_WARN_IF_MULTI_GL_VERSION_HEADERS_INCLUDED
#elif PLATFORM(GTK) || PLATFORM(EFL) || PLATFORM(WIN)
#include "OpenGLShims.h"
@@ -564,6 +565,18 @@
makeContextCurrent();
::glCopyBufferSubData(readTarget, writeTarget, readOffset, writeOffset, size);
}
+
+void GraphicsContext3D::texStorage2D(GC3Denum target, GC3Dsizei levels, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height)
+{
+ makeContextCurrent();
+ ::glTexStorage2D(target, levels, internalformat, width, height);
+}
+
+void GraphicsContext3D::texStorage3D(GC3Denum target, GC3Dsizei levels, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dsizei depth)
+{
+ makeContextCurrent();
+ ::glTexStorage3D(target, levels, internalformat, width, height, depth);
+}
#endif
GC3Denum GraphicsContext3D::checkFramebufferStatus(GC3Denum target)