Title: [108093] trunk/Source
Revision
108093
Author
[email protected]
Date
2012-02-17 10:27:32 -0800 (Fri, 17 Feb 2012)

Log Message

[chromium] Refactor video drawing to be more data driven
https://bugs.webkit.org/show_bug.cgi?id=76720

Patch by Tim Dresser <[email protected]> on 2012-02-17
Reviewed by James Robinson.

Source/WebCore:

CCVideoLayerImpl no longer handles drawing itself, but produces a list of CCVideoDrawQuads.
These quads are then drawn by LayerRendererChromium.

CCLayerImpl::willDraw(LayerRendererChromium*) is called directly before appendQuads.
CCLayerImpl::didDraw() is called directly after all drawing has been completed.
CCLayerImpl::draw has been removed.

willDraw and didDraw are used to handle interaction with the VideoFrameProvider
in CCVideoLayerImpl. willDraw gets a frame from the VideoFrameProvider, and
didDraw returns it.

A unit test has been added: CCLayerTreeHostImplTest.didDrawCalledOnAllLayers.
This test ensures that CCLayerImpl::didDraw() is called on all layers,
including layers on different render surfaces.

As this was a refactor, no other tests were added.

* platform/graphics/chromium/LayerRendererChromium.cpp:
(WebCore::LayerRendererChromium::drawYUV):
(WebCore):
(WebCore::LayerRendererChromium::drawSingleTextureVideoQuad):
(WebCore::LayerRendererChromium::drawRGBA):
(WebCore::LayerRendererChromium::drawNativeTexture):
(WebCore::LayerRendererChromium::copyFrameToTextures):
(WebCore::LayerRendererChromium::copyPlaneToTexture):
(WebCore::LayerRendererChromium::drawVideoQuad):
* platform/graphics/chromium/LayerRendererChromium.h:
(LayerRendererChromium):
* platform/graphics/chromium/cc/CCLayerImpl.cpp:
* platform/graphics/chromium/cc/CCLayerImpl.h:
(WebCore::CCLayerImpl::didDraw):
(CCLayerImpl):
* platform/graphics/chromium/cc/CCLayerTreeHostImpl.cpp:
(WebCore::CCLayerTreeHostImpl::calculateRenderPasses):
(WebCore::CCLayerTreeHostImpl::drawLayers):
* platform/graphics/chromium/cc/CCLayerTreeHostImpl.h:
(CCLayerTreeHostImpl):
* platform/graphics/chromium/cc/CCVideoDrawQuad.cpp:
(WebCore::CCVideoDrawQuad::create):
(WebCore::CCVideoDrawQuad::CCVideoDrawQuad):
* platform/graphics/chromium/cc/CCVideoDrawQuad.h:
(CCVideoDrawQuad):
(WebCore::CCVideoDrawQuad::textures):
(WebCore::CCVideoDrawQuad::frame):
(WebCore::CCVideoDrawQuad::format):
* platform/graphics/chromium/cc/CCVideoLayerImpl.cpp:
(WebCore::CCVideoLayerImpl::willDraw):
(WebCore::CCVideoLayerImpl::appendQuads):
(WebCore::CCVideoLayerImpl::didDraw):
(WebCore::CCVideoLayerImpl::computeVisibleSize):
* platform/graphics/chromium/cc/CCVideoLayerImpl.h:
(CCVideoLayerImpl):
(WebCore::CCVideoLayerImpl::providerMutex):
(WebCore::CCVideoLayerImpl::provider):
(Texture):

Source/WebKit/chromium:

CCLayerTreeHostImplTest.didDrawCalledOnAllLayers ensures that
CCLayerImpl::didDraw() is called on all layers, including layers
on different render surfaces.

* tests/CCLayerTreeHostImplTest.cpp:
(DidDrawCheckLayer):
(WebKit::DidDrawCheckLayer::create):
(WebKit::DidDrawCheckLayer::didDraw):
(WebKit::DidDrawCheckLayer::didDrawCalled):
(WebKit::DidDrawCheckLayer::DidDrawCheckLayer):
(WebKit):
(WebKit::TEST_F):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (108092 => 108093)


