WebGL 2 conformance: framebuffer-test
authorjustin_fan@apple.com <justin_fan@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 28 Aug 2018 00:37:49 +0000 (00:37 +0000)
committerjustin_fan@apple.com <justin_fan@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 28 Aug 2018 00:37:49 +0000 (00:37 +0000)
https://bugs.webkit.org/show_bug.cgi?id=188812

Reviewed by Jon Lee.

Source/WebCore:

Update WebGL 2 implementation to handle READ_FRAMEBUFFER and default framebuffer conformance. Also taking this
chance to fix memory leak in PlatformScreenMac/gpuIDForDisplayMask().

Covered by existing WebGL tests as well as newly-enabled webgl/2.0.0/conformance2/renderbuffers/framebuffer-test.html.

* html/canvas/WebGL2RenderingContext.cpp:
(WebCore::WebGL2RenderingContext::blitFramebuffer):
(WebCore::WebGL2RenderingContext::framebufferTextureLayer):
(WebCore::validateDefaultFramebufferAttachment):
(WebCore::WebGL2RenderingContext::getFramebufferAttachmentParameter):
(WebCore::WebGL2RenderingContext::validateFramebufferFuncParameters):
(WebCore::WebGL2RenderingContext::validateFramebufferTarget):
(WebCore::WebGL2RenderingContext::validateNonDefaultFramebufferAttachment):
(WebCore::WebGL2RenderingContext::getParameter):
* html/canvas/WebGL2RenderingContext.h:
* html/canvas/WebGLFramebuffer.cpp:
(WebCore::WebGLFramebuffer::isBound const):
* html/canvas/WebGLRenderingContextBase.cpp:
(WebCore::WebGLRenderingContextBase::initializeNewContext):
(WebCore::WebGLRenderingContextBase::~WebGLRenderingContextBase):
(WebCore::WebGLRenderingContextBase::bindFramebuffer):
(WebCore::WebGLRenderingContextBase::checkFramebufferStatus):
(WebCore::WebGLRenderingContextBase::deleteFramebuffer):
(WebCore::WebGLRenderingContextBase::framebufferRenderbuffer):
(WebCore::WebGLRenderingContextBase::framebufferTexture2D):
* html/canvas/WebGLRenderingContextBase.h:
* platform/graphics/GraphicsContext3D.h:
* platform/graphics/opengl/GraphicsContext3DOpenGLCommon.cpp:
(WebCore::GraphicsContext3D::blitFramebuffer):
* platform/mac/PlatformScreenMac.mm:
(WebCore::gpuIDForDisplayMask):

LayoutTests:

Update WebGL 2 implementation to handle READ_FRAMEBUFFER and default framebuffer conformance.

* TestExpectations: Unskipping webgl/2.0.0/conformance2/renderbuffers/framebuffer-test.html.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@235417 268f45cc-cd09-0410-ab3c-d52691b4dbfc

LayoutTests/ChangeLog
LayoutTests/TestExpectations
LayoutTests/webgl/2.0.0/conformance2/renderbuffers/framebuffer-test-expected.txt
Source/WebCore/ChangeLog
Source/WebCore/html/canvas/WebGL2RenderingContext.cpp
Source/WebCore/html/canvas/WebGL2RenderingContext.h
Source/WebCore/html/canvas/WebGLFramebuffer.cpp
Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp
Source/WebCore/html/canvas/WebGLRenderingContextBase.h

index 3ed81e5..1f72292 100644 (file)
@@ -1,3 +1,14 @@
+2018-08-27  Justin Fan  <justin_fan@apple.com>
+
+        WebGL 2 conformance: framebuffer-test
+        https://bugs.webkit.org/show_bug.cgi?id=188812
+
+        Reviewed by Jon Lee.
+
+        Update WebGL 2 implementation to handle READ_FRAMEBUFFER and default framebuffer conformance.
+
+        * TestExpectations: Unskipping webgl/2.0.0/conformance2/renderbuffers/framebuffer-test.html.
+
 2018-08-27  Myles C. Maxfield  <mmaxfield@apple.com>
 
         Null pointer deref in WidthIterator
index 48c4ab1..6c712b9 100644 (file)
@@ -2068,6 +2068,7 @@ webkit.org/b/186574 media/video-buffering-allowed.html [ Pass Failure ]
 webgl/2.0.0 [ Skip ]
 webgl/2.0.0/conformance2/glsl3 [ Pass ]
 webgl/2.0.0/conformance2/vertex_arrays [ Pass ]
