Title: [262366] trunk
Revision
262366
Author
d...@apple.com
Date
2020-05-31 16:20:51 -0700 (Sun, 31 May 2020)

Log Message

AutoTrader crashed while browsing search results
https://bugs.webkit.org/show_bug.cgi?id=212461
rdar://60733185

Reviewed by Sam Weinig.

Source/WebCore:

On iOS, when using WebKit1 (UIWebView), CoreAnimation would
call WebGLLayer's display method from a thread that is not
the Web Thread. That method was performing some GL work using
ANGLE, causing a crash.

Since all the WebGLLayer's display method really needs to do
is swap buffers for compositing, the fix is to separate all
the GL operations into a method that can be called after
painting but before compositing. This should also have the added
benefit that by the time CoreAnimation comes to call display
on all the dirty layers, we will have already executed our
expensive GPU work. The total amount of work done on the GPU
is the same, but hopefully it is now all done in WebKit's
paint cycle, rather than when the Window Server is trying
to get CA to composite things.

Covered by a new API test: WebGLPrepareDisplayOnWebThread

* html/HTMLCanvasElement.h:
* html/HTMLCanvasElement.cpp:
(WebCore::HTMLCanvasElement::HTMLCanvasElement):
(WebCore::HTMLCanvasElement::~HTMLCanvasElement):
(WebCore::HTMLCanvasElement::didMoveToNewDocument):
(WebCore::HTMLCanvasElement::removedFromAncestor):
    Add or remove the document as a CanvasObserver.
(WebCore::HTMLCanvasElement::needsPreparationForDisplay):
    Signals whether this element is the type that needs preparation.
(WebCore::HTMLCanvasElement::prepareForDisplay):
    Tell the WebGLRenderingContext it must prepare.

* html/canvas/WebGLRenderingContextBase.h:
* html/canvas/WebGLRenderingContextBase.cpp:
(WebCore::WebGLRenderingContextBase::prepareForDisplay):
    The WebGLRenderingContext must forward the call
    to prepare down to the GraphicsContextGLOpenGL.

* platform/graphics/opengl/GraphicsContextGLOpenGL.h:
* platform/graphics/opengl/GraphicsContextGLOpenGL.cpp:
* platform/graphics/cocoa/GraphicsContextGLOpenGLCocoa.mm:
(WebCore::GraphicsContextGLOpenGL::prepareForDisplay):
    And the GraphicsContextGLOpenGL forwards the call
    into the WebGLLayer.

* platform/graphics/cocoa/WebGLLayer.h:
* platform/graphics/cocoa/WebGLLayer.mm:
(-[WebGLLayer prepareForDisplay]):
(-[WebGLLayer display]):
    Split the parts of the `display` method that deal
    with flushing the GL commands, preparing the framebuffer texture,
    and swapping the IOSurfaces into a new `prepareForDisplay`. This
    method is invoked at the end of the rendering/layout tasks, leaving
    the `display` method to only tell CoreAnimation about a new buffer
    to composite.

* dom/Document.cpp:
* dom/Document.h:
(WebCore::Document::prepareCanvasesForDisplayIfNeeded):
(WebCore::Document::canvasChanged):
(WebCore::Document::canvasDestroyed):
    Keep a set of HTMLCanvasElements that need to
    be prepared so we can tell them when they need to prepare.
    Do this by becoming a CanvasObserver, thus getting
    notified when a canvas has done something that
    would cause painting.

* page/Page.cpp:
(WebCore::Page::doAfterUpdateRendering):
    Add a new task that asks the Document to notify
    all relevant canvas objects that they should prepare
    for display.

Tools:

* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/WebKitLegacy/ios/WebGLPrepareDisplayOnWebThread.mm: Added.
(-[WebGLPrepareDisplayOnWebThreadDelegate webViewDidFinishLoad:]):
(-[WebGLPrepareDisplayOnWebThreadDelegate webView:shouldStartLoadWithRequest:navigationType:]):
(TestWebKitAPI::TEST):
* TestWebKitAPI/Tests/WebKitLegacy/ios/webgl.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (262365 => 262366)