--- trunk/Source/WebCore/ChangeLog	2012-02-17 18:19:18 UTC (rev 108092)
+++ trunk/Source/WebCore/ChangeLog	2012-02-17 18:27:32 UTC (rev 108093)
@@ -1,3 +1,66 @@
+2012-02-17  Tim Dresser  <[email protected]>
+
+        [chromium] Refactor video drawing to be more data driven
+        https://bugs.webkit.org/show_bug.cgi?id=76720
+
+        Reviewed by James Robinson.
+
+        CCVideoLayerImpl no longer handles drawing itself, but produces a list of CCVideoDrawQuads.
+        These quads are then drawn by LayerRendererChromium.
+
+        CCLayerImpl::willDraw(LayerRendererChromium*) is called directly before appendQuads.
+        CCLayerImpl::didDraw() is called directly after all drawing has been completed.
+        CCLayerImpl::draw has been removed.
+
+        willDraw and didDraw are used to handle interaction with the VideoFrameProvider
+        in CCVideoLayerImpl. willDraw gets a frame from the VideoFrameProvider, and
+        didDraw returns it.
+
+        A unit test has been added: CCLayerTreeHostImplTest.didDrawCalledOnAllLayers.
+        This test ensures that CCLayerImpl::didDraw() is called on all layers,
+        including layers on different render surfaces.
+
+        As this was a refactor, no other tests were added.
+
+        * platform/graphics/chromium/LayerRendererChromium.cpp:
+        (WebCore::LayerRendererChromium::drawYUV):
+        (WebCore):
+        (WebCore::LayerRendererChromium::drawSingleTextureVideoQuad):
+        (WebCore::LayerRendererChromium::drawRGBA):
+        (WebCore::LayerRendererChromium::drawNativeTexture):
+        (WebCore::LayerRendererChromium::copyFrameToTextures):
+        (WebCore::LayerRendererChromium::copyPlaneToTexture):
+        (WebCore::LayerRendererChromium::drawVideoQuad):
+        * platform/graphics/chromium/LayerRendererChromium.h:
+        (LayerRendererChromium):
+        * platform/graphics/chromium/cc/CCLayerImpl.cpp:
+        * platform/graphics/chromium/cc/CCLayerImpl.h:
+        (WebCore::CCLayerImpl::didDraw):
+        (CCLayerImpl):
+        * platform/graphics/chromium/cc/CCLayerTreeHostImpl.cpp:
+        (WebCore::CCLayerTreeHostImpl::calculateRenderPasses):
+        (WebCore::CCLayerTreeHostImpl::drawLayers):
+        * platform/graphics/chromium/cc/CCLayerTreeHostImpl.h:
+        (CCLayerTreeHostImpl):
+        * platform/graphics/chromium/cc/CCVideoDrawQuad.cpp:
+        (WebCore::CCVideoDrawQuad::create):
+        (WebCore::CCVideoDrawQuad::CCVideoDrawQuad):
+        * platform/graphics/chromium/cc/CCVideoDrawQuad.h:
+        (CCVideoDrawQuad):
+        (WebCore::CCVideoDrawQuad::textures):
+        (WebCore::CCVideoDrawQuad::frame):
+        (WebCore::CCVideoDrawQuad::format):
+        * platform/graphics/chromium/cc/CCVideoLayerImpl.cpp:
+        (WebCore::CCVideoLayerImpl::willDraw):
+        (WebCore::CCVideoLayerImpl::appendQuads):
+        (WebCore::CCVideoLayerImpl::didDraw):
+        (WebCore::CCVideoLayerImpl::computeVisibleSize):
+        * platform/graphics/chromium/cc/CCVideoLayerImpl.h:
+        (CCVideoLayerImpl):
+        (WebCore::CCVideoLayerImpl::providerMutex):
+        (WebCore::CCVideoLayerImpl::provider):
+        (Texture):
+
 2012-02-17  Stephen Chenney  <[email protected]>
 
         Crash at WebCore::SVGUseElement::expandSymbolElementsInShadowTree

Modified: trunk/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp (108092 => 108093)


--- trunk/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp	2012-02-17 18:19:18 UTC (rev 108092)
+++ trunk/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp	2012-02-17 18:27:32 UTC (rev 108093)
@@ -694,10 +694,139 @@
     GLC(m_context.get(), m_context->blendFunc(GraphicsContext3D::ONE, GraphicsContext3D::ONE_MINUS_SRC_ALPHA));
 }
 
