Title: [112187] trunk/Source/WebCore
Revision
112187
Author
[email protected]
Date
2012-03-26 18:31:50 -0700 (Mon, 26 Mar 2012)

Log Message

Make filters and the threaded compositor play well together.
https://bugs.webkit.org/show_bug.cgi?id=78139
        
Use a dedicated GraphicsContext3D instance for all filters calls in
the threaded case.  Clone all FilterOperations for thread safety
in the threaded case.

Reviewed by James Robinson.
        
Covered by tests in LayoutTests/css3/filters.

* platform/graphics/chromium/LayerChromium.cpp:
(WebCore::LayerChromium::setFilters):
Set a global flag if we've seen content with filters, so we know
we need to create the filter context.
(WebCore::LayerChromium::pushPropertiesTo):
Clone all filter operations if we're in the threaded case.
* platform/graphics/chromium/cc/CCLayerTreeHost.cpp:
(WebCore):
* platform/graphics/chromium/cc/CCLayerTreeHost.h:
(WebCore::CCLayerTreeHost::needsFilterContext):
(WebCore::CCLayerTreeHost::setNeedsFilterContext):
(CCLayerTreeHost):
Add flag and accessors for needsFilterContext.
* platform/graphics/chromium/cc/CCRenderSurface.cpp:
(WebCore::CCRenderSurface::applyFilters):
Pick up the appropriate context from SharedGraphicsContext3D,
depending if we're in the threaded case or not.
* platform/graphics/chromium/cc/CCThreadProxy.cpp:
(WebCore::CCThreadProxy::recreateContext):
For the threaded compositor re-create the filter context
alongside the main compositor context on lost context, if requested.
(WebCore::CCThreadProxy::beginFrame):
Create the filter context in beginFrame, if it was resquested and is
NULL.  This handles the first-use case.
* platform/graphics/filters/CustomFilterOperation.h:
(WebCore::CustomFilterOperation::clone):
Assert if trying to clone the custom filter operation (it has
non-threadsafe members).
* platform/graphics/filters/FilterOperation.h:
(WebCore::DefaultFilterOperation::clone):
(WebCore::PassthroughFilterOperation::clone):
(WebCore::ReferenceFilterOperation::clone):
(WebCore::BasicColorMatrixFilterOperation::clone):
(WebCore::BasicComponentTransferFilterOperation::clone):
(WebCore::GammaFilterOperation::clone):
(WebCore::BlurFilterOperation::clone):
(WebCore::DropShadowFilterOperation::clone):
Add clone methods for all FilterOperations.
* platform/graphics/gpu/SharedGraphicsContext3D.cpp:
(WebCore::SharedGraphicsContext3DImpl::getOrCreateContext):
(WebCore::SharedGraphicsContext3DImpl::getContext):
(WebCore::SharedGraphicsContext3DImpl::createContext):
(WebCore::SharedGraphicsContext3D::get):
(WebCore::getOrCreateContextForImplThread):
(WebCore::SharedGraphicsContext3D::getForImplThread):
(WebCore::SharedGraphicsContext3D::haveForImplThread):
(WebCore::SharedGraphicsContext3D::createForImplThread):
Split out context creation, lost context recovery, and retrieval
into separate functions, so the impl thread can use only the parts
it wants on the threads it wants (create and have on main, get on impl).
Add asserts to ensure that's how they're called.
* platform/graphics/gpu/SharedGraphicsContext3D.h:
(SharedGraphicsContext3D):
Reuse the SharedGraphicsContext infrastructure to create a new
context singleton for filter use in the threaded compositor.

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (112186 => 112187)