+webgl/2.0.0/conformance2/renderbuffers/framebuffer-test.html [ Pass ]
 
 imported/w3c/web-platform-tests/css/css-display/run-in/run-in-contains-table-row-001.xht [ ImageOnlyFailure ]
 imported/w3c/web-platform-tests/css/css-text-decor/text-emphasis-style-008.html [ ImageOnlyFailure ]
index 7916e89..ea0042c 100644 (file)
@@ -1,5 +1,65 @@
 This test runs the WebGL Test listed below in an iframe and reports PASS or FAIL.
 
 Test: ../../resources/webgl_test_files/conformance2/renderbuffers/framebuffer-test.html
+gl = wtu.create3DContext(canvas, undefined, 2) is non-null.
+getError was expected value: INVALID_ENUM : getFramebufferAttachmentParameter(COLOR_ATTACHMENT0) on the default framebuffer.
+getError was expected value: NO_ERROR : getFramebufferAttachmentParameter(BACK) on the default framebuffer.
+getError was expected value: NO_ERROR : checkFramebufferStatus on the default framebuffer.
+getError was expected value: INVALID_OPERATION : attach a texture to default framebuffer.
+getError was expected value: INVALID_OPERATION : detach default renderbuffer from default framebuffer.
+getError was expected value: NO_ERROR : allocate renderbuffer storage of a newly created renderbuffer.
+getError was expected value: INVALID_OPERATION : attach a renderbuffer to the default framebuffer.
+getError was expected value: NO_ERROR : bind a newly created framebuffer.
+getError was expected value: NO_ERROR : getFramebufferAttachmentParameter(READ_FRAMEBUFFER).
+checkFramebufferStatus(READ_FRAMEBUFFER) should succeed.
+getError was expected value: NO_ERROR : checkFramebufferStatus(READ_FRAMEBUFFER).
+getError was expected value: NO_ERROR : bindFramebuffer(READ_FRAMEBUFFER).
+bindFramebuffer(READ_FRAMEBUFFER) should change READ_FRAMEBUFFER_BINDING.
+bindFramebuffer(READ_FRAMEBUFFER) should not change DRAW_FRAMEBUFFER_BINDING.
+getError was expected value: NO_ERROR : getFramebufferAttachmentParameter(FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE) with no attachment.
+getError was expected value: NO_ERROR : framebufferTexImage2D(READ_FRAMEBUFFER).
+getError was expected value: NO_ERROR : framebufferRenderbuffer(READ_FRAMEBUFFER).
+getError was expected value: NO_ERROR : framebufferTexImage2D(COLOR_ATTACHMENT1).
+getError was expected value: NO_ERROR : framebufferRenderbuffer(COLOR_ATTACHMENT1).
+getError was expected value: INVALID_OPERATION : getFramebufferAttachmentParameter(GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING) with no attachment.
+getError was expected value: NO_ERROR : attach a texture to a framebuffer.
+getError was expected value: NO_ERROR : detach a texture from a framebuffer.
+getError was expected value: NO_ERROR : framebufferTexture2D with an appropriate mipmap level.
+getError was expected value: INVALID_VALUE : framebufferTexture2D with a mipmap level out of range.
+getError was expected value: NO_ERROR : attach a renderbuffer to a framebuffer.
+getError was expected value: NO_ERROR : detach a renderbuffer from a framebuffer.
+getError was expected value: NO_ERROR : bind default (null) framebuffer.
+getError was expected value: NO_ERROR : attach a texture to read/draw framebuffer binding point.
+getError was expected value: NO_ERROR : getFramebufferAttachmentParameter(FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING) on read/draw framebuffer.
+getError was expected value: INVALID_OPERATION : getFramebufferAttachmentParameter(FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING) on read/draw framebuffer with no attachment.
+getError was expected value: NO_ERROR : detach a texture from read/draw framebuffer.
+getError was expected value: NO_ERROR : attach a texture to read/draw framebuffer binding point.
+getError was expected value: NO_ERROR : getFramebufferAttachmentParameter(FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING) on read/draw framebuffer.
+getError was expected value: INVALID_OPERATION : getFramebufferAttachmentParameter(FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING) on read/draw framebuffer with no attachment.
+getError was expected value: NO_ERROR : detach a texture from read/draw framebuffer.
+gl.getFramebufferAttachmentParameter(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_BLUE_SIZE) is non-zero.
+gl.getFramebufferAttachmentParameter(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_BLUE_SIZE) is 0
+getError was expected value: INVALID_OPERATION : getFramebufferAttachmentParameter(FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING) on read framebuffer with no attachment.
+getError was expected value: NO_ERROR : getFramebufferAttachmentParameter(FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING) on draw framebuffer.
+getError was expected value: INVALID_OPERATION : getFramebufferAttachmentParameter(FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING) on draw framebuffer with no attachment.
+getError was expected value: NO_ERROR : attaching a renderbuffer to a read/draw framebuffer.
+getError was expected value: NO_ERROR : getFramebufferAttachmentParameter(FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING) on read/draw framebuffer.
+getError was expected value: INVALID_OPERATION : getFramebufferAttachmentParameter(FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING) on read/draw framebuffer with no attachment.
+getError was expected value: NO_ERROR : detach a renderbuffer from a read/draw framebuffer.
+getError was expected value: NO_ERROR : attaching a renderbuffer to a read/draw framebuffer.
+getError was expected value: NO_ERROR : getFramebufferAttachmentParameter(FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING) on read/draw framebuffer.
+getError was expected value: INVALID_OPERATION : getFramebufferAttachmentParameter(FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING) on read/draw framebuffer with no attachment.
+getError was expected value: NO_ERROR : detach a renderbuffer from a read/draw framebuffer.
+getError was expected value: NO_ERROR : allocating renderbuffer storage of a newly created renderbuffer.
+gl.getFramebufferAttachmentParameter(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_RED_SIZE) is non-zero.
+getError was expected value: INVALID_OPERATION : getFramebufferAttachmentParameter(FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE) on read framebuffer without depth attachment.
+gl.getFramebufferAttachmentParameter(gl.DRAW_FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE) is non-zero.
+getError was expected value: INVALID_OPERATION : getFramebufferAttachmentParameter(FRAMEBUFFER_ATTACHMENT_RED_SIZE) on draw framebuffer without color attachment.
+getError was expected value: INVALID_OPERATION : getFramebufferAttachmentParameter(FRAMEBUFFER_ATTACHMENT_RED_SIZE) on read framebuffer with no attachment.
+gl.getFramebufferAttachmentParameter(gl.DRAW_FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE) is non-zero.
+getError was expected value: INVALID_OPERATION : getFramebufferAttachmentParameter(FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE) on draw framebuffer with no attachment.
+getError was expected value: NO_ERROR : bind read framebuffer to default (null) framebuffer.
+getError was expected value: NO_ERROR : bind draw framebuffer to default (null) framebuffer.
+successfullyParsed is true
 PASS
 