+void LayerRendererChromium::drawYUV(const CCVideoDrawQuad* quad)
+{
+    const CCVideoLayerImpl::YUVProgram* program = videoLayerYUVProgram();
+    ASSERT(program && program->initialized());
+
+    const CCVideoLayerImpl::Texture& yTexture = quad->textures()[VideoFrameChromium::yPlane];
+    const CCVideoLayerImpl::Texture& uTexture = quad->textures()[VideoFrameChromium::uPlane];
+    const CCVideoLayerImpl::Texture& vTexture = quad->textures()[VideoFrameChromium::vPlane];
+
+    GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE1));
+    GLC(context(), context()->bindTexture(GraphicsContext3D::TEXTURE_2D, yTexture.m_texture->textureId()));
+    GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE2));
+    GLC(context(), context()->bindTexture(GraphicsContext3D::TEXTURE_2D, uTexture.m_texture->textureId()));
+    GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE3));
+    GLC(context(), context()->bindTexture(GraphicsContext3D::TEXTURE_2D, vTexture.m_texture->textureId()));
+
+    GLC(context(), context()->useProgram(program->program()));
+
+    float yWidthScaleFactor = static_cast<float>(yTexture.m_visibleSize.width()) / yTexture.m_texture->size().width();
+    // Arbitrarily take the u sizes because u and v dimensions are identical.
+    float uvWidthScaleFactor = static_cast<float>(uTexture.m_visibleSize.width()) / uTexture.m_texture->size().width();
+    GLC(context(), context()->uniform1f(program->vertexShader().yWidthScaleFactorLocation(), yWidthScaleFactor));
+    GLC(context(), context()->uniform1f(program->vertexShader().uvWidthScaleFactorLocation(), uvWidthScaleFactor));
+
+    GLC(context(), context()->uniform1i(program->fragmentShader().yTextureLocation(), 1));
+    GLC(context(), context()->uniform1i(program->fragmentShader().uTextureLocation(), 2));
+    GLC(context(), context()->uniform1i(program->fragmentShader().vTextureLocation(), 3));
+
+    GLC(context(), context()->uniformMatrix3fv(program->fragmentShader().ccMatrixLocation(), 0, const_cast<float*>(CCVideoLayerImpl::yuv2RGB), 1));
+    GLC(context(), context()->uniform3fv(program->fragmentShader().yuvAdjLocation(), const_cast<float*>(CCVideoLayerImpl::yuvAdjust), 1));
+
+    const IntSize& bounds = quad->quadRect().size();
+    drawTexturedQuad(quad->layerTransform(), bounds.width(), bounds.height(), quad->opacity(), FloatQuad(),
+                                    program->vertexShader().matrixLocation(),
+                                    program->fragmentShader().alphaLocation(),
+                                    -1);
+
+    // Reset active texture back to texture 0.
+    GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE0));
+}
+
+template<class Program>
+void LayerRendererChromium::drawSingleTextureVideoQuad(const CCVideoDrawQuad* quad, Program* program, float widthScaleFactor, Platform3DObject textureId)
+{
+    ASSERT(program && program->initialized());
+
+    GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE0));
+    GLC(context(), context()->bindTexture(GraphicsContext3D::TEXTURE_2D, textureId));
+
+    GLC(context(), context()->useProgram(program->program()));
+    GLC(context(), context()->uniform4f(program->vertexShader().texTransformLocation(), 0, 0, widthScaleFactor, 1));
+    GLC(context(), context()->uniform1i(program->fragmentShader().samplerLocation(), 0));
+
+    const IntSize& bounds = quad->quadRect().size();
+    drawTexturedQuad(quad->layerTransform(), bounds.width(), bounds.height(), quad->opacity(), sharedGeometryQuad(),
+                                    program->vertexShader().matrixLocation(),
+                                    program->fragmentShader().alphaLocation(),
+                                    -1);
+}
+
+void LayerRendererChromium::drawRGBA(const CCVideoDrawQuad* quad)
+{
+    const CCVideoLayerImpl::RGBAProgram* program = videoLayerRGBAProgram();
+    const CCVideoLayerImpl::Texture& texture = quad->textures()[VideoFrameChromium::rgbPlane];
+    float widthScaleFactor = static_cast<float>(texture.m_visibleSize.width()) / texture.m_texture->size().width();
+    drawSingleTextureVideoQuad(quad, program, widthScaleFactor, texture.m_texture->textureId());
+}
+
+void LayerRendererChromium::drawNativeTexture(const CCVideoDrawQuad* quad)
+{
+    const CCVideoLayerImpl::NativeTextureProgram* program = videoLayerNativeTextureProgram();
+    drawSingleTextureVideoQuad(quad, program, 1, quad->frame()->textureId());
+}
+
+bool LayerRendererChromium::copyFrameToTextures(const CCVideoDrawQuad* quad)
+{
+    const VideoFrameChromium* frame = quad->frame();
+
+    for (unsigned plane = 0; plane < frame->planes(); ++plane) {
+        ASSERT(quad->frame()->requiredTextureSize(plane) == quad->textures()[plane].m_texture->size());
+        copyPlaneToTexture(quad, frame->data(plane), plane);
+    }
+    for (unsigned plane = frame->planes(); plane < CCVideoLayerImpl::MaxPlanes; ++plane) {
+        CCVideoLayerImpl::Texture* texture = &quad->textures()[plane];
+        texture->m_texture.clear();
+        texture->m_visibleSize = IntSize();
+    }
+    return true;
+}
+
+void LayerRendererChromium::copyPlaneToTexture(const CCVideoDrawQuad* quad, const void* plane, int index)
+{
+    CCVideoLayerImpl::Texture& texture = quad->textures()[index];
+    TextureAllocator* allocator = renderSurfaceTextureAllocator();
+    texture.m_texture->bindTexture(context(), allocator);
+    GC3Denum format = texture.m_texture->format();
+    IntSize dimensions = texture.m_texture->size();
+
+    void* mem = static_cast<Extensions3DChromium*>(context()->getExtensions())->mapTexSubImage2DCHROMIUM(GraphicsContext3D::TEXTURE_2D, 0, 0, 0, dimensions.width(), dimensions.height(), format, GraphicsContext3D::UNSIGNED_BYTE, Extensions3DChromium::WRITE_ONLY);
+    if (mem) {
+        memcpy(mem, plane, dimensions.width() * dimensions.height());
+        GLC(context(), static_cast<Extensions3DChromium*>(context()->getExtensions())->unmapTexSubImage2DCHROMIUM(mem));
+    } else {
+        // If mapTexSubImage2DCHROMIUM fails, then do the slower texSubImage2D
+        // upload. This does twice the copies as mapTexSubImage2DCHROMIUM, one
+        // in the command buffer and another to the texture.
+        GLC(context(), context()->texSubImage2D(GraphicsContext3D::TEXTURE_2D, 0, 0, 0, dimensions.width(), dimensions.height(), format, GraphicsContext3D::UNSIGNED_BYTE, plane));
+    }
+}
+
 void LayerRendererChromium::drawVideoQuad(const CCVideoDrawQuad* quad)
 {
-    CCLayerImpl* layer = quad->layer();
-    layer->draw(this);
+    ASSERT(CCProxy::isImplThread());
+
+    if (!quad->frame())
+        return;
+
+    if (!copyFrameToTextures(quad))
+        return;
+
+    switch (quad->format()) {
+    case GraphicsContext3D::LUMINANCE:
+        drawYUV(quad);
+        break;
+    case GraphicsContext3D::RGBA:
+        drawRGBA(quad);
+        break;
+    case GraphicsContext3D::TEXTURE_2D:
+        drawNativeTexture(quad);
+        break;
+    default:
+        CRASH(); // Someone updated convertVFCFormatToGC3DFormat above but update this!
+    }
 }
 
 struct PluginProgramBinding {

Modified: trunk/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.h (108092 => 108093)


--- trunk/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.h	2012-02-17 18:19:18 UTC (rev 108092)
+++ trunk/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.h	2012-02-17 18:27:32 UTC (rev 108093)
@@ -168,6 +168,13 @@
     void drawPluginQuad(const CCPluginDrawQuad*);
 
     ManagedTexture* getOffscreenLayerTexture();
+    void copyPlaneToTexture(const CCVideoDrawQuad*, const void* plane, int index);
+    bool copyFrameToTextures(const CCVideoDrawQuad*);
+    template<class Program> void drawSingleTextureVideoQuad(const CCVideoDrawQuad*, Program*, float widthScaleFactor, Platform3DObject textureId);
+    void drawNativeTexture(const CCVideoDrawQuad*);
+    void drawRGBA(const CCVideoDrawQuad*);
+    void drawYUV(const CCVideoDrawQuad*);
+
     void copyOffscreenTextureToDisplay();
 
     void setDrawViewportRect(const IntRect&, bool flipY);

Modified: trunk/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.cpp (108092 => 108093)


--- trunk/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.cpp	2012-02-17 18:19:18 UTC (rev 108092)
+++ trunk/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.cpp	2012-02-17 18:27:32 UTC (rev 108093)
@@ -115,11 +115,6 @@
     return false;
 }
 