--- trunk/Source/WebCore/ChangeLog	2012-03-27 01:21:51 UTC (rev 112186)
+++ trunk/Source/WebCore/ChangeLog	2012-03-27 01:31:50 UTC (rev 112187)
@@ -1,3 +1,72 @@
+2012-03-26  Stephen White  <[email protected]>
+
+        Make filters and the threaded compositor play well together.
+        https://bugs.webkit.org/show_bug.cgi?id=78139
+        
+        Use a dedicated GraphicsContext3D instance for all filters calls in
+        the threaded case.  Clone all FilterOperations for thread safety
+        in the threaded case.
+
+        Reviewed by James Robinson.
+        
+        Covered by tests in LayoutTests/css3/filters.
+
+        * platform/graphics/chromium/LayerChromium.cpp:
+        (WebCore::LayerChromium::setFilters):
+        Set a global flag if we've seen content with filters, so we know
+        we need to create the filter context.
+        (WebCore::LayerChromium::pushPropertiesTo):
+        Clone all filter operations if we're in the threaded case.
+        * platform/graphics/chromium/cc/CCLayerTreeHost.cpp:
+        (WebCore):
+        * platform/graphics/chromium/cc/CCLayerTreeHost.h:
+        (WebCore::CCLayerTreeHost::needsFilterContext):
+        (WebCore::CCLayerTreeHost::setNeedsFilterContext):
+        (CCLayerTreeHost):
+        Add flag and accessors for needsFilterContext.
+        * platform/graphics/chromium/cc/CCRenderSurface.cpp:
+        (WebCore::CCRenderSurface::applyFilters):
+        Pick up the appropriate context from SharedGraphicsContext3D,
+        depending if we're in the threaded case or not.
+        * platform/graphics/chromium/cc/CCThreadProxy.cpp:
+        (WebCore::CCThreadProxy::recreateContext):
+        For the threaded compositor re-create the filter context
+        alongside the main compositor context on lost context, if requested.
+        (WebCore::CCThreadProxy::beginFrame):
+        Create the filter context in beginFrame, if it was resquested and is
+        NULL.  This handles the first-use case.
+        * platform/graphics/filters/CustomFilterOperation.h:
+        (WebCore::CustomFilterOperation::clone):
+        Assert if trying to clone the custom filter operation (it has
+        non-threadsafe members).
+        * platform/graphics/filters/FilterOperation.h:
+        (WebCore::DefaultFilterOperation::clone):
+        (WebCore::PassthroughFilterOperation::clone):
+        (WebCore::ReferenceFilterOperation::clone):
+        (WebCore::BasicColorMatrixFilterOperation::clone):
+        (WebCore::BasicComponentTransferFilterOperation::clone):
+        (WebCore::GammaFilterOperation::clone):
+        (WebCore::BlurFilterOperation::clone):
+        (WebCore::DropShadowFilterOperation::clone):
+        Add clone methods for all FilterOperations.
+        * platform/graphics/gpu/SharedGraphicsContext3D.cpp:
+        (WebCore::SharedGraphicsContext3DImpl::getOrCreateContext):
+        (WebCore::SharedGraphicsContext3DImpl::getContext):
+        (WebCore::SharedGraphicsContext3DImpl::createContext):
+        (WebCore::SharedGraphicsContext3D::get):
+        (WebCore::getOrCreateContextForImplThread):
+        (WebCore::SharedGraphicsContext3D::getForImplThread):
+        (WebCore::SharedGraphicsContext3D::haveForImplThread):
+        (WebCore::SharedGraphicsContext3D::createForImplThread):
+        Split out context creation, lost context recovery, and retrieval
+        into separate functions, so the impl thread can use only the parts
+        it wants on the threads it wants (create and have on main, get on impl).
+        Add asserts to ensure that's how they're called.
+        * platform/graphics/gpu/SharedGraphicsContext3D.h:
+        (SharedGraphicsContext3D):
+        Reuse the SharedGraphicsContext infrastructure to create a new
+        context singleton for filter use in the threaded compositor.
+
 2012-03-26  Adam Barth  <[email protected]>
 
         FrameLoader::shouldAllowNavigation uses Frame for context rather than Document