--- trunk/Source/WebCore/ChangeLog	2020-05-31 19:52:53 UTC (rev 262365)
+++ trunk/Source/WebCore/ChangeLog	2020-05-31 23:20:51 UTC (rev 262366)
@@ -1,3 +1,82 @@
+2020-05-31  Dean Jackson  <d...@apple.com>
+
+        AutoTrader crashed while browsing search results
+        https://bugs.webkit.org/show_bug.cgi?id=212461
+        rdar://60733185
+
+        Reviewed by Sam Weinig.
+
+        On iOS, when using WebKit1 (UIWebView), CoreAnimation would
+        call WebGLLayer's display method from a thread that is not
+        the Web Thread. That method was performing some GL work using
+        ANGLE, causing a crash.
+
+        Since all the WebGLLayer's display method really needs to do
+        is swap buffers for compositing, the fix is to separate all
+        the GL operations into a method that can be called after
+        painting but before compositing. This should also have the added
+        benefit that by the time CoreAnimation comes to call display
+        on all the dirty layers, we will have already executed our
+        expensive GPU work. The total amount of work done on the GPU
+        is the same, but hopefully it is now all done in WebKit's
+        paint cycle, rather than when the Window Server is trying
+        to get CA to composite things.
+
+        Covered by a new API test: WebGLPrepareDisplayOnWebThread
+
+        * html/HTMLCanvasElement.h:
+        * html/HTMLCanvasElement.cpp:
+        (WebCore::HTMLCanvasElement::HTMLCanvasElement):
+        (WebCore::HTMLCanvasElement::~HTMLCanvasElement):
+        (WebCore::HTMLCanvasElement::didMoveToNewDocument):
+        (WebCore::HTMLCanvasElement::removedFromAncestor):
+            Add or remove the document as a CanvasObserver.
+        (WebCore::HTMLCanvasElement::needsPreparationForDisplay):
+            Signals whether this element is the type that needs preparation.
+        (WebCore::HTMLCanvasElement::prepareForDisplay):
+            Tell the WebGLRenderingContext it must prepare.
+
+        * html/canvas/WebGLRenderingContextBase.h:
+        * html/canvas/WebGLRenderingContextBase.cpp:
+        (WebCore::WebGLRenderingContextBase::prepareForDisplay):
+            The WebGLRenderingContext must forward the call
+            to prepare down to the GraphicsContextGLOpenGL.
+
+        * platform/graphics/opengl/GraphicsContextGLOpenGL.h:
+        * platform/graphics/opengl/GraphicsContextGLOpenGL.cpp:
+        * platform/graphics/cocoa/GraphicsContextGLOpenGLCocoa.mm:
+        (WebCore::GraphicsContextGLOpenGL::prepareForDisplay):
+            And the GraphicsContextGLOpenGL forwards the call
+            into the WebGLLayer.
+
+        * platform/graphics/cocoa/WebGLLayer.h:
+        * platform/graphics/cocoa/WebGLLayer.mm:
+        (-[WebGLLayer prepareForDisplay]):
+        (-[WebGLLayer display]):
+            Split the parts of the `display` method that deal
+            with flushing the GL commands, preparing the framebuffer texture,
+            and swapping the IOSurfaces into a new `prepareForDisplay`. This
+            method is invoked at the end of the rendering/layout tasks, leaving
+            the `display` method to only tell CoreAnimation about a new buffer
+            to composite.
+
+        * dom/Document.cpp:
+        * dom/Document.h:
+        (WebCore::Document::prepareCanvasesForDisplayIfNeeded):
+        (WebCore::Document::canvasChanged):
+        (WebCore::Document::canvasDestroyed):
+            Keep a set of HTMLCanvasElements that need to
+            be prepared so we can tell them when they need to prepare.
+            Do this by becoming a CanvasObserver, thus getting
+            notified when a canvas has done something that
+            would cause painting.
+
+        * page/Page.cpp:
+        (WebCore::Page::doAfterUpdateRendering):
+            Add a new task that asks the Document to notify
+            all relevant canvas objects that they should prepare
+            for display.
+
 2020-05-31  Jer Noble  <jer.no...@apple.com>
 
         [Cocoa] EME should return more helpful error code during key exchange

Modified: trunk/Source/WebCore/dom/Document.cpp (262365 => 262366)


--- trunk/Source/WebCore/dom/Document.cpp	2020-05-31 19:52:53 UTC (rev 262365)
+++ trunk/Source/WebCore/dom/Document.cpp	2020-05-31 23:20:51 UTC (rev 262366)
@@ -8582,6 +8582,34 @@
     return *m_lazyLoadImageObserver;
 }
 
+void Document::prepareCanvasesForDisplayIfNeeded()
+{
+    // Some canvas contexts need to do work when rendering has finished but
+    // before their content is composited.
+    for (auto* canvas : m_canvasesNeedingDisplayPreparation) {
+        auto refCountedCanvas = makeRefPtr(canvas);
+        refCountedCanvas->prepareForDisplay();
+    }
+    m_canvasesNeedingDisplayPreparation.clear();
+}
+
+void Document::canvasChanged(CanvasBase& canvasBase, const FloatRect&)
+{
+    if (is<HTMLCanvasElement>(canvasBase)) {
+        auto* canvas = downcast<HTMLCanvasElement>(&canvasBase);
+        if (canvas->needsPreparationForDisplay())
+            m_canvasesNeedingDisplayPreparation.add(canvas);
+    }
+}
+
+void Document::canvasDestroyed(CanvasBase& canvasBase)
+{
+    if (is<HTMLCanvasElement>(canvasBase)) {
+        auto* canvas = downcast<HTMLCanvasElement>(&canvasBase);
+        m_canvasesNeedingDisplayPreparation.remove(canvas);
+    }
+}
+
 } // namespace WebCore
 
 #undef RELEASE_LOG_IF_ALLOWED