-void CCLayerImpl::draw(LayerRendererChromium*)
-{
-    ASSERT_NOT_REACHED();
-}
-
 PassOwnPtr<CCSharedQuadState> CCLayerImpl::createSharedQuadState() const
 {
     IntRect layerClipRect;

Modified: trunk/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.h (108092 => 108093)


--- trunk/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.h	2012-02-17 18:19:18 UTC (rev 108092)
+++ trunk/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.h	2012-02-17 18:27:32 UTC (rev 108093)
@@ -75,9 +75,9 @@
     PassOwnPtr<CCSharedQuadState> createSharedQuadState() const;
     virtual void willDraw(LayerRendererChromium*) { }
     virtual void appendQuads(CCQuadList&, const CCSharedQuadState*);
+    virtual void didDraw() { }
     void appendDebugBorderQuad(CCQuadList&, const CCSharedQuadState*) const;
 
-    virtual void draw(LayerRendererChromium*);
     void unreserveContentsTexture();
     virtual void bindContentsTexture(LayerRendererChromium*);
 

Modified: trunk/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostImpl.cpp (108092 => 108093)


--- trunk/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostImpl.cpp	2012-02-17 18:19:18 UTC (rev 108092)
+++ trunk/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostImpl.cpp	2012-02-17 18:27:32 UTC (rev 108093)
@@ -31,6 +31,7 @@
 #include "LayerRendererChromium.h"
 #include "TraceEvent.h"
 #include "cc/CCDamageTracker.h"
+#include "cc/CCLayerIterator.h"
 #include "cc/CCLayerTreeHost.h"
 #include "cc/CCLayerTreeHostCommon.h"
 #include "cc/CCPageScaleAnimation.h"
@@ -187,9 +188,8 @@
     return surfaceDamageRect;
 }
 
