[SCM] WebKit Debian packaging branch, debian/experimental, updated. upstream/1.3.3-9427-gc2be6fc

eric.carlson at apple.com eric.carlson at apple.com
Wed Dec 22 11:47:52 UTC 2010


The following commit has been merged in the debian/experimental branch:
commit 2e9a595fe029fa45dd780ec2d705d94ad6562616
Author: eric.carlson at apple.com <eric.carlson at apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Fri Aug 6 23:35:55 2010 +0000

    2010-08-06  Eric Carlson  <eric.carlson at apple.com>
    
            Reviewed by Simon Fraser.
    
            HTML5 "video" tag with poster frame defined "flashes" right before movie displays
            https://bugs.webkit.org/show_bug.cgi?id=37591
            <rdar://problem/5650561>
    
            If a video element has a poster frame, display it until the playback is requested or the movie's
            time is changed.
    
            Test: compositing/video/video-poster.html
    
            * html/HTMLMediaElement.cpp:
            (WebCore::HTMLMediaElement::HTMLMediaElement): Initialize m_displayMode.
            (WebCore::HTMLMediaElement::prepareForLoad): Set m_displayMode to Unknown.
            (WebCore::HTMLMediaElement::loadResource): Call updateDisplayState to let it set configure
            the poster, if necessary.
            (WebCore::HTMLMediaElement::noneSupported): updatePosterImage -> updateDisplayState.
            (WebCore::HTMLMediaElement::setNetworkState): Ditto.
            (WebCore::HTMLMediaElement::setReadyState): Ditto.
            (WebCore::HTMLMediaElement::finishSeek): Set display mode to Video so a video frame will be
            displayed if a poster is currently visible.
            (WebCore::HTMLMediaElement::mediaPlayerRepaint): updatePosterImage -> updateDisplayState.
            (WebCore::HTMLMediaElement::updatePlayState): Set display mode to Video.
            * html/HTMLMediaElement.h:
            (WebCore::HTMLMediaElement::displayMode): New.
            (WebCore::HTMLMediaElement::setDisplayMode): Ditto.
            (WebCore::HTMLMediaElement::updateDisplayState): Ditto.
    
            * html/HTMLVideoElement.cpp:
            (WebCore::HTMLVideoElement::HTMLVideoElement): Remove m_shouldDisplayPosterImage.
            (WebCore::HTMLVideoElement::attach): Call shouldDisplayPosterImage instead of checking
            m_shouldDisplayPosterImage directly.
            (WebCore::HTMLVideoElement::detach): Ditto.
            (WebCore::HTMLVideoElement::parseMappedAttribute): Set m_displayMode to Unknown before calling
            updateDisplayState so shouldDisplayPosterImage() will return the correct result. Remove the
            PLUGIN_PROXY_FOR_VIDEO code, it is now in updateDisplayState.
            (WebCore::HTMLVideoElement::setDisplayMode): Renamed from updatePosterImage and rework logic
            so we tell the media engine it is OK to display video frames when there is no poster, or
            once the media engine has something to display and the movie has started or seeked.
            (WebCore::HTMLVideoElement::updateDisplayState): New, manage display mode based on poster
            attribute.
            * html/HTMLVideoElement.h:
            (WebCore::HTMLVideoElement::shouldDisplayPosterImage):
    
            * platform/graphics/MediaPlayer.cpp:
            (WebCore::MediaPlayer::prepareForRendering): New, call media engine's prepareForRendering.
            * platform/graphics/MediaPlayer.h:
            * platform/graphics/MediaPlayerPrivate.h:
            (WebCore::MediaPlayerPrivateInterface::prepareForRendering):
    
            * platform/graphics/mac/MediaPlayerPrivateQTKit.h:
            * platform/graphics/mac/MediaPlayerPrivateQTKit.mm:
            (WebCore::MediaPlayerPrivate::MediaPlayerPrivate): Initialize m_isAllowedToRender.
            (WebCore::MediaPlayerPrivate::setUpVideoRendering):
            (WebCore::MediaPlayerPrivate::isReadyForVideoSetup): Renamed from isReadyForRendering.
            (WebCore::MediaPlayerPrivate::prepareForRendering): New, set m_isAllowedToRender and
            inform the client that render tree should be updated so we correctly switch from showing
            the poster, which often doens't use a layer, to showing video frames, which do.
            (WebCore::MediaPlayerPrivate::updateStates): Don't call setUpVideoRendering until
            isReadyForVideoSetup() returns true.
            (WebCore::MediaPlayerPrivate::supportsAcceleratedRendering): isReadyForRendering -> isReadyForVideoSetup
    
            * rendering/RenderLayerBacking.cpp:
            (WebCore::RenderLayerBacking::containsPaintedContent): Only consider video when displaying
            video frames so a poster won't force compositing mode.
    
            * rendering/RenderLayerCompositor.cpp:
            (WebCore::RenderLayerCompositor::requiresCompositingForVideo): Ditto.
    
            * rendering/RenderVideo.cpp:
            (WebCore::RenderVideo::shouldDisplayVideo): New, return true when not displaying a poster.
            * rendering/RenderVideo.h:
    
    2010-08-06  Eric Carlson  <eric.carlson at apple.com>
    
            Reviewed by Simon Fraser.
    
            HTML5 "video" tag with poster frame defined "flashes" right before movie displays
            https://bugs.webkit.org/show_bug.cgi?id=37591
            <rdar://problem/5650561>
    
            If a video element has a poster frame, display it until the playback is requested or the movie's
            time is changed. Test this by ensuring that an element with a poster doesn't have layers while
            and element with one does.
    
            * compositing/video/video-poster-expected.txt: Added.
            * compositing/video/video-poster.html: Added.
    
    
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@64884 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index 943e9c8..bd433be 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,3 +1,18 @@
+2010-08-06  Eric Carlson  <eric.carlson at apple.com>
+
+        Reviewed by Simon Fraser.
+
+        HTML5 "video" tag with poster frame defined "flashes" right before movie displays
+        https://bugs.webkit.org/show_bug.cgi?id=37591
+        <rdar://problem/5650561>
+
+        If a video element has a poster frame, display it until the playback is requested or the movie's
+        time is changed. Test this by ensuring that an element with a poster doesn't have layers while
+        and element with one does.
+
+        * compositing/video/video-poster-expected.txt: Added.
+        * compositing/video/video-poster.html: Added.
+
 2010-08-06  Dimitri Glazkov  <dglazkov at chromium.org>
 
         [Chromium/DRT] Update expectation overrides for Windows.