Modified: trunk/Source/WebCore/dom/Document.h (262365 => 262366)


--- trunk/Source/WebCore/dom/Document.h	2020-05-31 19:52:53 UTC (rev 262365)
+++ trunk/Source/WebCore/dom/Document.h	2020-05-31 23:20:51 UTC (rev 262366)
@@ -28,6 +28,7 @@
 #pragma once
 
 #include "CSSRegisteredCustomProperty.h"
+#include "CanvasBase.h"
 #include "Color.h"
 #include "ContainerNode.h"
 #include "DisabledAdaptations.h"
@@ -357,7 +358,8 @@
     , public FontSelectorClient
     , public FrameDestructionObserver
     , public Supplementable<Document>
-    , public Logger::Observer {
+    , public Logger::Observer
+    , public CanvasObserver {
     WTF_MAKE_ISO_ALLOCATED(Document);
 public:
     static Ref<Document> create(const URL&);
@@ -1593,6 +1595,11 @@
     FrameSelection& selection() { return m_selection; }
     const FrameSelection& selection() const { return m_selection; }
 
+    void prepareCanvasesForDisplayIfNeeded();
+    void canvasChanged(CanvasBase&, const FloatRect&) final;
+    void canvasResized(CanvasBase&) final { };
+    void canvasDestroyed(CanvasBase&) final;
+
 protected:
     enum ConstructionFlags { Synthesized = 1, NonRenderedPlaceholder = 1 << 1 };
     Document(Frame*, const URL&, unsigned = DefaultDocumentClass, unsigned constructionFlags = 0);
@@ -1811,6 +1818,11 @@
     std::unique_ptr<SVGDocumentExtensions> m_svgExtensions;
     HashSet<SVGUseElement*> m_svgUseElements;
 
+    // Collection of canvas objects that need to do work after they've
+    // rendered but before compositing, for the next frame. The set is
+    // cleared after they've been called.
+    HashSet<HTMLCanvasElement*> m_canvasesNeedingDisplayPreparation;
+
 #if ENABLE(DARK_MODE_CSS)
     OptionSet<ColorScheme> m_colorScheme;
     bool m_allowsColorSchemeTransformations { true };

Modified: trunk/Source/WebCore/html/HTMLCanvasElement.cpp (262365 => 262366)


--- trunk/Source/WebCore/html/HTMLCanvasElement.cpp	2020-05-31 19:52:53 UTC (rev 262365)
+++ trunk/Source/WebCore/html/HTMLCanvasElement.cpp	2020-05-31 23:20:51 UTC (rev 262366)
@@ -124,6 +124,7 @@
     , ActiveDOMObject(document)
 {
     ASSERT(hasTagName(canvasTag));
+    addObserver(document);
 }
 
 Ref<HTMLCanvasElement> HTMLCanvasElement::create(Document& document)
@@ -145,6 +146,7 @@
     // FIXME: This has to be called here because CSSCanvasValue::CanvasObserverProxy::canvasDestroyed()
     // downcasts the CanvasBase object to HTMLCanvasElement. That invokes virtual methods, which should be
     // avoided in destructors, but works as long as it's done before HTMLCanvasElement destructs completely.
+    // This will also cause the document to remove itself as an observer.
     notifyObserversCanvasDestroyed();
 
     m_context = nullptr; // Ensure this goes away before the ImageBuffer.
@@ -997,4 +999,33 @@
 #endif
 }
 
+void HTMLCanvasElement::didMoveToNewDocument(Document& oldDocument, Document& newDocument)
+{
+    removeObserver(oldDocument);
+    addObserver(newDocument);
+
+    HTMLElement::didMoveToNewDocument(oldDocument, newDocument);
 }
+
+void HTMLCanvasElement::removedFromAncestor(RemovalType removalType, ContainerNode& oldParentOfRemovedTree)
+{
+    if (removalType.disconnectedFromDocument)
+        removeObserver(oldParentOfRemovedTree.document());
+
+    HTMLElement::removedFromAncestor(removalType, oldParentOfRemovedTree);
+}
+
+bool HTMLCanvasElement::needsPreparationForDisplay()
+{
+    return is<WebGLRenderingContextBase>(m_context.get());
+}
+
+void HTMLCanvasElement::prepareForDisplay()
+{
+    ASSERT(needsPreparationForDisplay());
+
+    if (is<WebGLRenderingContextBase>(m_context.get()))
+        downcast<WebGLRenderingContextBase>(m_context.get())->prepareForDisplay();
+}
+
+}

Modified: trunk/Source/WebCore/html/HTMLCanvasElement.h (262365 => 262366)


--- trunk/Source/WebCore/html/HTMLCanvasElement.h	2020-05-31 19:52:53 UTC (rev 262365)
+++ trunk/Source/WebCore/html/HTMLCanvasElement.h	2020-05-31 23:20:51 UTC (rev 262366)
@@ -129,6 +129,9 @@
 
     WEBCORE_EXPORT static void setMaxPixelMemoryForTesting(size_t);
 