-void CCLayerTreeHostImpl::calculateRenderPasses(CCRenderPassList& passes)
+void CCLayerTreeHostImpl::calculateRenderPasses(CCRenderPassList& passes, CCLayerList& renderSurfaceLayerList)
 {
-    CCLayerList renderSurfaceLayerList;
     renderSurfaceLayerList.append(rootLayer());
 
     if (!rootLayer()->renderSurface())
@@ -263,13 +263,23 @@
         return;
 
     CCRenderPassList passes;
-    calculateRenderPasses(passes);
+    CCLayerList renderSurfaceLayerList;
+    calculateRenderPasses(passes, renderSurfaceLayerList);
 
     optimizeRenderPasses(passes);
 
     m_layerRenderer->beginDrawingFrame();
     for (size_t i = 0; i < passes.size(); ++i)
         m_layerRenderer->drawRenderPass(passes[i].get());
+
+    typedef CCLayerIterator<CCLayerImpl, CCRenderSurface, CCLayerIteratorActions::BackToFront> CCLayerIteratorType;
+
+    CCLayerIteratorType end = CCLayerIteratorType::end(&renderSurfaceLayerList);
+    for (CCLayerIteratorType it = CCLayerIteratorType::begin(&renderSurfaceLayerList); it != end; ++it) {
+        if (it.representsItself())
+            it->didDraw();
+    }
+
     m_layerRenderer->finishDrawingFrame();
 
     ++m_frameNumber;

Modified: trunk/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostImpl.h (108092 => 108093)


--- trunk/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostImpl.h	2012-02-17 18:19:18 UTC (rev 108092)
+++ trunk/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostImpl.h	2012-02-17 18:27:32 UTC (rev 108093)
@@ -133,7 +133,7 @@
     void adjustScrollsForPageScaleChange(float);
     void updateMaxScrollPosition();
     void trackDamageForAllSurfaces(CCLayerImpl* rootDrawLayer, const CCLayerList& renderSurfaceLayerList);
-    void calculateRenderPasses(CCRenderPassList&);
+    void calculateRenderPasses(CCRenderPassList&, CCLayerList& renderSurfaceLayerList);
     void optimizeRenderPasses(CCRenderPassList&);
     IntSize contentSize() const;
 

Modified: trunk/Source/WebCore/platform/graphics/chromium/cc/CCVideoDrawQuad.cpp (108092 => 108093)


--- trunk/Source/WebCore/platform/graphics/chromium/cc/CCVideoDrawQuad.cpp	2012-02-17 18:19:18 UTC (rev 108092)
+++ trunk/Source/WebCore/platform/graphics/chromium/cc/CCVideoDrawQuad.cpp	2012-02-17 18:27:32 UTC (rev 108093)
@@ -29,16 +29,17 @@
 
 namespace WebCore {
 
-PassOwnPtr<CCVideoDrawQuad> CCVideoDrawQuad::create(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect, CCLayerImpl* layer)
+PassOwnPtr<CCVideoDrawQuad> CCVideoDrawQuad::create(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect, CCVideoLayerImpl::Texture* textures, VideoFrameChromium* frame, GC3Denum format)
 {
-    return adoptPtr(new CCVideoDrawQuad(sharedQuadState, quadRect, layer));
+    return adoptPtr(new CCVideoDrawQuad(sharedQuadState, quadRect, textures, frame, format));
 }
 
-CCVideoDrawQuad::CCVideoDrawQuad(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect, CCLayerImpl* layer)
+CCVideoDrawQuad::CCVideoDrawQuad(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect, CCVideoLayerImpl::Texture* textures, VideoFrameChromium* frame, GC3Denum format)
     : CCDrawQuad(sharedQuadState, CCDrawQuad::VideoContent, quadRect)
-    , m_layer(layer)
+    , m_textures(textures)
+    , m_frame(frame)
+    , m_format(format)
 {
-    ASSERT(m_layer);
 }
 
 }

Modified: trunk/Source/WebCore/platform/graphics/chromium/cc/CCVideoDrawQuad.h (108092 => 108093)


--- trunk/Source/WebCore/platform/graphics/chromium/cc/CCVideoDrawQuad.h	2012-02-17 18:19:18 UTC (rev 108092)
+++ trunk/Source/WebCore/platform/graphics/chromium/cc/CCVideoDrawQuad.h	2012-02-17 18:27:32 UTC (rev 108093)
@@ -26,23 +26,28 @@
 #ifndef CCVideoDrawQuad_h
 #define CCVideoDrawQuad_h
 
+#include "GraphicsTypes3D.h"
 #include "cc/CCDrawQuad.h"
+#include "cc/CCVideoLayerImpl.h"
 #include <wtf/PassOwnPtr.h>
 
 namespace WebCore {
 
-class CCLayerImpl;
 class CCVideoDrawQuad : public CCDrawQuad {
     WTF_MAKE_NONCOPYABLE(CCVideoDrawQuad);
 public:
-    static PassOwnPtr<CCVideoDrawQuad> create(const CCSharedQuadState*, const IntRect&, CCLayerImpl*);
+    static PassOwnPtr<CCVideoDrawQuad> create(const CCSharedQuadState*, const IntRect&, CCVideoLayerImpl::Texture* textures, VideoFrameChromium*, GC3Denum format);
 
-    CCLayerImpl* layer() const { return m_layer; }
+    CCVideoLayerImpl::Texture* textures() const { return m_textures; }
+    VideoFrameChromium* frame() const { return m_frame; }
+    GC3Denum format() const { return m_format; }
 
 private:
-    CCVideoDrawQuad(const CCSharedQuadState*, const IntRect&, CCLayerImpl*);
+    CCVideoDrawQuad(const CCSharedQuadState*, const IntRect&, CCVideoLayerImpl::Texture* textures, VideoFrameChromium*, GC3Denum format);
 
-    CCLayerImpl* m_layer;
+    CCVideoLayerImpl::Texture* m_textures;
+    VideoFrameChromium* m_frame;
+    GC3Denum m_format;
 };
 
 }

Modified: trunk/Source/WebCore/platform/graphics/chromium/cc/CCVideoLayerImpl.cpp (108092 => 108093)


--- trunk/Source/WebCore/platform/graphics/chromium/cc/CCVideoLayerImpl.cpp	2012-02-17 18:19:18 UTC (rev 108092)
+++ trunk/Source/WebCore/platform/graphics/chromium/cc/CCVideoLayerImpl.cpp	2012-02-17 18:27:32 UTC (rev 108093)
@@ -112,7 +112,7 @@
     return GraphicsContext3D::INVALID_VALUE;
 }
 