diff --git a/LayoutTests/compositing/video/video-poster-expected.txt b/LayoutTests/compositing/video/video-poster-expected.txt
new file mode 100644
index 0000000..cf29f9e
--- /dev/null
+++ b/LayoutTests/compositing/video/video-poster-expected.txt
@@ -0,0 +1,13 @@
+A <video> should not have a layer until playback begins.
+This test can not be run manually, it requires layoutTestController.layerTreeAsText.
+
+No src, no poster 
+  PASS: wants layers = false, has layers = false
+
+Displaying poster 
+  PASS: wants layers = false, has layers = false
+
+Playing movie 
+  PASS: wants layers = true, has layers = true
+
+
diff --git a/LayoutTests/compositing/video/video-poster.html b/LayoutTests/compositing/video/video-poster.html
new file mode 100644
index 0000000..6f62010
--- /dev/null
+++ b/LayoutTests/compositing/video/video-poster.html
@@ -0,0 +1,66 @@
+<!DOCTYPE>
+<html>
+    <head>
+        <title>Video with poster</title>
+        <script>
+
+            var count = 0;
+            function log(str)
+            {
+                document.getElementById('result').innerHTML += str + "<br>";
+            }
+
+            function hasLayers()
+            {
+                if (window.layoutTestController)
+                    return layoutTestController.layerTreeAsText() != "";
+                return false;
+            }
+
+            function checkLayers(prefix, wantsLayers)
+            {
+                var layers = hasLayers();
+                log(prefix + " <br>&nbsp;&nbsp;" + (wantsLayers == layers ? "PASS" : "FAIL") + ": wants layers = " + wantsLayers + ", has layers = " + layers);
+                log("");
+            }
+
+            function layerTest()
+            {
+                var video = document.getElementsByTagName('video')[0];
+
+                switch (event.type)
+                {
+                    case "load":
+                        checkLayers("No src, no poster", false);
+                        video.src = "../resources/video.mp4"
+                        video.poster = "../resources/apple.jpg";
+                        break;
+                    case "canplaythrough":
+                        checkLayers("Displaying poster", false);
+                        video.play();
+                        break;
+                    case "playing":
+                        checkLayers("Playing movie", true);
+                        if (window.layoutTestController)
+                            layoutTestController.notifyDone();
+                        break;
+                }
+            }
+
+            if (window.layoutTestController) {
+                layoutTestController.dumpAsText();
+                layoutTestController.waitUntilDone();
+            }
+            window.addEventListener('load', layerTest, false);
+        </script>
+    </head>
+    <body>
+    
+        <video oncanplaythrough="layerTest()" onplaying="layerTest()"></video>
+        
+        <p>A &lt;video&gt; should not have a layer until playback begins.<br>
+        This test can not be run manually, it requires layoutTestController.layerTreeAsText.</p>
+        <p id="result"></p>
+    
+    </body>
+</html>
diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index 2b756d6..68e2271 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -1,3 +1,78 @@
+2010-08-06  Eric Carlson  <eric.carlson at apple.com>
+
+        Reviewed by Simon Fraser.
+
+        HTML5 "video" tag with poster frame defined "flashes" right before movie displays
+        https://bugs.webkit.org/show_bug.cgi?id=37591
+        <rdar://problem/5650561>
+
+        If a video element has a poster frame, display it until the playback is requested or the movie's
+        time is changed.
+
+        Test: compositing/video/video-poster.html
+
+        * html/HTMLMediaElement.cpp:
+        (WebCore::HTMLMediaElement::HTMLMediaElement): Initialize m_displayMode.
+        (WebCore::HTMLMediaElement::prepareForLoad): Set m_displayMode to Unknown.
+        (WebCore::HTMLMediaElement::loadResource): Call updateDisplayState to let it set configure
+        the poster, if necessary.
+        (WebCore::HTMLMediaElement::noneSupported): updatePosterImage -> updateDisplayState.
+        (WebCore::HTMLMediaElement::setNetworkState): Ditto.
+        (WebCore::HTMLMediaElement::setReadyState): Ditto.
+        (WebCore::HTMLMediaElement::finishSeek): Set display mode to Video so a video frame will be
+        displayed if a poster is currently visible.
+        (WebCore::HTMLMediaElement::mediaPlayerRepaint): updatePosterImage -> updateDisplayState.
+        (WebCore::HTMLMediaElement::updatePlayState): Set display mode to Video.
+        * html/HTMLMediaElement.h:
+        (WebCore::HTMLMediaElement::displayMode): New.
+        (WebCore::HTMLMediaElement::setDisplayMode): Ditto.
+        (WebCore::HTMLMediaElement::updateDisplayState): Ditto.
+
+        * html/HTMLVideoElement.cpp:
+        (WebCore::HTMLVideoElement::HTMLVideoElement): Remove m_shouldDisplayPosterImage.
+        (WebCore::HTMLVideoElement::attach): Call shouldDisplayPosterImage instead of checking
+        m_shouldDisplayPosterImage directly.
+        (WebCore::HTMLVideoElement::detach): Ditto.
+        (WebCore::HTMLVideoElement::parseMappedAttribute): Set m_displayMode to Unknown before calling 
+        updateDisplayState so shouldDisplayPosterImage() will return the correct result. Remove the
+        PLUGIN_PROXY_FOR_VIDEO code, it is now in updateDisplayState.
+        (WebCore::HTMLVideoElement::setDisplayMode): Renamed from updatePosterImage and rework logic
+        so we tell the media engine it is OK to display video frames when there is no poster, or 
+        once the media engine has something to display and the movie has started or seeked.
+        (WebCore::HTMLVideoElement::updateDisplayState): New, manage display mode based on poster 
+        attribute.
+        * html/HTMLVideoElement.h:
+        (WebCore::HTMLVideoElement::shouldDisplayPosterImage):
+
+        * platform/graphics/MediaPlayer.cpp:
+        (WebCore::MediaPlayer::prepareForRendering): New, call media engine's prepareForRendering.
+        * platform/graphics/MediaPlayer.h:
+        * platform/graphics/MediaPlayerPrivate.h:
+        (WebCore::MediaPlayerPrivateInterface::prepareForRendering):
+
+        * platform/graphics/mac/MediaPlayerPrivateQTKit.h:
+        * platform/graphics/mac/MediaPlayerPrivateQTKit.mm:
+        (WebCore::MediaPlayerPrivate::MediaPlayerPrivate): Initialize m_isAllowedToRender.
+        (WebCore::MediaPlayerPrivate::setUpVideoRendering):
+        (WebCore::MediaPlayerPrivate::isReadyForVideoSetup): Renamed from isReadyForRendering.
+        (WebCore::MediaPlayerPrivate::prepareForRendering): New, set m_isAllowedToRender and
+        inform the client that render tree should be updated so we correctly switch from showing
+        the poster, which often doens't use a layer, to showing video frames, which do.
+        (WebCore::MediaPlayerPrivate::updateStates): Don't call setUpVideoRendering until 
+        isReadyForVideoSetup() returns true.
+        (WebCore::MediaPlayerPrivate::supportsAcceleratedRendering): isReadyForRendering -> isReadyForVideoSetup
+
+        * rendering/RenderLayerBacking.cpp:
+        (WebCore::RenderLayerBacking::containsPaintedContent): Only consider video when displaying
+        video frames so a poster won't force compositing mode.
+
+        * rendering/RenderLayerCompositor.cpp:
+        (WebCore::RenderLayerCompositor::requiresCompositingForVideo): Ditto.
+
+        * rendering/RenderVideo.cpp:
+        (WebCore::RenderVideo::shouldDisplayVideo): New, return true when not displaying a poster.
+        * rendering/RenderVideo.h:
+
 2010-08-06  James Robinson  <jamesr at chromium.org>
 
         Reviewed by Simon Fraser.