+    bool needsPreparationForDisplay();
+    void prepareForDisplay();
+
 private:
     HTMLCanvasElement(const QualifiedName&, Document&);
 
@@ -165,6 +168,9 @@
 
     ScriptExecutionContext* canvasBaseScriptExecutionContext() const final { return HTMLElement::scriptExecutionContext(); }
 
+    void didMoveToNewDocument(Document& oldDocument, Document& newDocument) final;
+    void removedFromAncestor(RemovalType, ContainerNode& oldParentOfRemovedTree) final;
+
     FloatRect m_dirtyRect;
 
     bool m_ignoreReset { false };

Modified: trunk/Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp (262365 => 262366)


--- trunk/Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp	2020-05-31 19:52:53 UTC (rev 262365)
+++ trunk/Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp	2020-05-31 23:20:51 UTC (rev 262366)
@@ -7526,7 +7526,14 @@
     queueTaskToDispatchEvent(*canvas, TaskSource::WebGL, WebGLContextEvent::create(eventNames().webglcontextchangedEvent, Event::CanBubble::No, Event::IsCancelable::Yes, emptyString()));
 }
 
+void WebGLRenderingContextBase::prepareForDisplay()
+{
+    if (!m_context)
+        return;
 
+    m_context->prepareForDisplay();
+}
+
 } // namespace WebCore
 
 #endif // ENABLE(WEBGL)

Modified: trunk/Source/WebCore/html/canvas/WebGLRenderingContextBase.h (262365 => 262366)


--- trunk/Source/WebCore/html/canvas/WebGLRenderingContextBase.h	2020-05-31 19:52:53 UTC (rev 262365)
+++ trunk/Source/WebCore/html/canvas/WebGLRenderingContextBase.h	2020-05-31 23:20:51 UTC (rev 262366)
@@ -382,6 +382,8 @@
     // Used for testing only, from Internals.
     WEBCORE_EXPORT void setFailNextGPUStatusCheck();
 
+    void prepareForDisplay();
+
     // GraphicsContextGL::Client
     void didComposite() override;
     void forceContextLost() override;

Modified: trunk/Source/WebCore/page/Page.cpp (262365 => 262366)


--- trunk/Source/WebCore/page/Page.cpp	2020-05-31 19:52:53 UTC (rev 262365)
+++ trunk/Source/WebCore/page/Page.cpp	2020-05-31 23:20:51 UTC (rev 262366)
@@ -1463,6 +1463,10 @@
     if (UNLIKELY(isMonitoringWheelEvents()))
         wheelEventTestMonitor()->checkShouldFireCallbacks();
 
+    forEachDocument([] (Document& document) {
+        document.prepareCanvasesForDisplayIfNeeded();
+    });
+
 #if ASSERT_ENABLED
     for (Frame* child = mainFrame().tree().firstRenderedChild(); child; child = child->tree().traverseNextRendered()) {
         auto* frameView = child->view();

Modified: trunk/Source/WebCore/platform/graphics/cocoa/GraphicsContextGLOpenGLCocoa.mm (262365 => 262366)


--- trunk/Source/WebCore/platform/graphics/cocoa/GraphicsContextGLOpenGLCocoa.mm	2020-05-31 19:52:53 UTC (rev 262365)
+++ trunk/Source/WebCore/platform/graphics/cocoa/GraphicsContextGLOpenGLCocoa.mm	2020-05-31 23:20:51 UTC (rev 262366)
@@ -867,6 +867,11 @@
 }
 #endif // !PLATFORM(MAC)
 
+void GraphicsContextGLOpenGL::prepareForDisplay()
+{
+    [m_webGLLayer prepareForDisplay];
 }
 
+}
+
 #endif // ENABLE(GRAPHICS_CONTEXT_GL)

Modified: trunk/Source/WebCore/platform/graphics/cocoa/WebGLLayer.h (262365 => 262366)


--- trunk/Source/WebCore/platform/graphics/cocoa/WebGLLayer.h	2020-05-31 19:52:53 UTC (rev 262365)
+++ trunk/Source/WebCore/platform/graphics/cocoa/WebGLLayer.h	2020-05-31 23:20:51 UTC (rev 262366)
@@ -62,6 +62,7 @@
     void* _sparePbuffer;
     void* _latchedPbuffer;
 #endif
+    BOOL _prepared;
 }
 
 @property (nonatomic) NakedPtr<WebCore::GraphicsContextGLOpenGL> context;
@@ -70,6 +71,8 @@
 
 - (CGImageRef)copyImageSnapshotWithColorSpace:(CGColorSpaceRef)colorSpace;
 
+- (void)prepareForDisplay;
+
 #if USE(OPENGL) || USE(ANGLE)
 - (void)allocateIOSurfaceBackingStoreWithSize:(WebCore::IntSize)size usingAlpha:(BOOL)usingAlpha;
 - (void)bindFramebufferToNextAvailableSurface;