-void CCVideoLayerImpl::draw(LayerRendererChromium* layerRenderer)
+void CCVideoLayerImpl::willDraw(LayerRendererChromium* layerRenderer)
 {
     ASSERT(CCProxy::isImplThread());
 
@@ -121,92 +121,46 @@
     if (!m_provider)
         return;
 
-    VideoFrameChromium* frame = m_provider->getCurrentFrame();
-    if (!frame)
-        return;
-    GC3Denum format = convertVFCFormatToGC3DFormat(frame->format());
+    m_frame = m_provider->getCurrentFrame();
 
-    if (format == GraphicsContext3D::INVALID_VALUE) {
-        m_provider->putCurrentFrame(frame);
+    if (!m_frame)
         return;
-    }
 
-    if (!copyFrameToTextures(frame, format, layerRenderer)) {
-        m_provider->putCurrentFrame(frame);
+    m_format = convertVFCFormatToGC3DFormat(m_frame->format());
+
+    if (m_format == GraphicsContext3D::INVALID_VALUE) {
+        m_provider->putCurrentFrame(m_frame);
+        m_frame = 0;
         return;
     }
 
-    switch (format) {
-    case GraphicsContext3D::LUMINANCE:
-        drawYUV(layerRenderer);
-        break;
-    case GraphicsContext3D::RGBA:
-        drawRGBA(layerRenderer);
-        break;
-    case GraphicsContext3D::TEXTURE_2D:
-        drawNativeTexture(layerRenderer);
-        break;
-    default:
-        CRASH(); // Someone updated convertVFCFormatToGC3DFormat above but update this!
+    if (!reserveTextures(m_frame, m_format, layerRenderer)) {
+        m_provider->putCurrentFrame(m_frame);
+        m_frame = 0;
     }
-
-    for (unsigned plane = 0; plane < frame->planes(); ++plane)
-        m_textures[plane].m_texture->unreserve();
-    m_provider->putCurrentFrame(frame);
 }
 
 void CCVideoLayerImpl::appendQuads(CCQuadList& quadList, const CCSharedQuadState* sharedQuadState)
 {
     IntRect quadRect(IntPoint(), bounds());
-    quadList.append(CCVideoDrawQuad::create(sharedQuadState, quadRect, this));
+    quadList.append(CCVideoDrawQuad::create(sharedQuadState, quadRect, m_textures, m_frame, m_format));
 }
 
-bool CCVideoLayerImpl::copyFrameToTextures(const VideoFrameChromium* frame, GC3Denum format, LayerRendererChromium* layerRenderer)
+void CCVideoLayerImpl::didDraw()
 {
-    if (frame->format() == VideoFrameChromium::NativeTexture) {
-        m_nativeTextureId = frame->textureId();
-        m_nativeTextureSize = IntSize(frame->width(), frame->height());
-        return true;
-    }
+    ASSERT(CCProxy::isImplThread());
 
-    if (!reserveTextures(frame, format, layerRenderer))
-        return false;
+    MutexLocker locker(m_providerMutex);
 
-    for (unsigned plane = 0; plane < frame->planes(); ++plane) {
-        ASSERT(frame->requiredTextureSize(plane) == m_textures[plane].m_texture->size());
-        copyPlaneToTexture(layerRenderer, frame->data(plane), plane);
-    }
-    for (unsigned plane = frame->planes(); plane < MaxPlanes; ++plane) {
-        Texture& texture = m_textures[plane];
-        texture.m_texture.clear();
-        texture.m_visibleSize = IntSize();
-    }
-    m_planes = frame->planes();
-    return true;
-}
+    if (!m_provider || !m_frame)
+        return;
 
-void CCVideoLayerImpl::copyPlaneToTexture(LayerRendererChromium* layerRenderer, const void* plane, int index)
-{
-    Texture& texture = m_textures[index];
-    GraphicsContext3D* context = layerRenderer->context();
-    TextureAllocator* allocator = layerRenderer->renderSurfaceTextureAllocator();
-    texture.m_texture->bindTexture(context, allocator);
-    GC3Denum format = texture.m_texture->format();
-    IntSize dimensions = texture.m_texture->size();
-
-    void* mem = static_cast<Extensions3DChromium*>(context->getExtensions())->mapTexSubImage2DCHROMIUM(GraphicsContext3D::TEXTURE_2D, 0, 0, 0, dimensions.width(), dimensions.height(), format, GraphicsContext3D::UNSIGNED_BYTE, Extensions3DChromium::WRITE_ONLY);
-    if (mem) {
-        memcpy(mem, plane, dimensions.width() * dimensions.height());
-        GLC(context, static_cast<Extensions3DChromium*>(context->getExtensions())->unmapTexSubImage2DCHROMIUM(mem));
-    } else {
-        // If mapTexSubImage2DCHROMIUM fails, then do the slower texSubImage2D
-        // upload. This does twice the copies as mapTexSubImage2DCHROMIUM, one
-        // in the command buffer and another to the texture.
-        GLC(context, context->texSubImage2D(GraphicsContext3D::TEXTURE_2D, 0, 0, 0, dimensions.width(), dimensions.height(), format, GraphicsContext3D::UNSIGNED_BYTE, plane));
-    }
+    for (unsigned plane = 0; plane < m_frame->planes(); ++plane)
+        m_textures[plane].m_texture->unreserve();
+    m_provider->putCurrentFrame(m_frame);
 }
 
-static IntSize computeVisibleSize(const VideoFrameChromium* frame, unsigned plane)
+IntSize CCVideoLayerImpl::computeVisibleSize(const VideoFrameChromium* frame, unsigned plane)
 {
     int visibleWidth = frame->width(plane);
     int visibleHeight = frame->height(plane);
@@ -259,81 +213,6 @@
     return true;
 }
 
-void CCVideoLayerImpl::drawYUV(LayerRendererChromium* layerRenderer) const
-{
-    const YUVProgram* program = layerRenderer->videoLayerYUVProgram();
-    ASSERT(program && program->initialized());
-
-    GraphicsContext3D* context = layerRenderer->context();
-    const Texture& yTexture = m_textures[VideoFrameChromium::yPlane];
-    const Texture& uTexture = m_textures[VideoFrameChromium::uPlane];
-    const Texture& vTexture = m_textures[VideoFrameChromium::vPlane];
-
-    GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE1));
-    GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, yTexture.m_texture->textureId()));
-    GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE2));
-    GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, uTexture.m_texture->textureId()));
-    GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE3));
-    GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, vTexture.m_texture->textureId()));
-
-    GLC(context, context->useProgram(program->program()));
-
-    float yWidthScaleFactor = static_cast<float>(yTexture.m_visibleSize.width()) / yTexture.m_texture->size().width();
-    // Arbitrarily take the u sizes because u and v dimensions are identical.
-    float uvWidthScaleFactor = static_cast<float>(uTexture.m_visibleSize.width()) / uTexture.m_texture->size().width();
-    GLC(context, context->uniform1f(program->vertexShader().yWidthScaleFactorLocation(), yWidthScaleFactor));
-    GLC(context, context->uniform1f(program->vertexShader().uvWidthScaleFactorLocation(), uvWidthScaleFactor));
-
-    GLC(context, context->uniform1i(program->fragmentShader().yTextureLocation(), 1));
-    GLC(context, context->uniform1i(program->fragmentShader().uTextureLocation(), 2));
-    GLC(context, context->uniform1i(program->fragmentShader().vTextureLocation(), 3));
-
-    GLC(context, context->uniformMatrix3fv(program->fragmentShader().ccMatrixLocation(), 0, const_cast<float*>(yuv2RGB), 1));
-    GLC(context, context->uniform3fv(program->fragmentShader().yuvAdjLocation(), const_cast<float*>(yuvAdjust), 1));
-
-    layerRenderer->drawTexturedQuad(drawTransform(), bounds().width(), bounds().height(), drawOpacity(), FloatQuad(),
-                                    program->vertexShader().matrixLocation(),
-                                    program->fragmentShader().alphaLocation(),
-                                    -1);
-
-    // Reset active texture back to texture 0.
-    GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE0));
-}
-
-template<class Program>
-void CCVideoLayerImpl::drawCommon(LayerRendererChromium* layerRenderer, Program* program, float widthScaleFactor, Platform3DObject textureId) const
-{
-    ASSERT(program && program->initialized());
-
-    GraphicsContext3D* context = layerRenderer->context();
-
-    GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE0));
-    GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, textureId));
-
-    GLC(context, context->useProgram(program->program()));
-    GLC(context, context->uniform4f(program->vertexShader().texTransformLocation(), 0, 0, widthScaleFactor, 1));
-    GLC(context, context->uniform1i(program->fragmentShader().samplerLocation(), 0));
-
-    layerRenderer->drawTexturedQuad(drawTransform(), bounds().width(), bounds().height(), drawOpacity(), layerRenderer->sharedGeometryQuad(),
-                                    program->vertexShader().matrixLocation(),
-                                    program->fragmentShader().alphaLocation(),
-                                    -1);
-}
-
-void CCVideoLayerImpl::drawRGBA(LayerRendererChromium* layerRenderer) const
-{
-    const RGBAProgram* program = layerRenderer->videoLayerRGBAProgram();
-    const Texture& texture = m_textures[VideoFrameChromium::rgbPlane];
-    float widthScaleFactor = static_cast<float>(texture.m_visibleSize.width()) / texture.m_texture->size().width();
-    drawCommon(layerRenderer, program, widthScaleFactor, texture.m_texture->textureId());
-}
-
-void CCVideoLayerImpl::drawNativeTexture(LayerRendererChromium* layerRenderer) const
-{
-    const NativeTextureProgram* program = layerRenderer->videoLayerNativeTextureProgram();
-    drawCommon(layerRenderer, program, 1, m_nativeTextureId);
-}
-
 void CCVideoLayerImpl::dumpLayerProperties(TextStream& ts, int indent) const
 {
     writeIndent(ts, indent);

Modified: trunk/Source/WebCore/platform/graphics/chromium/cc/CCVideoLayerImpl.h (108092 => 108093)


--- trunk/Source/WebCore/platform/graphics/chromium/cc/CCVideoLayerImpl.h	2012-02-17 18:19:18 UTC (rev 108092)
+++ trunk/Source/WebCore/platform/graphics/chromium/cc/CCVideoLayerImpl.h	2012-02-17 18:27:32 UTC (rev 108093)
@@ -46,48 +46,46 @@
     }
     virtual ~CCVideoLayerImpl();
 