diff --git a/WebCore/html/HTMLMediaElement.cpp b/WebCore/html/HTMLMediaElement.cpp
index 34f54aa..ecd6c03 100644
--- a/WebCore/html/HTMLMediaElement.cpp
+++ b/WebCore/html/HTMLMediaElement.cpp
@@ -108,8 +108,9 @@ HTMLMediaElement::HTMLMediaElement(const QualifiedName& tagName, Document* doc)
 #endif
     , m_restrictions(NoRestrictions)
     , m_preload(MediaPlayer::Auto)
-    , m_playing(false)
+    , m_displayMode(Unknown)
     , m_processingMediaPlayerCallback(0)
+    , m_playing(false)
     , m_isWaitingUntilMediaCanStart(false)
     , m_processingLoad(false)
     , m_delayingTheLoadEvent(false)
@@ -494,6 +495,7 @@ void HTMLMediaElement::prepareForLoad()
     m_sentStalledEvent = false;
     m_haveFiredLoadedData = false;
     m_completelyLoaded = false;
+    m_displayMode = Unknown;
 
     // 1 - Abort any already-running instance of the resource selection algorithm for this element.
     m_currentSourceNode = 0;
@@ -533,7 +535,6 @@ void HTMLMediaElement::prepareForLoad()
     m_playedTimeRanges = TimeRanges::create();
     m_lastSeekTime = 0;
     m_closedCaptionsVisible = false;