Modified: trunk/Source/WebCore/platform/graphics/cocoa/WebGLLayer.mm (262365 => 262366)


--- trunk/Source/WebCore/platform/graphics/cocoa/WebGLLayer.mm	2020-05-31 19:52:53 UTC (rev 262365)
+++ trunk/Source/WebCore/platform/graphics/cocoa/WebGLLayer.mm	2020-05-31 23:20:51 UTC (rev 262366)
@@ -163,21 +163,21 @@
 #endif
 }
 
-- (void)display
+- (void)prepareForDisplay
 {
     if (!_context)
         return;
 
+    // To avoid running any OpenGL code in `display`, this method should be called
+    // at the end of the rendering task. We will flush all painting commands
+    // leaving the buffers ready to composite.
+
 #if USE(OPENGL)
     _context->prepareTexture();
     if (_drawingBuffer) {
         std::swap(_contentsBuffer, _drawingBuffer);
-        self.contents = _contentsBuffer->asLayerContents();
-        [self reloadValueForKeyPath:@"contents"];
         [self bindFramebufferToNextAvailableSurface];
     }
-#elif USE(OPENGL_ES)
-    _context->presentRenderbuffer();
 #elif USE(ANGLE)
     if (!_context->makeContextCurrent()) {
         // Context is likely being torn down.
@@ -198,12 +198,32 @@
             }
             _latchedPbuffer = nullptr;
         }
+
         std::swap(_contentsBuffer, _drawingBuffer);
         std::swap(_contentsPbuffer, _drawingPbuffer);
+        [self bindFramebufferToNextAvailableSurface];
+    }
+#endif
+
+    _prepared = YES;
+}
+
+- (void)display
+{
+    if (!_context)
+        return;
+
+    // At this point we've painted into the _drawingBuffer and swapped it with the old _contentsBuffer,
+    // so all we need to do here is tickle the CALayer to let it know it has new contents.
+    // This avoids running any OpenGL code in this method.
+
+#if USE(OPENGL) || USE(ANGLE)
+    if (_contentsBuffer && _prepared) {
         self.contents = _contentsBuffer->asLayerContents();
         [self reloadValueForKeyPath:@"contents"];
-        [self bindFramebufferToNextAvailableSurface];
     }
+#elif USE(OPENGL_ES)
+    _context->presentRenderbuffer();
 #endif
 
     _context->markLayerComposited();
@@ -210,6 +230,8 @@
     auto layer = WebCore::PlatformCALayer::platformCALayerForLayer((__bridge void*)self);
     if (layer && layer->owner())
         layer->owner()->platformCALayerLayerDidDisplay(layer.get());
+
+    _prepared = NO;
 }
 
 #if USE(ANGLE)

Modified: trunk/Source/WebCore/platform/graphics/opengl/GraphicsContextGLOpenGL.cpp (262365 => 262366)


--- trunk/Source/WebCore/platform/graphics/opengl/GraphicsContextGLOpenGL.cpp	2020-05-31 19:52:53 UTC (rev 262365)
+++ trunk/Source/WebCore/platform/graphics/opengl/GraphicsContextGLOpenGL.cpp	2020-05-31 23:20:51 UTC (rev 262366)
@@ -782,6 +782,10 @@
 void GraphicsContextGLOpenGL::simulateContextChanged()
 {
 }
+
+void GraphicsContextGLOpenGL::prepareForDisplay()
+{
+}
 #endif
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/platform/graphics/opengl/GraphicsContextGLOpenGL.h (262365 => 262366)


--- trunk/Source/WebCore/platform/graphics/opengl/GraphicsContextGLOpenGL.h	2020-05-31 19:52:53 UTC (rev 262365)
+++ trunk/Source/WebCore/platform/graphics/opengl/GraphicsContextGLOpenGL.h	2020-05-31 23:20:51 UTC (rev 262366)
@@ -661,6 +661,8 @@
     void screenDidChange(PlatformDisplayID);
 #endif
 
+    void prepareForDisplay();
+
 private:
     GraphicsContextGLOpenGL(GraphicsContextGLAttributes, HostWindow*, Destination = Destination::Offscreen, GraphicsContextGLOpenGL* sharedContext = nullptr);
 

Modified: trunk/Tools/ChangeLog (262365 => 262366)


--- trunk/Tools/ChangeLog	2020-05-31 19:52:53 UTC (rev 262365)
+++ trunk/Tools/ChangeLog	2020-05-31 23:20:51 UTC (rev 262366)
@@ -1,3 +1,18 @@
+2020-05-31  Dean Jackson  <d...@apple.com>
+
+        AutoTrader crashed while browsing search results
+        https://bugs.webkit.org/show_bug.cgi?id=212461
+        rdar://60733185
+
+        Reviewed by Sam Weinig.
+
+        * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+        * TestWebKitAPI/Tests/WebKitLegacy/ios/WebGLPrepareDisplayOnWebThread.mm: Added.
+        (-[WebGLPrepareDisplayOnWebThreadDelegate webViewDidFinishLoad:]):
+        (-[WebGLPrepareDisplayOnWebThreadDelegate webView:shouldStartLoadWithRequest:navigationType:]):
+        (TestWebKitAPI::TEST):
+        * TestWebKitAPI/Tests/WebKitLegacy/ios/webgl.html: Added.
+
 2020-05-31  Carlos Garcia Campos  <cgar...@igalia.com>
 
         Unreviewed. Fix GTK4 build with current GTK