index 063c481..0de7967 100644 (file)
@@ -1,3 +1,42 @@
+2018-08-27  Justin Fan  <justin_fan@apple.com>
+
+        WebGL 2 conformance: framebuffer-test
+        https://bugs.webkit.org/show_bug.cgi?id=188812
+
+        Reviewed by Jon Lee.
+
+        Update WebGL 2 implementation to handle READ_FRAMEBUFFER and default framebuffer conformance. Also taking this
+        chance to fix memory leak in PlatformScreenMac/gpuIDForDisplayMask().
+
+        Covered by existing WebGL tests as well as newly-enabled webgl/2.0.0/conformance2/renderbuffers/framebuffer-test.html.
+
+        * html/canvas/WebGL2RenderingContext.cpp:
+        (WebCore::WebGL2RenderingContext::blitFramebuffer):
+        (WebCore::WebGL2RenderingContext::framebufferTextureLayer):
+        (WebCore::validateDefaultFramebufferAttachment):
+        (WebCore::WebGL2RenderingContext::getFramebufferAttachmentParameter):
+        (WebCore::WebGL2RenderingContext::validateFramebufferFuncParameters):
+        (WebCore::WebGL2RenderingContext::validateFramebufferTarget):
+        (WebCore::WebGL2RenderingContext::validateNonDefaultFramebufferAttachment):
+        (WebCore::WebGL2RenderingContext::getParameter):
+        * html/canvas/WebGL2RenderingContext.h:
+        * html/canvas/WebGLFramebuffer.cpp:
+        (WebCore::WebGLFramebuffer::isBound const):
+        * html/canvas/WebGLRenderingContextBase.cpp:
+        (WebCore::WebGLRenderingContextBase::initializeNewContext):
+        (WebCore::WebGLRenderingContextBase::~WebGLRenderingContextBase):
+        (WebCore::WebGLRenderingContextBase::bindFramebuffer):
+        (WebCore::WebGLRenderingContextBase::checkFramebufferStatus):
+        (WebCore::WebGLRenderingContextBase::deleteFramebuffer):
+        (WebCore::WebGLRenderingContextBase::framebufferRenderbuffer):
+        (WebCore::WebGLRenderingContextBase::framebufferTexture2D):
+        * html/canvas/WebGLRenderingContextBase.h:
+        * platform/graphics/GraphicsContext3D.h:
+        * platform/graphics/opengl/GraphicsContext3DOpenGLCommon.cpp:
+        (WebCore::GraphicsContext3D::blitFramebuffer):
+        * platform/mac/PlatformScreenMac.mm:
+        (WebCore::gpuIDForDisplayMask):
+
 2018-08-27  Myles C. Maxfield  <mmaxfield@apple.com>
 
         Null pointer deref in WidthIterator