-
 }
 
 void HTMLMediaElement::loadInternal()
@@ -665,11 +666,9 @@ void HTMLMediaElement::loadResource(const KURL& initialURL, ContentType& content
 
     m_player->load(m_currentSrc, contentType);
 
-    if (isVideo() && m_player->canLoadPoster()) {
-        KURL posterURL = getNonEmptyURLAttribute(posterAttr);
-        if (!posterURL.isEmpty())
-            m_player->setPoster(posterURL);
-    }
+    // If there is no poster to display, allow the media engine to render video frames as soon as
+    // they are available.
+    updateDisplayState();
 
     if (renderer())
         renderer()->updateFromElement();
@@ -740,7 +739,7 @@ void HTMLMediaElement::noneSupported()
 
     // 9 -Abort these steps. Until the load() method is invoked, the element won't attempt to load another resource.
 
-    updatePosterImage();
+    updateDisplayState();
 
     if (renderer())
         renderer()->updateFromElement();
@@ -829,7 +828,7 @@ void HTMLMediaElement::setNetworkState(MediaPlayer::NetworkState state)
         else if (state == MediaPlayer::FormatError && m_loadState == LoadingFromSrcAttr)
             noneSupported();
 
-        updatePosterImage();
+        updateDisplayState();
         return;
     }
 
@@ -921,7 +920,7 @@ void HTMLMediaElement::setReadyState(MediaPlayer::ReadyState state)
         m_player->seek(0);
     }
 
-    bool shouldUpdatePosterImage = false;
+    bool shouldUpdateDisplayState = false;
 
     // 4.8.10.7 says loadeddata is sent only when the new state *is* HAVE_CURRENT_DATA: "If the
     // previous ready state was HAVE_METADATA and the new ready state is HAVE_CURRENT_DATA", 
@@ -930,7 +929,7 @@ void HTMLMediaElement::setReadyState(MediaPlayer::ReadyState state)
     // We go with the later because it seems useful to count on getting this event
     if (m_readyState >= HAVE_CURRENT_DATA && oldState < HAVE_CURRENT_DATA && !m_haveFiredLoadedData) {
         m_haveFiredLoadedData = true;
-        shouldUpdatePosterImage = true;
+        shouldUpdateDisplayState = true;
         scheduleEvent(eventNames().loadeddataEvent);
     }
 
@@ -939,7 +938,7 @@ void HTMLMediaElement::setReadyState(MediaPlayer::ReadyState state)
         scheduleEvent(eventNames().canplayEvent);
         if (isPotentiallyPlaying)
             scheduleEvent(eventNames().playingEvent);
-        shouldUpdatePosterImage = true;
+        shouldUpdateDisplayState = true;
     }
 
     if (m_readyState == HAVE_ENOUGH_DATA && oldState < HAVE_ENOUGH_DATA) {
@@ -957,11 +956,11 @@ void HTMLMediaElement::setReadyState(MediaPlayer::ReadyState state)
             scheduleEvent(eventNames().playingEvent);
         }
 
-        shouldUpdatePosterImage = true;
+        shouldUpdateDisplayState = true;
     }
 
-    if (shouldUpdatePosterImage)
-        updatePosterImage();
+    if (shouldUpdateDisplayState)
+        updateDisplayState();
 
     updatePlayState();
 }
@@ -1065,7 +1064,6 @@ void HTMLMediaElement::seek(float time, ExceptionCode& ec)
     m_player->seek(time);
 
     // 10-15 are handled, if necessary, when the engine signals a readystate change.
-
 }
 
 void HTMLMediaElement::finishSeek()
@@ -1075,6 +1073,8 @@ void HTMLMediaElement::finishSeek()
 
     // 4.8.10.10 Seeking step 13
     scheduleEvent(eventNames().seekedEvent);