Modified: trunk/Source/WebCore/platform/graphics/chromium/LayerChromium.cpp (112186 => 112187)


--- trunk/Source/WebCore/platform/graphics/chromium/LayerChromium.cpp	2012-03-27 01:21:51 UTC (rev 112186)
+++ trunk/Source/WebCore/platform/graphics/chromium/LayerChromium.cpp	2012-03-27 01:31:50 UTC (rev 112187)
@@ -318,6 +318,7 @@
         return;
     m_filters = filters;
     setNeedsCommit();
+    CCLayerTreeHost::setNeedsFilterContext();
 }
 
 void LayerChromium::setOpacity(float opacity)
@@ -459,6 +460,18 @@
     layer->setDebugName(m_debugName.isolatedCopy()); // We have to use isolatedCopy() here to safely pass ownership to another thread.
     layer->setDoubleSided(m_doubleSided);
     layer->setDrawsContent(drawsContent());
+    if (CCProxy::hasImplThread()) {
+        // Since FilterOperations contains a vector of RefPtrs, we must deep copy the filters.
+        FilterOperations filtersCopy;
+        for (unsigned i = 0; i < m_filters.size(); ++i) {
+            RefPtr<FilterOperation> clone = m_filters.at(i)->clone();
+            if (clone)
+                filtersCopy.operations().append(clone);
+        }
+        layer->setFilters(filtersCopy);
+    } else
+        layer->setFilters(filters());
+
     layer->setFilters(filters());
     layer->setIsNonCompositedContent(m_isNonCompositedContent);
     layer->setMasksToBounds(m_masksToBounds);

Modified: trunk/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHost.cpp (112186 => 112187)


--- trunk/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHost.cpp	2012-03-27 01:21:51 UTC (rev 112186)
+++ trunk/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHost.cpp	2012-03-27 01:31:50 UTC (rev 112187)
@@ -49,6 +49,8 @@
 
 namespace WebCore {
 
+bool CCLayerTreeHost::s_needsFilterContext = false;
+
 bool CCLayerTreeHost::anyLayerTreeHostInstanceExists()
 {
     return numLayerTreeInstances > 0;

Modified: trunk/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHost.h (112186 => 112187)


--- trunk/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHost.h	2012-03-27 01:21:51 UTC (rev 112186)
+++ trunk/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHost.h	2012-03-27 01:31:50 UTC (rev 112187)
@@ -129,6 +129,9 @@
     // Returns true if any CCLayerTreeHost is alive.
     static bool anyLayerTreeHostInstanceExists();
 
+    static bool needsFilterContext() { return s_needsFilterContext; }
+    static void setNeedsFilterContext() { s_needsFilterContext = true; }
+
     // CCLayerTreeHost interface to CCProxy.
     void willBeginFrame() { m_client->willBeginFrame(); }
     void updateAnimations(double wallClockTime);
@@ -268,6 +271,7 @@
 
     TextureList m_deleteTextureAfterCommitList;
     size_t m_partialTextureUpdateRequests;
+    static bool s_needsFilterContext;
 };
 
 }

Modified: trunk/Source/WebCore/platform/graphics/chromium/cc/CCRenderSurface.cpp (112186 => 112187)