index b87f9fd..12fcfda 100644 (file)
@@ -1178,24 +1178,63 @@ std::optional<Vector<String>> WebGL2RenderingContext::getSupportedExtensions()
     return result;
 }
 
+static bool validateDefaultFramebufferAttachment(GC3Denum& attachment)
+{
+    switch (attachment) {
+    case GraphicsContext3D::BACK:
+        // Because the backbuffer is simulated on all current WebKit ports, we need to change BACK to COLOR_ATTACHMENT0.
+        attachment = GraphicsContext3D::COLOR_ATTACHMENT0;
+        return true;
+    case GraphicsContext3D::DEPTH:
+    case GraphicsContext3D::STENCIL:
+        return true;
+    }
+
+    return false;
+}
+
 WebGLAny WebGL2RenderingContext::getFramebufferAttachmentParameter(GC3Denum target, GC3Denum attachment, GC3Denum pname)
 {
-    if (isContextLostOrPending() || !validateFramebufferFuncParameters("getFramebufferAttachmentParameter", target, attachment))
-        return nullptr;
-    
-    if (!m_framebufferBinding || !m_framebufferBinding->object()) {
-        synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "getFramebufferAttachmentParameter", "no framebuffer bound");
+    const char* functionName = "getFramebufferAttachmentParameter";
+    if (isContextLostOrPending() || !validateFramebufferTarget(functionName, target))
         return nullptr;
+
+    auto targetFramebuffer = (target == GraphicsContext3D::READ_FRAMEBUFFER) ? m_readFramebufferBinding : m_framebufferBinding;
+
+    if (!targetFramebuffer) {
+        // OpenGL ES 3: Default framebuffer is bound.
+        if (!validateDefaultFramebufferAttachment(attachment)) {
+            synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid attachment");
+            return nullptr;
+        }
+        GC3Dint value = 0;
+        m_context->getFramebufferAttachmentParameteriv(target, attachment, pname, &value);
+        return value;
     }
-    
-    auto object = makeRefPtr(m_framebufferBinding->getAttachmentObject(attachment));
+    if (!validateNonDefaultFramebufferAttachment(functionName, attachment))
+        return nullptr;
+
+    auto object = makeRefPtr(targetFramebuffer->getAttachmentObject(attachment));
     if (!object) {
         if (pname == GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE)
             return static_cast<unsigned>(GraphicsContext3D::NONE);
-        // OpenGL ES 2.0 specifies INVALID_ENUM in this case, while desktop GL specifies INVALID_OPERATION.
-        synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getFramebufferAttachmentParameter", "invalid parameter name");
+        synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid parameter name");
         return nullptr;
     }
+
+    switch (pname) {
+    case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_RED_SIZE:
+    case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
+    case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
+    case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
+    case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
+    case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
+    case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE: {
+        GC3Dint value = 0;
+        m_context->getFramebufferAttachmentParameteriv(target, attachment, pname, &value);
+        return value;
+    }
+    }
     
     if (object->isTexture()) {
         switch (pname) {
@@ -1211,7 +1250,7 @@ WebGLAny WebGL2RenderingContext::getFramebufferAttachmentParameter(GC3Denum targ
             return value;
         }
         default:
-            synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getFramebufferAttachmentParameter", "invalid parameter name for texture attachment");
+            synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid parameter name for texture attachment");
             return nullptr;
         }
     } else {
@@ -1233,7 +1272,7 @@ WebGLAny WebGL2RenderingContext::getFramebufferAttachmentParameter(GC3Denum targ
             return static_cast<unsigned>(GraphicsContext3D::LINEAR);
         }
         default:
-            synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getFramebufferAttachmentParameter", "invalid parameter name for renderbuffer attachment");
+            synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid parameter name for renderbuffer attachment");
             return nullptr;
         }
     }