Modified: trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj (262365 => 262366)


--- trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj	2020-05-31 19:52:53 UTC (rev 262365)
+++ trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj	2020-05-31 23:20:51 UTC (rev 262366)
@@ -192,6 +192,8 @@
 		315118101DB1AE4000176304 /* ExtendedColorTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3151180F1DB1ADD500176304 /* ExtendedColorTests.cpp */; };
 		31B76E4323298E2C007FED2C /* SystemPreview.mm in Sources */ = {isa = PBXBuildFile; fileRef = 31B76E4223298E2B007FED2C /* SystemPreview.mm */; };
 		31B76E4523299BDC007FED2C /* system-preview-trigger.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 31B76E4423299BA3007FED2C /* system-preview-trigger.html */; };
+		31E9BDA1247F4C62002E51A2 /* WebGLPrepareDisplayOnWebThread.mm in Sources */ = {isa = PBXBuildFile; fileRef = 31E9BDA0247F4C62002E51A2 /* WebGLPrepareDisplayOnWebThread.mm */; };
+		31E9BDA3247F5729002E51A2 /* webgl.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 31E9BDA2247F4DD0002E51A2 /* webgl.html */; };
 		33BE5AF9137B5AAE00705813 /* MouseMoveAfterCrash_Bundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 33BE5AF8137B5AAE00705813 /* MouseMoveAfterCrash_Bundle.cpp */; };
 		33DC8912141955FE00747EF7 /* simple-iframe.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 33DC890E1419539300747EF7 /* simple-iframe.html */; };
 		33DC89141419579F00747EF7 /* LoadCanceledNoServerRedirectCallback_Bundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 33DC89131419579F00747EF7 /* LoadCanceledNoServerRedirectCallback_Bundle.cpp */; };
@@ -1591,6 +1593,7 @@
 				57EDFC5C245A1A3F00959521 /* web-authentication-make-credential-la-no-mock.html in Copy Resources */,
 				5742178E2400D2DF002B303D /* web-authentication-make-credential-la.html in Copy Resources */,
 				1C2B81861C89259D00A5529F /* webfont.html in Copy Resources */,
+				31E9BDA3247F5729002E51A2 /* webgl.html in Copy Resources */,
 				51714EB41CF8C78C004723C4 /* WebProcessKillIDBCleanup-1.html in Copy Resources */,
 				51714EB51CF8C78C004723C4 /* WebProcessKillIDBCleanup-2.html in Copy Resources */,
 				536770361CC81B6100D425B1 /* WebScriptObjectDescription.html in Copy Resources */,
@@ -1812,6 +1815,8 @@
 		3151180F1DB1ADD500176304 /* ExtendedColorTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ExtendedColorTests.cpp; sourceTree = "<group>"; };
 		31B76E4223298E2B007FED2C /* SystemPreview.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = SystemPreview.mm; sourceTree = "<group>"; };
 		31B76E4423299BA3007FED2C /* system-preview-trigger.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = "system-preview-trigger.html"; sourceTree = "<group>"; };
+		31E9BDA0247F4C62002E51A2 /* WebGLPrepareDisplayOnWebThread.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = WebGLPrepareDisplayOnWebThread.mm; sourceTree = "<group>"; };
+		31E9BDA2247F4DD0002E51A2 /* webgl.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = webgl.html; sourceTree = "<group>"; };
 		333B9CE11277F23100FEFCE3 /* PreventEmptyUserAgent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PreventEmptyUserAgent.cpp; sourceTree = "<group>"; };
 		33BE5AF4137B5A6C00705813 /* MouseMoveAfterCrash.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MouseMoveAfterCrash.cpp; sourceTree = "<group>"; };
 		33BE5AF8137B5AAE00705813 /* MouseMoveAfterCrash_Bundle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MouseMoveAfterCrash_Bundle.cpp; sourceTree = "<group>"; };
@@ -4411,6 +4416,7 @@
 				CDC0932A21C872C10030C4B0 /* ScrollingDoesNotPauseMedia.mm */,
 				F434CA1922E65BCA005DDB26 /* ScrollToRevealSelection.mm */,
 				0F4FFA9D1ED3AA8500F7111F /* SnapshotViaRenderInContext.mm */,
+				31E9BDA0247F4C62002E51A2 /* WebGLPrepareDisplayOnWebThread.mm */,
 			);
 			path = ios;
 			sourceTree = "<group>";