+    virtual void willDraw(LayerRendererChromium*);
     virtual void appendQuads(CCQuadList&, const CCSharedQuadState*);
+    virtual void didDraw();
 
     typedef ProgramBinding<VertexShaderPosTexTransform, FragmentShaderRGBATexFlipAlpha> RGBAProgram;
     typedef ProgramBinding<VertexShaderPosTexYUVStretch, FragmentShaderYUVVideo> YUVProgram;
     typedef ProgramBinding<VertexShaderPosTexTransform, FragmentShaderRGBATexFlipAlpha> NativeTextureProgram;
 
-    virtual void draw(LayerRendererChromium*);
-
     virtual void dumpLayerProperties(TextStream&, int indent) const;
 
+    Mutex& providerMutex() { return m_providerMutex; }
+    VideoFrameProvider* provider() const { return m_provider; }
+
     // VideoFrameProvider::Client implementation (callable on any thread).
     virtual void stopUsingProvider();
 
+    static const float yuv2RGB[9];
+    static const float yuvAdjust[3];
+
+    struct Texture {
+        OwnPtr<ManagedTexture> m_texture;
+        IntSize m_visibleSize;
+    };
+    enum { MaxPlanes = 3 };
+
 private:
     explicit CCVideoLayerImpl(int, VideoFrameProvider*);
 
+    static IntSize computeVisibleSize(const VideoFrameChromium*, unsigned plane);
     virtual const char* layerTypeAsString() const { return "VideoLayer"; }
 
-    bool copyFrameToTextures(const VideoFrameChromium*, GC3Denum format, LayerRendererChromium*);
-    void copyPlaneToTexture(LayerRendererChromium*, const void* plane, int index);
     bool reserveTextures(const VideoFrameChromium*, GC3Denum format, LayerRendererChromium*);
-    void drawYUV(LayerRendererChromium*) const;
-    void drawRGBA(LayerRendererChromium*) const;
-    void drawNativeTexture(LayerRendererChromium*) const;
-    template<class Program> void drawCommon(LayerRendererChromium*, Program*, float widthScaleFactor, Platform3DObject textureId) const;
 
     Mutex m_providerMutex; // Guards m_provider below.
     VideoFrameProvider* m_provider;
 