@@ -1241,10 +1280,24 @@ WebGLAny WebGL2RenderingContext::getFramebufferAttachmentParameter(GC3Denum targ
 
 bool WebGL2RenderingContext::validateFramebufferFuncParameters(const char* functionName, GC3Denum target, GC3Denum attachment)
 {
-    if (target != GraphicsContext3D::FRAMEBUFFER) {
-        synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid target");
-        return false;
+    return validateFramebufferTarget(functionName, target) && validateNonDefaultFramebufferAttachment(functionName, attachment);
+}
+
+bool WebGL2RenderingContext::validateFramebufferTarget(const char* functionName, GC3Denum target)
+{
+    switch (target) {
+    case GraphicsContext3D::FRAMEBUFFER:
+    case GraphicsContext3D::DRAW_FRAMEBUFFER:
+    case GraphicsContext3D::READ_FRAMEBUFFER:
+        return true;
     }
+
+    synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid target");
+    return false;
+}
+
+bool WebGL2RenderingContext::validateNonDefaultFramebufferAttachment(const char* functionName, GC3Denum attachment)
+{
     switch (attachment) {
     case GraphicsContext3D::DEPTH_ATTACHMENT:
     case GraphicsContext3D::STENCIL_ATTACHMENT:
@@ -1253,9 +1306,10 @@ bool WebGL2RenderingContext::validateFramebufferFuncParameters(const char* funct
     default:
         if (attachment >= GraphicsContext3D::COLOR_ATTACHMENT0 && attachment < static_cast<GC3Denum>(GraphicsContext3D::COLOR_ATTACHMENT0 + getMaxColorAttachments()))
             return true;
-        synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid attachment");
-        return false;
     }
+
+    synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid attachment");
+    return false;
 }
 
 GC3Dint WebGL2RenderingContext::getMaxDrawBuffers()
@@ -1763,6 +1817,8 @@ WebGLAny WebGL2RenderingContext::getParameter(GC3Denum pname)
         if (m_framebufferBinding)
             return m_framebufferBinding->getDrawBuffer(pname);
         return m_backDrawBuffer; // emulated backbuffer
+    case GraphicsContext3D::READ_FRAMEBUFFER_BINDING:
+        return m_readFramebufferBinding;
     case GraphicsContext3D::COPY_READ_BUFFER:
     case GraphicsContext3D::COPY_WRITE_BUFFER:
     case GraphicsContext3D::PIXEL_PACK_BUFFER_BINDING:   
@@ -1771,7 +1827,6 @@ WebGLAny WebGL2RenderingContext::getParameter(GC3Denum pname)
     case GraphicsContext3D::SAMPLER_BINDING:
     case GraphicsContext3D::TEXTURE_BINDING_2D_ARRAY:
     case GraphicsContext3D::TEXTURE_BINDING_3D:
-    case GraphicsContext3D::READ_FRAMEBUFFER_BINDING:
     case GraphicsContext3D::TRANSFORM_FEEDBACK_BUFFER_BINDING:
     case GraphicsContext3D::UNIFORM_BUFFER_BINDING:
         synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "parameter name not yet supported");
index 655285d..2f85d1a 100644 (file)
@@ -217,6 +217,8 @@ private:
     bool validateBlendEquation(const char* functionName, GC3Denum mode) final;
     bool validateCapability(const char* functionName, GC3Denum cap) final;
     bool validateFramebufferFuncParameters(const char* functionName, GC3Denum target, GC3Denum attachment) final;
+    bool validateFramebufferTarget(const char* functionName, GC3Denum target);
+    bool validateNonDefaultFramebufferAttachment(const char* functionName, GC3Denum attachment);
     
     GC3Denum baseInternalFormatFromInternalFormat(GC3Denum internalformat);
     bool isIntegerFormat(GC3Denum internalformat);
index 6ada33c..02749ef 100644 (file)
@@ -586,7 +586,7 @@ bool WebGLFramebuffer::initializeAttachments(GraphicsContext3D* g3d, const char*
 
 bool WebGLFramebuffer::isBound() const
 {
-    return (context()->m_framebufferBinding.get() == this);
+    return (context()->m_framebufferBinding.get() == this) || (context()->m_readFramebufferBinding.get() == this);
 }
 
 void WebGLFramebuffer::drawBuffers(const Vector<GC3Denum>& bufs)
index cdef7cc..3b8038b 100644 (file)
@@ -744,6 +744,7 @@ void WebGLRenderingContextBase::initializeNewContext()
     m_boundArrayBuffer = nullptr;
     m_currentProgram = nullptr;
     m_framebufferBinding = nullptr;
+    m_readFramebufferBinding = nullptr;
     m_renderbufferBinding = nullptr;
     m_depthMask = true;
     m_stencilEnabled = false;
@@ -873,6 +874,7 @@ WebGLRenderingContextBase::~WebGLRenderingContextBase()
     m_vertexAttrib0Buffer = nullptr;
     m_currentProgram = nullptr;
     m_framebufferBinding = nullptr;
+    m_readFramebufferBinding = nullptr;
     m_renderbufferBinding = nullptr;
 
     for (auto& textureUnit : m_textureUnits) {
@@ -1264,11 +1266,29 @@ void WebGLRenderingContextBase::bindFramebuffer(GC3Denum target, WebGLFramebuffe
         return;
     if (deleted)
         buffer = 0;
-    if (target != GraphicsContext3D::FRAMEBUFFER) {
+
+    bool isWebGL2DrawFramebufferTarget = false;
+#if ENABLE(WEBGL2)
+    isWebGL2DrawFramebufferTarget = isWebGL2() && target == GraphicsContext3D::DRAW_FRAMEBUFFER;
+#endif
+    bool success = false;
+
+    if (target == GraphicsContext3D::FRAMEBUFFER || isWebGL2DrawFramebufferTarget) {
+        m_framebufferBinding = buffer;
+        success = true;
+    }
+#if ENABLE(WEBGL2)
+    if (isWebGL2() && (target == GraphicsContext3D::FRAMEBUFFER || target == GraphicsContext3D::READ_FRAMEBUFFER)) {
+        m_readFramebufferBinding = buffer;
+        success = true;
+    }
+#endif
+
+    if (!success) {
         synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "bindFramebuffer", "invalid target");
         return;
     }
-    m_framebufferBinding = buffer;
+
     m_context->bindFramebuffer(target, objectOrZero(buffer));
     if (buffer)
         buffer->setHasEverBeenBound();
@@ -1463,13 +1483,22 @@ GC3Denum WebGLRenderingContextBase::checkFramebufferStatus(GC3Denum target)
     if (isContextLostOrPending())
         return GraphicsContext3D::FRAMEBUFFER_UNSUPPORTED;
     if (target != GraphicsContext3D::FRAMEBUFFER) {
-        synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "checkFramebufferStatus", "invalid target");
-        return 0;
+#if ENABLE(WEBGL2)
+        if (isWebGL1() || (target != GraphicsContext3D::DRAW_FRAMEBUFFER && target != GraphicsContext3D::READ_FRAMEBUFFER)) {
+#endif
+            synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "checkFramebufferStatus", "invalid target");
+            return 0;
+#if ENABLE(WEBGL2)
+        }
+#endif
     }
-    if (!m_framebufferBinding || !m_framebufferBinding->object())
+
+    auto targetFramebuffer = (target == GraphicsContext3D::READ_FRAMEBUFFER) ? m_readFramebufferBinding : m_framebufferBinding;
+
+    if (!targetFramebuffer || !targetFramebuffer->object())
         return GraphicsContext3D::FRAMEBUFFER_COMPLETE;
     const char* reason = "framebuffer incomplete";
-    GC3Denum result = m_framebufferBinding->checkStatus(&reason);
+    GC3Denum result = targetFramebuffer->checkStatus(&reason);
     if (result != GraphicsContext3D::FRAMEBUFFER_COMPLETE) {
         String str = "WebGL: checkFramebufferStatus:" + String(reason);
         printToConsole(MessageLevel::Warning, str);
@@ -1794,9 +1823,20 @@ void WebGLRenderingContextBase::deleteFramebuffer(WebGLFramebuffer* framebuffer)
 {
     if (!deleteObject(framebuffer))
         return;
+#if ENABLE(WEBGL2)
+    if (isWebGL2() && framebuffer == m_readFramebufferBinding) {
+        m_readFramebufferBinding = nullptr;
+        m_context->bindFramebuffer(GraphicsContext3D::READ_FRAMEBUFFER, 0);
+    }
+#endif
     if (framebuffer == m_framebufferBinding) {
         m_framebufferBinding = nullptr;
-        m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, 0);
+#if ENABLE(WEBGL2)
+        if (isWebGL2())
+            m_context->bindFramebuffer(GraphicsContext3D::DRAW_FRAMEBUFFER, 0);
+        else
+#endif
+            m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, 0);
     }
 }
 
@@ -2361,10 +2401,13 @@ void WebGLRenderingContextBase::framebufferRenderbuffer(GC3Denum target, GC3Denu
         synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "framebufferRenderbuffer", "no buffer or buffer not from this context");
         return;
     }
+
+    auto targetFramebuffer = (target == GraphicsContext3D::READ_FRAMEBUFFER) ? m_readFramebufferBinding : m_framebufferBinding;
+
     // Don't allow the default framebuffer to be mutated; all current
     // implementations use an FBO internally in place of the default
     // FBO.
-    if (!m_framebufferBinding || !m_framebufferBinding->object()) {
+    if (!targetFramebuffer || !targetFramebuffer->object()) {
         synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "framebufferRenderbuffer", "no framebuffer bound");
         return;
     }
@@ -2377,7 +2420,7 @@ void WebGLRenderingContextBase::framebufferRenderbuffer(GC3Denum target, GC3Denu
     default:
         m_context->framebufferRenderbuffer(target, attachment, renderbuffertarget, bufferObject);
     }
-    m_framebufferBinding->setAttachmentForBoundFramebuffer(attachment, buffer);
+    targetFramebuffer->setAttachmentForBoundFramebuffer(attachment, buffer);
     applyStencilTest();
 }
 