+
+    setDisplayMode(Video);
 }
 
 HTMLMediaElement::ReadyState HTMLMediaElement::readyState() const
@@ -1613,10 +1613,9 @@ void HTMLMediaElement::mediaPlayerSawUnsupportedTracks(MediaPlayer*)
 void HTMLMediaElement::mediaPlayerRepaint(MediaPlayer*)
 {
     beginProcessingMediaPlayerCallback();
+    updateDisplayState();
     if (renderer())
         renderer()->repaint();
-
-    updatePosterImage();
     endProcessingMediaPlayerCallback();
 }
 
@@ -1777,6 +1776,8 @@ void HTMLMediaElement::updatePlayState()
     bool shouldBePlaying = potentiallyPlaying();
     bool playerPaused = m_player->paused();
     if (shouldBePlaying && playerPaused) {
+        setDisplayMode(Video);
+
         // Set rate before calling play in case the rate was set before the media engine wasn't setup.
         // The media engine should just stash the rate since it isn't already playing.
         m_player->setRate(m_playbackRate);
diff --git a/WebCore/html/HTMLMediaElement.h b/WebCore/html/HTMLMediaElement.h
index eede363..aeec188 100644
--- a/WebCore/html/HTMLMediaElement.h
+++ b/WebCore/html/HTMLMediaElement.h
@@ -178,6 +178,10 @@ protected:
     virtual void willMoveToNewOwnerDocument();
     virtual void didMoveToNewOwnerDocument();
 
+    enum DisplayMode { Unknown, None, Poster, Video };
+    DisplayMode displayMode() const { return m_displayMode; }
+    virtual void setDisplayMode(DisplayMode mode) { m_displayMode = mode; }
+
 private:
     virtual bool checkDTD(const Node* newChild);    
     virtual void attributeChanged(Attribute*, bool preserveDecls);
@@ -195,7 +199,8 @@ private:
     virtual void documentWillBecomeInactive();
     virtual void documentDidBecomeActive();
     virtual void mediaVolumeDidChange();
-    virtual void updatePosterImage() { }
+
+    virtual void updateDisplayState() { }
     
     void setReadyState(MediaPlayer::ReadyState);
     void setNetworkState(MediaPlayer::NetworkState);
@@ -254,7 +259,8 @@ private:
     void pauseInternal();
 
     void prepareForLoad();
-    
+    void allowVideoRendering();
+
     bool processingMediaPlayerCallback() const { return m_processingMediaPlayerCallback > 0; }
     void beginProcessingMediaPlayerCallback() { ++m_processingMediaPlayerCallback; }
     void endProcessingMediaPlayerCallback() { ASSERT(m_processingMediaPlayerCallback); --m_processingMediaPlayerCallback; }
@@ -326,14 +332,14 @@ private:
     
     MediaPlayer::Preload m_preload;
 
-    bool m_playing;
+    DisplayMode m_displayMode;
 
     // Counter incremented while processing a callback from the media player, so we can avoid
     // calling the media engine recursively.
     int m_processingMediaPlayerCallback;
 
-    bool m_isWaitingUntilMediaCanStart;
-
+    bool m_playing : 1;
+    bool m_isWaitingUntilMediaCanStart : 1;
     bool m_processingLoad : 1;
     bool m_delayingTheLoadEvent : 1;
     bool m_haveFiredLoadedData : 1;
diff --git a/WebCore/html/HTMLVideoElement.cpp b/WebCore/html/HTMLVideoElement.cpp
index bfdf241..fc74d32 100644
--- a/WebCore/html/HTMLVideoElement.cpp
+++ b/WebCore/html/HTMLVideoElement.cpp
@@ -47,7 +47,6 @@ using namespace HTMLNames;
 
 inline HTMLVideoElement::HTMLVideoElement(const QualifiedName& tagName, Document* document)
     : HTMLMediaElement(tagName, document)
-    , m_shouldDisplayPosterImage(false)
 {
     ASSERT(hasTagName(videoTag));
 }
@@ -74,8 +73,8 @@ void HTMLVideoElement::attach()
     HTMLMediaElement::attach();
 
 #if !ENABLE(PLUGIN_PROXY_FOR_VIDEO)
-    updatePosterImage();
-    if (m_shouldDisplayPosterImage) {
+    updateDisplayState();
+    if (shouldDisplayPosterImage()) {
         if (!m_imageLoader)
             m_imageLoader.set(new HTMLImageLoader(this));
         m_imageLoader->updateFromElement();
@@ -91,9 +90,8 @@ void HTMLVideoElement::detach()
 {
     HTMLMediaElement::detach();
     
-    if (!m_shouldDisplayPosterImage)
-        if (m_imageLoader)
-            m_imageLoader.clear();
+    if (!shouldDisplayPosterImage() && m_imageLoader)
+        m_imageLoader.clear();
 }
 
 void HTMLVideoElement::parseMappedAttribute(Attribute* attr)
@@ -101,15 +99,14 @@ void HTMLVideoElement::parseMappedAttribute(Attribute* attr)
     const QualifiedName& attrName = attr->name();
 
     if (attrName == posterAttr) {
-        updatePosterImage();
-        if (m_shouldDisplayPosterImage) {
+        // Force a poster recalc by setting m_displayMode to Unknown directly before calling updateDisplayState.
+        HTMLMediaElement::setDisplayMode(Unknown);
+        updateDisplayState();
+        if (shouldDisplayPosterImage()) {
 #if !ENABLE(PLUGIN_PROXY_FOR_VIDEO)
             if (!m_imageLoader)
                 m_imageLoader.set(new HTMLImageLoader(this));
             m_imageLoader->updateFromElementIgnoringPreviousError();
-#else
-            if (player())
-                player()->setPoster(getNonEmptyURLAttribute(posterAttr));
 #endif
         }
     } else if (attrName == widthAttr)
@@ -172,20 +169,42 @@ const QualifiedName& HTMLVideoElement::imageSourceAttributeName() const
     return posterAttr;
 }
 
-void HTMLVideoElement::updatePosterImage()
+void HTMLVideoElement::setDisplayMode(DisplayMode mode)
 {
-#if !ENABLE(PLUGIN_PROXY_FOR_VIDEO)
-    bool oldShouldShowPosterImage = m_shouldDisplayPosterImage;
-#endif
+    DisplayMode oldMode = displayMode();
+    KURL poster = getNonEmptyURLAttribute(posterAttr);
+
+    if (!poster.isEmpty()) {
+        // We have a poster path, but only show it until the user triggers display by playing or seeking and the
+        // media engine has something to display.
+        if (mode == Video) {
+            if (oldMode != Video && player())
+                player()->prepareForRendering();
+            if (!hasAvailableVideoFrame())
+                mode = Poster;
+        }
+    } else if (oldMode != Video && player())
+        player()->prepareForRendering();
+
+    HTMLMediaElement::setDisplayMode(mode);
 
-    m_shouldDisplayPosterImage = !getAttribute(posterAttr).isEmpty() && !hasAvailableVideoFrame();
+    if (player() && player()->canLoadPoster())
+        player()->setPoster(poster);
 
 #if !ENABLE(PLUGIN_PROXY_FOR_VIDEO)
-    if (renderer() && oldShouldShowPosterImage != m_shouldDisplayPosterImage)
+    if (renderer() && displayMode() != oldMode)
         renderer()->updateFromElement();
 #endif
 }
 
+void HTMLVideoElement::updateDisplayState()
+{
+    if (getNonEmptyURLAttribute(posterAttr).isEmpty())
+        setDisplayMode(Video);
+    else if (displayMode() < Poster)
+        setDisplayMode(Poster);
+}
+
 void HTMLVideoElement::paintCurrentFrameInContext(GraphicsContext* context, const IntRect& destRect)
 {
     MediaPlayer* player = HTMLMediaElement::player();
diff --git a/WebCore/html/HTMLVideoElement.h b/WebCore/html/HTMLVideoElement.h
index e7c3f34..04a0beb 100644
--- a/WebCore/html/HTMLVideoElement.h
+++ b/WebCore/html/HTMLVideoElement.h
@@ -55,11 +55,11 @@ public:
     void webkitEnterFullScreen(bool isUserGesture, ExceptionCode& ec) { webkitEnterFullscreen(isUserGesture, ec); }
     void webkitExitFullScreen() { webkitExitFullscreen(); }
 
-    bool shouldDisplayPosterImage() const { return m_shouldDisplayPosterImage; }
-
     // Used by canvas to gain raw pixel access
     void paintCurrentFrameInContext(GraphicsContext*, const IntRect&);
 
+    bool shouldDisplayPosterImage() const { return displayMode() == Poster; }
+
 private:
     HTMLVideoElement(const QualifiedName&, Document*);
 
@@ -78,11 +78,14 @@ private:
     virtual const QualifiedName& imageSourceAttributeName() const;
 
     virtual bool hasAvailableVideoFrame() const;
-    virtual void updatePosterImage();
+    virtual void updateDisplayState();
+
     virtual void willMoveToNewOwnerDocument();
 
+    virtual void setDisplayMode(DisplayMode);
+
     OwnPtr<HTMLImageLoader> m_imageLoader;
-    bool m_shouldDisplayPosterImage;
+
 };
 
 } //namespace
diff --git a/WebCore/platform/graphics/MediaPlayer.cpp b/WebCore/platform/graphics/MediaPlayer.cpp
index 4fb01c8..0732116 100644
--- a/WebCore/platform/graphics/MediaPlayer.cpp
+++ b/WebCore/platform/graphics/MediaPlayer.cpp
@@ -292,6 +292,11 @@ bool MediaPlayer::hasAvailableVideoFrame() const
     return m_private->hasAvailableVideoFrame();
 }
     
+void MediaPlayer::prepareForRendering()
+{
+    return m_private->prepareForRendering();
+}
+    
 bool MediaPlayer::canLoadPoster() const
 {
     return m_private->canLoadPoster();
diff --git a/WebCore/platform/graphics/MediaPlayer.h b/WebCore/platform/graphics/MediaPlayer.h
index 6945872..be4f672 100644
--- a/WebCore/platform/graphics/MediaPlayer.h
+++ b/WebCore/platform/graphics/MediaPlayer.h
@@ -246,6 +246,7 @@ public:
     MediaPlayerClient* mediaPlayerClient() const { return m_mediaPlayerClient; }
 
     bool hasAvailableVideoFrame() const;
+    void prepareForRendering();
 
     bool canLoadPoster() const;
     void setPoster(const String&);
diff --git a/WebCore/platform/graphics/MediaPlayerPrivate.h b/WebCore/platform/graphics/MediaPlayerPrivate.h
index 40aeacb..37e3ced 100644
--- a/WebCore/platform/graphics/MediaPlayerPrivate.h
+++ b/WebCore/platform/graphics/MediaPlayerPrivate.h
@@ -123,6 +123,8 @@ public:
 
     virtual MediaPlayer::MovieLoadType movieLoadType() const { return MediaPlayer::Unknown; }
 
+    virtual void prepareForRendering() { }
+
 };
 
 }