@@ -4428,6 +4434,7 @@
 				CD758A6E20572D540071834A /* video-with-paused-audio-and-playing-muted.html */,
 				CDC8E48B1BC5C96200594FEC /* video-without-audio.html */,
 				CDC8E48C1BC5C96200594FEC /* video-without-audio.mp4 */,
+				31E9BDA2247F4DD0002E51A2 /* webgl.html */,
 			);
 			name = Resources;
 			sourceTree = "<group>";
@@ -5247,6 +5254,7 @@
 				57A79857224AB34E00A7F6F1 /* WebCryptoMasterKey.mm in Sources */,
 				C1FF9EDB244644F000839AE4 /* WebFilter.mm in Sources */,
 				5C973F5C1F58EF8B00359C27 /* WebGLPolicy.mm in Sources */,
+				31E9BDA1247F4C62002E51A2 /* WebGLPrepareDisplayOnWebThread.mm in Sources */,
 				7CCE7EAB1A411A2400447C4C /* WebKitAgnosticTest.mm in Sources */,
 				51714EB81CF8CA17004723C4 /* WebProcessKillIDBCleanup.mm in Sources */,
 				536770341CC8022800D425B1 /* WebScriptObjectDescription.mm in Sources */,

Added: trunk/Tools/TestWebKitAPI/Tests/WebKitLegacy/ios/WebGLPrepareDisplayOnWebThread.mm (0 => 262366)


--- trunk/Tools/TestWebKitAPI/Tests/WebKitLegacy/ios/WebGLPrepareDisplayOnWebThread.mm	                        (rev 0)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitLegacy/ios/WebGLPrepareDisplayOnWebThread.mm	2020-05-31 23:20:51 UTC (rev 262366)
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2020 Apple 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 COMPUTER, INC. ``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 COMPUTER, INC. OR
+ * 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.
+ */
+
+#import "config.h"
+
+#if HAVE(UIWEBVIEW)
+
+#import "PlatformUtilities.h"
+#import <_javascript_Core/JSVirtualMachine.h>
+#import <_javascript_Core/JSVirtualMachineInternal.h>
+#import <UIKit/UIKit.h>
+#import <WebCore/WebCoreThread.h>
+#import <stdlib.h>
+#import <wtf/RetainPtr.h>
+
+@interface WebGLPrepareDisplayOnWebThreadDelegate : NSObject <UIWebViewDelegate> {
+}
+@end
+
+static bool didFinishLoad = false;
+static bool didFinishPainting = false;
+static bool isReady = false;
+
+@implementation WebGLPrepareDisplayOnWebThreadDelegate
+
+IGNORE_WARNINGS_BEGIN("deprecated-implementations")
+- (void)webViewDidFinishLoad:(UIWebView *)webView
+{
+    didFinishLoad = true;
+}
+
+- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
+{
+    if ([request.URL.scheme isEqualToString:@"callback"] && [request.URL.resourceSpecifier isEqualToString:@"didFinishPainting"]) {
+        didFinishPainting = true;
+        return NO;
+    }
+
+    if ([request.URL.scheme isEqualToString:@"callback"] && [request.URL.resourceSpecifier isEqualToString:@"isReady"]) {
+        isReady = true;
+        return NO;
+    }
+
+    return YES;
+}
+IGNORE_WARNINGS_END
+
+@end
+
+namespace TestWebKitAPI {
+
+TEST(WebKitLegacy, WebGLPrepareDisplayOnWebThread)
+{
+    RetainPtr<UIWindow> uiWindow = adoptNS([[UIWindow alloc] initWithFrame:NSMakeRect(0, 0, 800, 600)]);
+    RetainPtr<UIWebView> uiWebView = adoptNS([[UIWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600)]);
+    [uiWindow addSubview:uiWebView.get()];
+
+    RetainPtr<WebGLPrepareDisplayOnWebThreadDelegate> uiDelegate = adoptNS([[WebGLPrepareDisplayOnWebThreadDelegate alloc] init]);
+    uiWebView.get().delegate = uiDelegate.get();
+
+    NSURL *url = "" mainBundle] URLForResource:@"webgl" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
+    NSLog(@"Loading %@", url);
+    [uiWebView loadRequest:[NSURLRequest requestWithURL:url]];
+
+    Util::run(&didFinishLoad);
+    Util::run(&isReady);
+
+    RetainPtr<JSContext> jsContext = [uiWebView valueForKeyPath:@"documentView.webView.mainFrame._javascript_Context"];
+
+    EXPECT_TRUE(!!jsContext.get());
+
+    RetainPtr<JSVirtualMachine> jsVM = [jsContext virtualMachine];
+    EXPECT_TRUE([jsVM isWebThreadAware]);
+
+    // Release WebThread lock.
+    Util::spinRunLoop(1);
+
+    EXPECT_FALSE(WebThreadIsLocked());
+
+    [jsContext evaluateScript:@"loadColorIntoTexture(128, 128, 255, 255)"];
+    [jsContext evaluateScript:@"draw()"];
+    Util::run(&didFinishPainting);
+
+}
+
+}
+
+#endif