@@ -2385,7 +2428,7 @@ void WebGLRenderingContextBase::framebufferTexture2D(GC3Denum target, GC3Denum a
 {
     if (isContextLostOrPending() || !validateFramebufferFuncParameters("framebufferTexture2D", target, attachment))
         return;
-    if (level) {
+    if (level && isWebGL1()) {
         synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "framebufferTexture2D", "level not 0");
         return;
     }
@@ -2393,10 +2436,13 @@ void WebGLRenderingContextBase::framebufferTexture2D(GC3Denum target, GC3Denum a
         synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "framebufferTexture2D", "no texture or texture not from this context");
         return;
     }
+
+    auto targetFramebuffer = (target == GraphicsContext3D::READ_FRAMEBUFFER) ? m_readFramebufferBinding : m_framebufferBinding;
+
     // Don't allow the default framebuffer to be mutated; all current
     // implementations use an FBO internally in place of the default
     // FBO.
-    if (!m_framebufferBinding || !m_framebufferBinding->object()) {
+    if (!targetFramebuffer || !targetFramebuffer->object()) {
         synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "framebufferTexture2D", "no framebuffer bound");
         return;
     }
@@ -2415,7 +2461,7 @@ void WebGLRenderingContextBase::framebufferTexture2D(GC3Denum target, GC3Denum a
     default:
         m_context->framebufferTexture2D(target, attachment, textarget, textureObject, level);
     }
-    m_framebufferBinding->setAttachmentForBoundFramebuffer(attachment, textarget, texture, level);
+    targetFramebuffer->setAttachmentForBoundFramebuffer(attachment, textarget, texture, level);
     applyStencilTest();
 }
 
index cc3abc1..bade614 100644 (file)
@@ -497,6 +497,7 @@ protected:
 
     RefPtr<WebGLProgram> m_currentProgram;
     RefPtr<WebGLFramebuffer> m_framebufferBinding;
+    RefPtr<WebGLFramebuffer> m_readFramebufferBinding;
     RefPtr<WebGLRenderbuffer> m_renderbufferBinding;
     struct TextureUnitState {
         RefPtr<WebGLTexture> texture2DBinding;