-    static const float yuv2RGB[9];
-    static const float yuvAdjust[3];
-
-    struct Texture {
-        OwnPtr<ManagedTexture> m_texture;
-        IntSize m_visibleSize;
-    };
-    enum { MaxPlanes = 3 };
     Texture m_textures[MaxPlanes];
-    int m_planes;
 
-    Platform3DObject m_nativeTextureId;
-    IntSize m_nativeTextureSize;
+    VideoFrameChromium* m_frame;
+    GC3Denum m_format;
 };
 
 }

Modified: trunk/Source/WebKit/chromium/ChangeLog (108092 => 108093)


--- trunk/Source/WebKit/chromium/ChangeLog	2012-02-17 18:19:18 UTC (rev 108092)
+++ trunk/Source/WebKit/chromium/ChangeLog	2012-02-17 18:27:32 UTC (rev 108093)
@@ -1,3 +1,23 @@
+2012-02-17  Tim Dresser  <[email protected]>
+
+        [chromium] Refactor video drawing to be more data driven
+        https://bugs.webkit.org/show_bug.cgi?id=76720
+
+        Reviewed by James Robinson.
+
+        CCLayerTreeHostImplTest.didDrawCalledOnAllLayers ensures that
+        CCLayerImpl::didDraw() is called on all layers, including layers
+        on different render surfaces.
+
+        * tests/CCLayerTreeHostImplTest.cpp:
+        (DidDrawCheckLayer):
+        (WebKit::DidDrawCheckLayer::create):
+        (WebKit::DidDrawCheckLayer::didDraw):
+        (WebKit::DidDrawCheckLayer::didDrawCalled):
+        (WebKit::DidDrawCheckLayer::DidDrawCheckLayer):
+        (WebKit):
+        (WebKit::TEST_F):
+
 2012-02-17  Ilya Tikhonovsky  <[email protected]>
 
         Unreviewed, rolling out r108071.

Modified: trunk/Source/WebKit/chromium/tests/CCLayerTreeHostImplTest.cpp (108092 => 108093)


--- trunk/Source/WebKit/chromium/tests/CCLayerTreeHostImplTest.cpp	2012-02-17 18:19:18 UTC (rev 108092)
+++ trunk/Source/WebKit/chromium/tests/CCLayerTreeHostImplTest.cpp	2012-02-17 18:27:32 UTC (rev 108093)
@@ -276,6 +276,63 @@
     }
 }
 
+class DidDrawCheckLayer : public CCLayerImpl {
+public:
+    static PassRefPtr<DidDrawCheckLayer> create(int id) { return adoptRef(new DidDrawCheckLayer(id)); }
+
+    virtual void didDraw()
+    {
+        m_didDrawCalled = true;
+    }
+
+    bool didDrawCalled() const { return m_didDrawCalled; }
+
+private:
+    explicit DidDrawCheckLayer(int id)
+        : CCLayerImpl(id)
+        , m_didDrawCalled(false)
+    {
+        setAnchorPoint(FloatPoint(0, 0));
+        setBounds(IntSize(10, 10));
+        setDrawsContent(true);
+    }
+
+    bool m_didDrawCalled;
+};
+
+TEST_F(CCLayerTreeHostImplTest, didDrawCalledOnAllLayers)
+{
+    GraphicsContext3D::Attributes attrs;
+    RefPtr<GraphicsContext3D> context = GraphicsContext3DPrivate::createGraphicsContextFromWebContext(adoptPtr(new FakeWebGraphicsContext3D()), attrs, 0, GraphicsContext3D::RenderDirectlyToHostWindow, GraphicsContext3DPrivate::ForUseOnThisThread);
+    m_hostImpl->initializeLayerRenderer(context);
+    m_hostImpl->setViewportSize(IntSize(10, 10));
+
+    RefPtr<DidDrawCheckLayer> root = DidDrawCheckLayer::create(0);
+    m_hostImpl->setRootLayer(root);
+
+    RefPtr<DidDrawCheckLayer> layer1 = DidDrawCheckLayer::create(1);
+    root->addChild(layer1);
+
+    RefPtr<DidDrawCheckLayer> layer2 = DidDrawCheckLayer::create(2);
+    layer1->addChild(layer2);
+
+    layer1->setOpacity(0.3);
+    layer1->setPreserves3D(false);
+
+    EXPECT_FALSE(root->didDrawCalled());
+    EXPECT_FALSE(layer1->didDrawCalled());
+    EXPECT_FALSE(layer2->didDrawCalled());
+
+    m_hostImpl->drawLayers();
+
+    EXPECT_TRUE(root->didDrawCalled());
+    EXPECT_TRUE(layer1->didDrawCalled());
+    EXPECT_TRUE(layer2->didDrawCalled());
+
+    EXPECT_NE(root->renderSurface(), layer1->renderSurface());
+    EXPECT_TRUE(!!layer1->renderSurface());
+}
+
 class BlendStateTrackerContext: public FakeWebGraphicsContext3D {
 public:
     BlendStateTrackerContext() : m_blend(false) { }
@@ -507,7 +564,6 @@
 class FakeDrawableCCLayerImpl: public CCLayerImpl {
 public:
     explicit FakeDrawableCCLayerImpl(int id) : CCLayerImpl(id) { }
-    virtual void draw(LayerRendererChromium* renderer) { }
 };
 
 // Only reshape when we know we are going to draw. Otherwise, the reshape
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to