diff --git a/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h b/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h
index 2636aeb..3895a00 100644
--- a/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h
+++ b/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h
@@ -59,7 +59,6 @@ class MediaPlayerPrivate : public MediaPlayerPrivateInterface {
 public:
     static void registerMediaEngine(MediaEngineRegistrar);
 
-
     void repaint();
     void loadStateChanged();
     void rateChanged();
@@ -127,6 +126,8 @@ private:
 
     void paint(GraphicsContext*, const IntRect&);
     void paintCurrentFrameInContext(GraphicsContext*, const IntRect&);
+    virtual void prepareForRendering();
+
 
 #if USE(ACCELERATED_COMPOSITING)
     bool supportsAcceleratedRendering() const;
@@ -170,7 +171,7 @@ private:
     void cacheMovieScale();
     bool metaDataAvailable() const { return m_qtMovie && m_readyState >= MediaPlayer::HaveMetadata; }
 
-    bool isReadyForRendering() const;
+    bool isReadyForVideoSetup() const;
     
     MediaPlayer* m_player;
     RetainPtr<QTMovie> m_qtMovie;
@@ -197,6 +198,7 @@ private:
     bool m_hasUnsupportedTracks;
     bool m_videoFrameHasDrawn;
     bool m_delayingLoad;
+    bool m_isAllowedToRender;
 #if DRAW_FRAME_RATE
     int  m_frameCountWhilePlaying;
     double m_timeStartedPlaying;
diff --git a/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm b/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm
index 5c327f9..435e56e 100644
--- a/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm
+++ b/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm
@@ -217,6 +217,7 @@ MediaPlayerPrivate::MediaPlayerPrivate(MediaPlayer* player)
     , m_visible(false)
     , m_hasUnsupportedTracks(false)
     , m_videoFrameHasDrawn(false)
+    , m_isAllowedToRender(false)
 #if DRAW_FRAME_RATE
     , m_frameCountWhilePlaying(0)
     , m_timeStartedPlaying(0)
@@ -495,7 +496,7 @@ MediaPlayerPrivate::MediaRenderingMode MediaPlayerPrivate::preferredRenderingMod
 
 void MediaPlayerPrivate::setUpVideoRendering()
 {
-    if (!isReadyForRendering())
+    if (!isReadyForVideoSetup())
         return;
 
     MediaRenderingMode currentMode = currentRenderingMode();
@@ -519,10 +520,9 @@ void MediaPlayerPrivate::setUpVideoRendering()
         break;
     }
 
-#if USE(ACCELERATED_COMPOSITING)
+    // If using a movie layer, inform the client so the compositing tree is updated.
     if (currentMode == MediaRenderingMovieLayer || preferredMode == MediaRenderingMovieLayer)
         m_player->mediaPlayerClient()->mediaPlayerRenderingModeChanged(m_player);
-#endif
 }
 
 void MediaPlayerPrivate::tearDownVideoRendering()