Added: trunk/Tools/TestWebKitAPI/Tests/WebKitLegacy/ios/webgl.html (0 => 262366)


--- trunk/Tools/TestWebKitAPI/Tests/WebKitLegacy/ios/webgl.html	                        (rev 0)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitLegacy/ios/webgl.html	2020-05-31 23:20:51 UTC (rev 262366)
@@ -0,0 +1,142 @@
+<!DOCTYPE html>
+<head>
+<title>WebGL drawing</title>
+<style>
+canvas {
+    width: 100px;
+    height: 100px;
+}
+</style>
+</head>
+<script id="vertexShaderSource" type="text/glsl">
+attribute vec4 a_position;
+varying vec2 v_texturePosition;
+
+void main() {
+    v_texturePosition = vec2((a_position.x + 1.0) / 2.0, (a_position.y + 1.0) / 2.0);
+    gl_Position = a_position;
+}
+</script>
+<script id="fragmentShaderSource" type="text/glsl">
+precision mediump float;
+
+varying vec2 v_texturePosition;
+
+uniform sampler2D texture;
+
+void main() {
+  gl_FragColor = texture2D(texture, v_texturePosition);
+}
+</script>
+<script>
+let texture;
+let gl;
+let textureUniform;
+let NUMBER_OF_PAINTS_REMAINING = 60;
+
+function signalReady() {
+    window.location = "callback:isReady";
+}
+
+function signalFinished() {
+    window.location = "callback:didFinishPainting";
+}
+
+function loadColorIntoTexture(r, g, b, a) {
+    gl.bindTexture(gl.TEXTURE_2D, texture);
+    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array([r, g, b, a]));
+}
+
+function draw() {
+    gl.clear(gl.COLOR_BUFFER_BIT);
+
+    gl.activeTexture(gl.TEXTURE0);
+    gl.bindTexture(gl.TEXTURE_2D, texture);
+
+    gl.drawArrays(gl.TRIANGLES, 0, 6);
+
+    if (NUMBER_OF_PAINTS_REMAINING--) {
+        window.requestAnimationFrame(draw);
+    } else {
+        signalFinished();
+    }
+};
+
+function run() {
+
+    let canvas = document.querySelector("canvas");
+    canvas.width = 100;
+    canvas.height = 100;
+
+    gl = canvas.getContext("webgl");
+
+    gl.clearColor(0, 0, 1, 1);
+
+    let vertexShader = gl.createShader(gl.VERTEX_SHADER);
+
+    gl.shaderSource(vertexShader, document.getElementById("vertexShaderSource").textContent);
+
+    gl.compileShader(vertexShader);
+    if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) {
+        // We failed to compile. Output to the console and quit.
+        console.error("Vertex Shader failed to compile.");
+        console.log(gl.getShaderInfoLog(vertexShader));
+        return;
+    }
+
+    let fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
+    gl.shaderSource(fragmentShader, document.getElementById("fragmentShaderSource").textContent);
+    gl.compileShader(fragmentShader);
+    if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) {
+        console.error("Fragment Shader failed to compile.");
+        console.log(gl.getShaderInfoLog(fragmentShader));
+        return;
+    }
+
+    let program = gl.createProgram();
+    gl.attachShader(program, vertexShader);
+    gl.attachShader(program, fragmentShader);
+    gl.linkProgram(program);
+
+    if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
+        console.error("Unable to link shaders into program.");
+        return;
+    }
+
+    gl.useProgram(program);
+
+    let textureUniform = gl.getUniformLocation(program, "texture");
+
+    let positionAttribute = gl.getAttribLocation(program, "a_position");
+    gl.enableVertexAttribArray(positionAttribute);
+
+    let vertices = new Float32Array([
+       -1, -1,
+       1, -1,
+       1, 1,
+       1, 1,
+       -1, 1,
+       -1, -1
+    ]);
+
+    let quadBuffer = gl.createBuffer();
+
+    gl.bindBuffer(gl.ARRAY_BUFFER, quadBuffer);
+    gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
+
+    texture = gl.createTexture();
+    loadColorIntoTexture(0, 128, 255, 255);
+
+    gl.bindBuffer(gl.ARRAY_BUFFER, quadBuffer);
+    gl.vertexAttribPointer(positionAttribute, 2, gl.FLOAT, false, 0, 0);
+
+    gl.uniform1i(textureUniform, 0);
+
+    signalReady();
+}
+
+window.addEventListener("load", run, false);
+</script>
+<body>
+    <canvas></canvas>
+</body>
Property changes on: trunk/Tools/TestWebKitAPI/Tests/WebKitLegacy/ios/webgl.html
___________________________________________________________________

Added: svn:eol-style

+native \ No newline at end of property

Added: svn:keywords

+Date Revision \ No newline at end of property

Added: svn:mime-type

+text/html \ No newline at end of property
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to