--- trunk/Source/WebCore/platform/graphics/chromium/cc/CCRenderSurface.cpp	2012-03-27 01:21:51 UTC (rev 112186)
+++ trunk/Source/WebCore/platform/graphics/chromium/cc/CCRenderSurface.cpp	2012-03-27 01:31:50 UTC (rev 112187)
@@ -223,13 +223,16 @@
 
 SkBitmap CCRenderSurface::applyFilters(LayerRendererChromium* layerRenderer)
 {
-    // Don't use the utility context if we have a compositor thread, since
-    // it can race with canvas's use.
-    if (!m_contentsTexture || !m_filters.size() || CCProxy::hasImplThread())
+    if (!m_contentsTexture || !m_filters.size())
         return SkBitmap();
 
+    RefPtr<GraphicsContext3D> filterContext = CCProxy::hasImplThread() ? SharedGraphicsContext3D::getForImplThread() : SharedGraphicsContext3D::get();
+    if (!filterContext)
+        return SkBitmap();
+
     layerRenderer->context()->flush();
-    return CCRenderSurfaceFilters::apply(m_filters, m_contentsTexture->textureId(), m_contentRect.size(), SharedGraphicsContext3D::get().get());
+
+    return CCRenderSurfaceFilters::apply(m_filters, m_contentsTexture->textureId(), m_contentRect.size(), filterContext.get());
 }
 
 String CCRenderSurface::name() const

Modified: trunk/Source/WebCore/platform/graphics/chromium/cc/CCThreadProxy.cpp (112186 => 112187)


--- trunk/Source/WebCore/platform/graphics/chromium/cc/CCThreadProxy.cpp	2012-03-27 01:21:51 UTC (rev 112186)
+++ trunk/Source/WebCore/platform/graphics/chromium/cc/CCThreadProxy.cpp	2012-03-27 01:31:50 UTC (rev 112187)
@@ -27,6 +27,7 @@
 #include "cc/CCThreadProxy.h"
 
 #include "GraphicsContext3D.h"
+#include "SharedGraphicsContext3D.h"
 #include "TraceEvent.h"
 #include "cc/CCDelayBasedTimeSource.h"
 #include "cc/CCFrameRateController.h"
@@ -209,6 +210,10 @@
     RefPtr<GraphicsContext3D> context = m_layerTreeHost->createContext();
     if (!context)
         return false;
+    if (CCLayerTreeHost::needsFilterContext())
+        if (!SharedGraphicsContext3D::createForImplThread())
+            return false;
+
     ASSERT(context->hasOneRef());
 
     // Leak the context pointer so we can transfer ownership of it to the other side...
@@ -422,6 +427,9 @@
         return;
     }
 
+    if (CCLayerTreeHost::needsFilterContext() && !SharedGraphicsContext3D::haveForImplThread())
+        SharedGraphicsContext3D::createForImplThread();
+
     OwnPtr<BeginFrameAndCommitState> request(m_pendingBeginFrameRequest.release());
 
     // Do not notify the impl thread of commit requests that occur during

Modified: trunk/Source/WebCore/platform/graphics/filters/CustomFilterOperation.h (112186 => 112187)


--- trunk/Source/WebCore/platform/graphics/filters/CustomFilterOperation.h	2012-03-27 01:21:51 UTC (rev 112186)
+++ trunk/Source/WebCore/platform/graphics/filters/CustomFilterOperation.h	2012-03-27 01:31:50 UTC (rev 112187)
@@ -62,6 +62,13 @@
         return adoptRef(new CustomFilterOperation(program, sortedParameters, meshRows, meshColumns, meshBoxType, meshType));
     }
     
+    virtual PassRefPtr<FilterOperation> clone() const
+    {
+        // Some member vars (e.g., m_program) are not thread-safe, so
+        // we can't be cloned.
+        return 0;
+    }
+    
     CustomFilterProgram* program() const { return m_program.get(); }
     
     const CustomFilterParameterList& parameters() { return m_parameters; }

Modified: trunk/Source/WebCore/platform/graphics/filters/FilterOperation.h (112186 => 112187)


--- trunk/Source/WebCore/platform/graphics/filters/FilterOperation.h	2012-03-27 01:21:51 UTC (rev 112186)
+++ trunk/Source/WebCore/platform/graphics/filters/FilterOperation.h	2012-03-27 01:31:50 UTC (rev 112187)
@@ -82,6 +82,8 @@
     // True if the the value of one pixel can affect the value of another pixel under this operation, such as blur.
     virtual bool movesPixels() const { return false; }
 