@@ -915,11 +915,26 @@ void MediaPlayerPrivate::cacheMovieScale()
         m_scaleFactor.setHeight(initialSize.height / naturalSize.height);
 }
 
-bool MediaPlayerPrivate::isReadyForRendering() const
+bool MediaPlayerPrivate::isReadyForVideoSetup() const
 {
     return m_readyState >= MediaPlayer::HaveMetadata && m_player->visible();
 }
 
+void MediaPlayerPrivate::prepareForRendering()
+{
+    if (m_isAllowedToRender)
+        return;
+    m_isAllowedToRender = true;
+
+    if (!hasSetUpVideoRendering())
+        setUpVideoRendering();
+
+    // If using a movie layer, inform the client so the compositing tree is updated. This is crucial if the movie
+    // has a poster, as it will most likely not have a layer and we will now be rendering frames to the movie layer.
+    if (currentRenderingMode() == MediaRenderingMovieLayer || preferredRenderingMode() == MediaRenderingMovieLayer)
+        m_player->mediaPlayerClient()->mediaPlayerRenderingModeChanged(m_player);
+}
+
 void MediaPlayerPrivate::updateStates()
 {
     MediaPlayer::NetworkState oldNetworkState = m_networkState;
@@ -1009,7 +1024,7 @@ void MediaPlayerPrivate::updateStates()
         }
     }
 
-    if (!hasSetUpVideoRendering())
+    if (isReadyForVideoSetup() && !hasSetUpVideoRendering())
         setUpVideoRendering();
 
     if (seeking())
@@ -1443,8 +1458,9 @@ void MediaPlayerPrivate::sawUnsupportedTracks()
 #if USE(ACCELERATED_COMPOSITING)
 bool MediaPlayerPrivate::supportsAcceleratedRendering() const
 {
-    // When in the media document we render via QTMovieView, which is already accelerated.
-    return isReadyForRendering() && getQTMovieLayerClass() != Nil && !m_player->inMediaDocument();
+    // Also don't claim to support accelerated rendering when in the media document, as we will then render 
+    // via QTMovieView which is already accelerated.
+    return isReadyForVideoSetup() && getQTMovieLayerClass() != Nil && !m_player->inMediaDocument();
 }
 
 void MediaPlayerPrivate::acceleratedRenderingStateChanged()
diff --git a/WebCore/rendering/RenderLayerBacking.cpp b/WebCore/rendering/RenderLayerBacking.cpp
index b3a7917..68dc4d8 100644
--- a/WebCore/rendering/RenderLayerBacking.cpp
+++ b/WebCore/rendering/RenderLayerBacking.cpp
@@ -759,7 +759,7 @@ bool RenderLayerBacking::containsPaintedContent() const
 
     // FIXME: we could optimize cases where the image, video or canvas is known to fill the border box entirely,
     // and set background color on the layer in that case, instead of allocating backing store and painting.
-    if (renderer()->isVideo())
+    if (renderer()->isVideo() && toRenderVideo(renderer())->shouldDisplayVideo())
         return hasBoxDecorationsOrBackground(renderer());
 #if ENABLE(3D_CANVAS) || ENABLE(ACCELERATED_2D_CANVAS)
     if (isAcceleratedCanvas(renderer()))
diff --git a/WebCore/rendering/RenderLayerCompositor.cpp b/WebCore/rendering/RenderLayerCompositor.cpp
index 7798dfb..a8cf4e9 100644
--- a/WebCore/rendering/RenderLayerCompositor.cpp
+++ b/WebCore/rendering/RenderLayerCompositor.cpp
@@ -1163,7 +1163,7 @@ bool RenderLayerCompositor::requiresCompositingForVideo(RenderObject* renderer)
 #if ENABLE(VIDEO)
     if (renderer->isVideo()) {
         RenderVideo* video = toRenderVideo(renderer);
-        return canAccelerateVideoRendering(video);
+        return video->shouldDisplayVideo() && canAccelerateVideoRendering(video);
     }
 #if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
     else if (renderer->isRenderPart()) {
diff --git a/WebCore/rendering/RenderVideo.cpp b/WebCore/rendering/RenderVideo.cpp
index 610fb5f..1e0adc4 100644
--- a/WebCore/rendering/RenderVideo.cpp
+++ b/WebCore/rendering/RenderVideo.cpp
@@ -155,7 +155,12 @@ IntRect RenderVideo::videoBox() const
 
     return renderBox;
 }
-    
+
+bool RenderVideo::shouldDisplayVideo() const
+{
+    return !videoElement()->shouldDisplayPosterImage();
+}
+
 void RenderVideo::paintReplaced(PaintInfo& paintInfo, int tx, int ty)
 {
     MediaPlayer* mediaPlayer = player();
@@ -174,6 +179,7 @@ void RenderVideo::paintReplaced(PaintInfo& paintInfo, int tx, int ty)
     if (rect.isEmpty())
         return;
     rect.move(tx, ty);
+
     if (displayingPoster)
         paintIntoRect(paintInfo.context, rect);
     else
diff --git a/WebCore/rendering/RenderVideo.h b/WebCore/rendering/RenderVideo.h
index bb2b05c..d2f0ed4 100644
--- a/WebCore/rendering/RenderVideo.h
+++ b/WebCore/rendering/RenderVideo.h
@@ -50,6 +50,8 @@ public:
     void acceleratedRenderingStateChanged();
 #endif
 
+    virtual bool shouldDisplayVideo() const;
+
 private:
     virtual void updateFromElement();
     inline HTMLVideoElement* videoElement() const;

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list