+    virtual PassRefPtr<FilterOperation> clone() const = 0;
+
 protected:
     FilterOperation(OperationType type)
         : m_type(type)
@@ -98,6 +100,11 @@
         return adoptRef(new DefaultFilterOperation(type));
     }
 
+    virtual PassRefPtr<FilterOperation> clone() const
+    {
+        return adoptRef(new DefaultFilterOperation(m_type));
+    }
+
 private:
 
     virtual bool operator==(const FilterOperation& o) const
@@ -120,6 +127,11 @@
         return adoptRef(new PassthroughFilterOperation());
     }
 
+    virtual PassRefPtr<FilterOperation> clone() const
+    {
+        return adoptRef(new PassthroughFilterOperation());
+    }
+
 private:
 
     virtual bool operator==(const FilterOperation& o) const
@@ -140,6 +152,12 @@
         return adoptRef(new ReferenceFilterOperation(reference, type));
     }
 
+    virtual PassRefPtr<FilterOperation> clone() const
+    {
+        // AtomicString is thread-hostile, so we can't be cloned.
+        return 0;
+    }
+
     virtual bool affectsOpacity() const { return true; }
     virtual bool movesPixels() const { return true; }
 
@@ -173,6 +191,11 @@
         return adoptRef(new BasicColorMatrixFilterOperation(amount, type));
     }
 
+    virtual PassRefPtr<FilterOperation> clone() const
+    {
+        return adoptRef(new BasicColorMatrixFilterOperation(m_amount, m_type));
+    }
+
     double amount() const { return m_amount; }
 
     virtual PassRefPtr<FilterOperation> blend(const FilterOperation* from, double progress, bool blendToPassthrough = false);
@@ -205,6 +228,11 @@
         return adoptRef(new BasicComponentTransferFilterOperation(amount, type));
     }
 
+    virtual PassRefPtr<FilterOperation> clone() const
+    {
+        return adoptRef(new BasicComponentTransferFilterOperation(m_amount, m_type));
+    }
+
     double amount() const { return m_amount; }
 
     virtual bool affectsOpacity() const { return m_type == OPACITY; }
@@ -238,6 +266,11 @@
         return adoptRef(new GammaFilterOperation(amplitude, exponent, offset, type));
     }
 
+    virtual PassRefPtr<FilterOperation> clone() const
+    {
+        return adoptRef(new GammaFilterOperation(m_amplitude, m_exponent, m_offset, m_type));
+    }
+
     double amplitude() const { return m_amplitude; }
     double exponent() const { return m_exponent; }
     double offset() const { return m_offset; }
@@ -273,6 +306,11 @@
         return adoptRef(new BlurFilterOperation(stdDeviation, type));
     }
 
+    virtual PassRefPtr<FilterOperation> clone() const
+    {
+        return adoptRef(new BlurFilterOperation(m_stdDeviation, m_type));
+    }
+
     Length stdDeviation() const { return m_stdDeviation; }
 
     virtual bool affectsOpacity() const { return true; }
@@ -305,6 +343,11 @@
         return adoptRef(new DropShadowFilterOperation(x, y, stdDeviation, color, type));
     }
 
+    virtual PassRefPtr<FilterOperation> clone() const
+    {
+        return adoptRef(new DropShadowFilterOperation(m_x, m_y, m_stdDeviation, m_color, m_type));
+    }
+
     int x() const { return m_x; }
     int y() const { return m_y; }
     int stdDeviation() const { return m_stdDeviation; }

Modified: trunk/Source/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.cpp (112186 => 112187)


--- trunk/Source/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.cpp	2012-03-27 01:21:51 UTC (rev 112186)
+++ trunk/Source/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.cpp	2012-03-27 01:31:50 UTC (rev 112187)
@@ -28,33 +28,44 @@
 
 #include "SharedGraphicsContext3D.h"
 #include "Extensions3D.h"
+#include "cc/CCProxy.h"
 
 namespace WebCore {
 
 class SharedGraphicsContext3DImpl {
 public:
     SharedGraphicsContext3DImpl() : m_context(0) { }
-    PassRefPtr<GraphicsContext3D> get()
+    PassRefPtr<GraphicsContext3D> getOrCreateContext()
     {
         // If we lost the context, or can't make it current, create a new one.
         if (m_context && (!m_context->makeContextCurrent() || (m_context->getExtensions()->getGraphicsResetStatusARB() != GraphicsContext3D::NO_ERROR)))
             m_context.clear();
 
-        if (!m_context) {
-            GraphicsContext3D::Attributes attributes;
-            attributes.depth = false;
-            attributes.stencil = true;
-            attributes.antialias = false;
-            attributes.shareResources = true;
-            attributes.preferDiscreteGPU = true;
-            m_context = GraphicsContext3D::create(attributes, 0);
-        }
+        if (!m_context)
+            createContext();
 
         if (m_context && !m_context->makeContextCurrent())
             m_context.clear();
 
         return m_context;
     }
+
+    PassRefPtr<GraphicsContext3D> getContext()
+    {
+        return m_context;
+    }
+
+    PassRefPtr<GraphicsContext3D> createContext()
+    {
+        GraphicsContext3D::Attributes attributes;
+        attributes.depth = false;
+        attributes.stencil = true;
+        attributes.antialias = false;
+        attributes.shareResources = true;
+        attributes.preferDiscreteGPU = true;
+        m_context = GraphicsContext3D::create(attributes, 0);
+        return m_context;
+    }
 private:
     RefPtr<GraphicsContext3D> m_context;
 };
@@ -62,8 +73,36 @@
 PassRefPtr<GraphicsContext3D> SharedGraphicsContext3D::get()
 {
     DEFINE_STATIC_LOCAL(SharedGraphicsContext3DImpl, impl, ());
-    return impl.get();
+    return impl.getOrCreateContext();
 }
 
+enum ContextOperation {
+    Get, Create
+};
+
+static PassRefPtr<GraphicsContext3D> getOrCreateContextForImplThread(ContextOperation op)
+{
+    DEFINE_STATIC_LOCAL(SharedGraphicsContext3DImpl, impl, ());
+    return op == Create ? impl.createContext() : impl.getContext();
 }
 
+PassRefPtr<GraphicsContext3D> SharedGraphicsContext3D::getForImplThread()
+{
+    ASSERT(CCProxy::isImplThread());
+    return getOrCreateContextForImplThread(Get);
+}
+
+bool SharedGraphicsContext3D::haveForImplThread()
+{
+    ASSERT(CCProxy::isMainThread());
+    return getOrCreateContextForImplThread(Get);
+}
+
+bool SharedGraphicsContext3D::createForImplThread()
+{
+    ASSERT(CCProxy::isMainThread());
+    return getOrCreateContextForImplThread(Create);
+}
+
+}
+

Modified: trunk/Source/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.h (112186 => 112187)


--- trunk/Source/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.h	2012-03-27 01:21:51 UTC (rev 112186)
+++ trunk/Source/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.h	2012-03-27 01:31:50 UTC (rev 112187)
@@ -40,6 +40,15 @@
     // function again. Note that the return value may be 0 if the
     // GPU is unavailable.
     static PassRefPtr<GraphicsContext3D> get();
+    // This one returns the context, and does not touch it or re-create it.
+    // Should only be called on the impl thread.
+    static PassRefPtr<GraphicsContext3D> getForImplThread();
+    // This one returns if the threaded utility context exists.
+    // Should only be called on the main thread.
+    static bool haveForImplThread();
+    // This call creates the context unconditionally, but does not touch it.
+    // Should only be called on the main thread.
+    static bool createForImplThread();
 };
 
 }
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to