diff options
Diffstat (limited to 'WebCore/platform')
11 files changed, 421 insertions, 141 deletions
diff --git a/WebCore/platform/android/RenderThemeAndroid.cpp b/WebCore/platform/android/RenderThemeAndroid.cpp index 66f034d..5253219 100644 --- a/WebCore/platform/android/RenderThemeAndroid.cpp +++ b/WebCore/platform/android/RenderThemeAndroid.cpp @@ -248,7 +248,7 @@ bool RenderThemeAndroid::shouldRenderMediaControlPart(ControlPart part, Element* return false; case MediaSeekBackButtonPart: case MediaSeekForwardButtonPart: - return true; + return false; case MediaRewindButtonPart: return mediaElement->movieLoadType() != MediaPlayer::LiveStream; case MediaReturnToRealtimeButtonPart: @@ -262,19 +262,34 @@ bool RenderThemeAndroid::shouldRenderMediaControlPart(ControlPart part, Element* } } +bool paintMediaFullscreenButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& rect) +{ + bool translucent = false; + if (o && toParentMediaElement(o) && toParentMediaElement(o)->hasTagName(HTMLNames::videoTag)) + translucent = true; + RenderSkinMediaButton::Draw(getCanvasFromInfo(paintInfo), rect, RenderSkinMediaButton::PLAY, translucent); + return false; +} + bool RenderThemeAndroid::paintMediaMuteButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& rect) { - RenderSkinMediaButton::Draw(getCanvasFromInfo(paintInfo), rect, RenderSkinMediaButton::MUTE); + bool translucent = false; + if (o && toParentMediaElement(o) && toParentMediaElement(o)->hasTagName(HTMLNames::videoTag)) + translucent = true; + RenderSkinMediaButton::Draw(getCanvasFromInfo(paintInfo), rect, RenderSkinMediaButton::MUTE, translucent); return false; } bool RenderThemeAndroid::paintMediaPlayButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& rect) { + bool translucent = false; + if (o && toParentMediaElement(o) && toParentMediaElement(o)->hasTagName(HTMLNames::videoTag)) + translucent = true; if (MediaControlPlayButtonElement* btn = static_cast<MediaControlPlayButtonElement*>(o->node())) { if (btn->displayType() == MediaPlayButton) - RenderSkinMediaButton::Draw(getCanvasFromInfo(paintInfo), rect, RenderSkinMediaButton::PLAY); + RenderSkinMediaButton::Draw(getCanvasFromInfo(paintInfo), rect, RenderSkinMediaButton::PLAY, translucent); else - RenderSkinMediaButton::Draw(getCanvasFromInfo(paintInfo), rect, RenderSkinMediaButton::PAUSE); + RenderSkinMediaButton::Draw(getCanvasFromInfo(paintInfo), rect, RenderSkinMediaButton::PAUSE, translucent); return false; } return true; @@ -282,31 +297,46 @@ bool RenderThemeAndroid::paintMediaPlayButton(RenderObject* o, const PaintInfo& bool RenderThemeAndroid::paintMediaSeekBackButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& rect) { - RenderSkinMediaButton::Draw(getCanvasFromInfo(paintInfo), rect, RenderSkinMediaButton::REWIND); + bool translucent = false; + if (o && toParentMediaElement(o) && toParentMediaElement(o)->hasTagName(HTMLNames::videoTag)) + translucent = true; + RenderSkinMediaButton::Draw(getCanvasFromInfo(paintInfo), rect, RenderSkinMediaButton::REWIND, translucent); return false; } bool RenderThemeAndroid::paintMediaSeekForwardButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& rect) { - RenderSkinMediaButton::Draw(getCanvasFromInfo(paintInfo), rect, RenderSkinMediaButton::FORWARD); + bool translucent = false; + if (o && toParentMediaElement(o) && toParentMediaElement(o)->hasTagName(HTMLNames::videoTag)) + translucent = true; + RenderSkinMediaButton::Draw(getCanvasFromInfo(paintInfo), rect, RenderSkinMediaButton::FORWARD, translucent); return false; } -bool RenderThemeAndroid::paintMediaControlsBackground(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect) +bool RenderThemeAndroid::paintMediaControlsBackground(RenderObject* o, const PaintInfo& paintInfo, const IntRect& rect) { - RenderSkinMediaButton::Draw(getCanvasFromInfo(paintInfo), rect, RenderSkinMediaButton::BACKGROUND_SLIDER); + bool translucent = false; + if (o && toParentMediaElement(o) && toParentMediaElement(o)->hasTagName(HTMLNames::videoTag)) + translucent = true; + RenderSkinMediaButton::Draw(getCanvasFromInfo(paintInfo), rect, RenderSkinMediaButton::BACKGROUND_SLIDER, translucent); return false; } bool RenderThemeAndroid::paintMediaSliderTrack(RenderObject* o, const PaintInfo& paintInfo, const IntRect& rect) { - RenderSkinMediaButton::Draw(getCanvasFromInfo(paintInfo), rect, RenderSkinMediaButton::SLIDER_TRACK); + bool translucent = false; + if (o && toParentMediaElement(o) && toParentMediaElement(o)->hasTagName(HTMLNames::videoTag)) + translucent = true; + RenderSkinMediaButton::Draw(getCanvasFromInfo(paintInfo), rect, RenderSkinMediaButton::SLIDER_TRACK, translucent); return false; } bool RenderThemeAndroid::paintMediaSliderThumb(RenderObject* o, const PaintInfo& paintInfo, const IntRect& rect) { - RenderSkinMediaButton::Draw(getCanvasFromInfo(paintInfo), rect, RenderSkinMediaButton::SLIDER_THUMB); + bool translucent = false; + if (o && toParentMediaElement(o) && toParentMediaElement(o)->hasTagName(HTMLNames::videoTag)) + translucent = true; + RenderSkinMediaButton::Draw(getCanvasFromInfo(paintInfo), rect, RenderSkinMediaButton::SLIDER_THUMB, translucent); return false; } diff --git a/WebCore/platform/graphics/android/AndroidAnimation.cpp b/WebCore/platform/graphics/android/AndroidAnimation.cpp index 3280d07..a064d05 100644 --- a/WebCore/platform/graphics/android/AndroidAnimation.cpp +++ b/WebCore/platform/graphics/android/AndroidAnimation.cpp @@ -54,17 +54,17 @@ long AndroidAnimation::instancesCount() return gDebugAndroidAnimationInstances; } -AndroidAnimation::AndroidAnimation(AndroidAnimationType type, +AndroidAnimation::AndroidAnimation(AnimatedPropertyID type, const Animation* animation, + KeyframeValueList* operations, double beginTime) : m_beginTime(beginTime) , m_duration(animation->duration()) , m_iterationCount(animation->iterationCount()) - , m_currentIteration(0) , m_direction(animation->direction()) - , m_currentDirection(false) , m_timingFunction(animation->timingFunction()) , m_type(type) + , m_operations(operations) { ASSERT(m_timingFunction); @@ -78,11 +78,10 @@ AndroidAnimation::AndroidAnimation(AndroidAnimation* anim) : m_beginTime(anim->m_beginTime) , m_duration(anim->m_duration) , m_iterationCount(anim->m_iterationCount) - , m_currentIteration(0) , m_direction(anim->m_direction) - , m_currentDirection(false) , m_timingFunction(anim->m_timingFunction) , m_type(anim->m_type) + , m_operations(anim->m_operations) { gDebugAndroidAnimationInstances++; } @@ -92,7 +91,7 @@ AndroidAnimation::~AndroidAnimation() gDebugAndroidAnimationInstances--; } -float AndroidAnimation::currentProgress(double time) +double AndroidAnimation::elapsedTime(double time) { if (m_beginTime <= 0.000001) // overflow or not correctly set m_beginTime = time; @@ -105,37 +104,69 @@ float AndroidAnimation::currentProgress(double time) if (m_elapsedTime < 0) // animation not yet started. return 0; - return m_elapsedTime / m_duration; + return m_elapsedTime; } bool AndroidAnimation::checkIterationsAndProgress(double time, float* finalProgress) { - float progress = currentProgress(time); + double progress = elapsedTime(time); + double dur = m_duration; + if (m_iterationCount > 0) + dur *= m_iterationCount; - int currentIteration = static_cast<int>(progress); - if (currentIteration != m_currentIteration) - if (m_direction == Animation::AnimationDirectionAlternate) - swapDirection(); - - m_currentIteration = currentIteration; - progress -= m_currentIteration; + if (m_duration <= 0) + return false; - if ((m_currentIteration >= m_iterationCount) - && (m_iterationCount != Animation::IterationCountInfinite)) + // If not infinite, return false if we are done + if (m_iterationCount > 0 && progress > dur) return false; - if (m_timingFunction->isCubicBezierTimingFunction()) { - CubicBezierTimingFunction* bezierFunction = static_cast<CubicBezierTimingFunction*>(m_timingFunction.get()); + double fractionalTime = progress / m_duration; + int integralTime = static_cast<int>(fractionalTime); + + fractionalTime -= integralTime; + + if ((m_direction == Animation::AnimationDirectionAlternate) && (integralTime & 1)) + fractionalTime = 1 - fractionalTime; + + *finalProgress = fractionalTime; + return true; +} + +double AndroidAnimation::applyTimingFunction(float from, float to, double progress, + const TimingFunction* tf) +{ + double fractionalTime = progress; + double offset = from; + double scale = 1.0 / (to - from); + + if (scale != 1 || offset) + fractionalTime = (fractionalTime - offset) * scale; + + const TimingFunction* timingFunction = tf; + + if (!timingFunction) + timingFunction = m_timingFunction.get(); + + if (timingFunction && timingFunction->isCubicBezierTimingFunction()) { + const CubicBezierTimingFunction* bezierFunction = static_cast<const CubicBezierTimingFunction*>(timingFunction); UnitBezier bezier(bezierFunction->x1(), bezierFunction->y1(), bezierFunction->x2(), bezierFunction->y2()); if (m_duration > 0) - progress = bezier.solve(progress, 1.0f / (200.0f * m_duration)); + fractionalTime = bezier.solve(fractionalTime, 1.0f / (200.0f * m_duration)); + } else if (timingFunction && timingFunction->isStepsTimingFunction()) { + const StepsTimingFunction* stepFunction = static_cast<const StepsTimingFunction*>(timingFunction); + if (stepFunction->stepAtStart()) { + fractionalTime = (floor(stepFunction->numberOfSteps() * fractionalTime) + 1) / stepFunction->numberOfSteps(); + if (fractionalTime > 1.0) + fractionalTime = 1.0; + } else { + fractionalTime = floor(stepFunction->numberOfSteps() * fractionalTime) / stepFunction->numberOfSteps(); + } } - - *finalProgress = progress; - return true; + return fractionalTime; } PassRefPtr<AndroidOpacityAnimation> AndroidOpacityAnimation::create( @@ -150,14 +181,12 @@ PassRefPtr<AndroidOpacityAnimation> AndroidOpacityAnimation::create( AndroidOpacityAnimation::AndroidOpacityAnimation(const Animation* animation, KeyframeValueList* operations, double beginTime) - : AndroidAnimation(AndroidAnimation::OPACITY, animation, beginTime) - , m_operations(operations) + : AndroidAnimation(AnimatedPropertyOpacity, animation, operations, beginTime) { } AndroidOpacityAnimation::AndroidOpacityAnimation(AndroidOpacityAnimation* anim) : AndroidAnimation(anim) - , m_operations(anim->m_operations) { } @@ -166,41 +195,45 @@ PassRefPtr<AndroidAnimation> AndroidOpacityAnimation::copy() return adoptRef(new AndroidOpacityAnimation(this)); } -bool AndroidOpacityAnimation::evaluate(LayerAndroid* layer, double time) +void AndroidAnimation::pickValues(double progress, int* start, int* end) { - float progress; - if (!checkIterationsAndProgress(time, &progress)) - return false; - - if (progress < 0) // we still want to be evaluated until we get progress > 0 - return true; - - // First, we need to get the from and to values - - FloatAnimationValue* fromValue = 0; - FloatAnimationValue* toValue = 0; - - float distance = 0; + float distance = -1; unsigned int foundAt = 0; for (unsigned int i = 0; i < m_operations->size(); i++) { - FloatAnimationValue* value = (FloatAnimationValue*) m_operations->at(i); - float opacity = (float) value->value(); + const AnimationValue* value = m_operations->at(i); float key = value->keyTime(); float d = progress - key; - XLOG("[%d] Key %.2f, opacity %.4f", i, key, opacity); - if (!fromValue || (d > 0 && d < distance && i + 1 < m_operations->size())) { - fromValue = value; + if (distance == -1 || (d >= 0 && d < distance && i + 1 < m_operations->size())) { distance = d; foundAt = i; } } + *start = foundAt; + if (foundAt + 1 < m_operations->size()) - toValue = (FloatAnimationValue*) m_operations->at(foundAt + 1); + *end = foundAt + 1; else - toValue = fromValue; + *end = foundAt; +} - XLOG("[layer %d] fromValue %x, key %.2f, toValue %x, key %.2f for progress %.2f", +bool AndroidOpacityAnimation::evaluate(LayerAndroid* layer, double time) +{ + float progress; + if (!checkIterationsAndProgress(time, &progress)) + return false; + + if (progress < 0) // we still want to be evaluated until we get progress > 0 + return true; + + // First, we need to get the from and to values + + int from, to; + pickValues(progress, &from, &to); + FloatAnimationValue* fromValue = (FloatAnimationValue*) m_operations->at(from); + FloatAnimationValue* toValue = (FloatAnimationValue*) m_operations->at(to); + + XLOG("[layer %d] opacity fromValue %x, key %.2f, toValue %x, key %.2f for progress %.2f", layer->uniqueId(), fromValue, fromValue->keyTime(), toValue, toValue->keyTime(), progress); @@ -208,18 +241,14 @@ bool AndroidOpacityAnimation::evaluate(LayerAndroid* layer, double time) // We now have the correct two values to work with, let's compute the // progress value - float delta = toValue->keyTime() - fromValue->keyTime(); - float rprogress = (progress - fromValue->keyTime()) / delta; - XLOG("We picked keys %.2f to %.2f for progress %.2f, real progress %.2f", - fromValue->keyTime(), toValue->keyTime(), progress, rprogress); - progress = rprogress; - - float from = (float) fromValue->value(); - float to = (float) toValue->value(); - float value = from + ((to - from) * progress); + const TimingFunction* timingFunction = fromValue->timingFunction(); + progress = applyTimingFunction(fromValue->keyTime(), toValue->keyTime(), + progress, timingFunction); + float value = fromValue->value() + ((toValue->value() - fromValue->value()) * progress); layer->setOpacity(value); - XLOG("AndroidOpacityAnimation::evaluate(%p, %p, %L) value=%.6f", this, layer, time, value); + + XLOG("AndroidOpacityAnimation::evaluate(%p, %p, %.2f) value=%.6f", this, layer, time, value); return true; } @@ -234,14 +263,12 @@ PassRefPtr<AndroidTransformAnimation> AndroidTransformAnimation::create( AndroidTransformAnimation::AndroidTransformAnimation(const Animation* animation, KeyframeValueList* operations, double beginTime) - : AndroidAnimation(AndroidAnimation::TRANSFORM, animation, beginTime) - , m_operations(operations) + : AndroidAnimation(AnimatedPropertyWebkitTransform, animation, operations, beginTime) { } AndroidTransformAnimation::AndroidTransformAnimation(AndroidTransformAnimation* anim) : AndroidAnimation(anim) - , m_operations(anim->m_operations) { } @@ -269,28 +296,10 @@ bool AndroidTransformAnimation::evaluate(LayerAndroid* layer, double time) // First, we need to get the from and to values - TransformAnimationValue* fromValue = 0; - TransformAnimationValue* toValue = 0; - - float distance = 0; - unsigned int foundAt = 0; - for (unsigned int i = 0; i < m_operations->size(); i++) { - TransformAnimationValue* value = (TransformAnimationValue*) m_operations->at(i); - TransformOperations* values = (TransformOperations*) value->value(); - float key = value->keyTime(); - float d = progress - key; - XLOG("[%d] Key %.2f, %d values", i, key, values->size()); - if (!fromValue || (d > 0 && d < distance && i + 1 < m_operations->size())) { - fromValue = value; - distance = d; - foundAt = i; - } - } - - if (foundAt + 1 < m_operations->size()) - toValue = (TransformAnimationValue*) m_operations->at(foundAt + 1); - else - toValue = fromValue; + int from, to; + pickValues(progress, &from, &to); + TransformAnimationValue* fromValue = (TransformAnimationValue*) m_operations->at(from); + TransformAnimationValue* toValue = (TransformAnimationValue*) m_operations->at(to); XLOG("[layer %d] fromValue %x, key %.2f, toValue %x, key %.2f for progress %.2f", layer->uniqueId(), @@ -300,12 +309,12 @@ bool AndroidTransformAnimation::evaluate(LayerAndroid* layer, double time) // We now have the correct two values to work with, let's compute the // progress value - float delta = toValue->keyTime() - fromValue->keyTime(); - float rprogress = (progress - fromValue->keyTime()) / delta; - XLOG("We picked keys %.2f to %.2f for progress %.2f, real progress %.2f", - fromValue->keyTime(), toValue->keyTime(), progress, rprogress); - progress = rprogress; - + const TimingFunction* timingFunction = fromValue->timingFunction(); + float p = applyTimingFunction(fromValue->keyTime(), toValue->keyTime(), + progress, timingFunction); + XLOG("progress %.2f => %.2f from: %.2f to: %.2f", progress, p, fromValue->keyTime(), + toValue->keyTime()); + progress = p; // With both values and the progress, we also need to check out that // the operations are compatible (i.e. we are animating the same number diff --git a/WebCore/platform/graphics/android/AndroidAnimation.h b/WebCore/platform/graphics/android/AndroidAnimation.h index d682103..4f84799 100644 --- a/WebCore/platform/graphics/android/AndroidAnimation.h +++ b/WebCore/platform/graphics/android/AndroidAnimation.h @@ -35,38 +35,35 @@ class TimingFunction; class AndroidAnimation : public RefCounted<AndroidAnimation> { public: - enum AndroidAnimationType { - UNDEFINED, - OPACITY, - TRANSFORM - }; - AndroidAnimation(AndroidAnimationType type, + AndroidAnimation(AnimatedPropertyID type, const Animation* animation, + KeyframeValueList* operations, double beginTime); AndroidAnimation(AndroidAnimation* anim); virtual ~AndroidAnimation(); virtual PassRefPtr<AndroidAnimation> copy() = 0; - float currentProgress(double time); + double elapsedTime(double time); + void pickValues(double progress, int* start, int* end); bool checkIterationsAndProgress(double time, float* finalProgress); - virtual void swapDirection() { m_currentDirection = !m_currentDirection; } + double applyTimingFunction(float from, float to, double progress, + const TimingFunction* timingFunction); virtual bool evaluate(LayerAndroid* layer, double time) = 0; static long instancesCount(); void setName(const String& name) { m_name = name; } String name() { return m_name; } - AndroidAnimationType type() { return m_type; } + AnimatedPropertyID type() { return m_type; } protected: double m_beginTime; double m_elapsedTime; double m_duration; int m_iterationCount; - int m_currentIteration; int m_direction; - bool m_currentDirection; RefPtr<TimingFunction> m_timingFunction; String m_name; - AndroidAnimationType m_type; + AnimatedPropertyID m_type; + KeyframeValueList* m_operations; }; class AndroidOpacityAnimation : public AndroidAnimation { @@ -81,9 +78,6 @@ class AndroidOpacityAnimation : public AndroidAnimation { virtual PassRefPtr<AndroidAnimation> copy(); virtual bool evaluate(LayerAndroid* layer, double time); - - private: - KeyframeValueList* m_operations; }; class AndroidTransformAnimation : public AndroidAnimation { @@ -100,9 +94,6 @@ class AndroidTransformAnimation : public AndroidAnimation { virtual PassRefPtr<AndroidAnimation> copy(); virtual bool evaluate(LayerAndroid* layer, double time); - - private: - KeyframeValueList* m_operations; }; } // namespace WebCore diff --git a/WebCore/platform/graphics/android/BaseTile.cpp b/WebCore/platform/graphics/android/BaseTile.cpp index 47be13b..4400ea5 100644 --- a/WebCore/platform/graphics/android/BaseTile.cpp +++ b/WebCore/platform/graphics/android/BaseTile.cpp @@ -381,6 +381,9 @@ void BaseTile::paintBitmap() if (!m_currentDirtyArea->isEmpty()) m_dirty = true; + if (!m_dirty) + m_usable = true; + m_painting = false; m_atomicSync.unlock(); @@ -398,6 +401,10 @@ int BaseTile::paintPartialBitmap(SkIRect r, float ptx, float pty, fullRepaint = true; } + if ((rect.width() > TilesManager::instance()->tileWidth()) || + (rect.height() > TilesManager::instance()->tileHeight())) + fullRepaint = true; + if (fullRepaint) { rect.set(0, 0, TilesManager::instance()->tileWidth(), TilesManager::instance()->tileHeight()); diff --git a/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp b/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp index 54346e5..72aefa4 100644 --- a/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp +++ b/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp @@ -609,7 +609,7 @@ bool GraphicsLayerAndroid::repaint() } } - TLOG("(%x) repaint() on (%.2f,%.2f) contentlayer(%.2f,%.2f,%.2f,%.2f)paintGraphicsLayer called!", + LOG("(%x) repaint() on (%.2f,%.2f) contentlayer(%.2f,%.2f,%.2f,%.2f)paintGraphicsLayer called!", this, m_size.width(), m_size.height(), m_contentLayer->getPosition().fX, m_contentLayer->getPosition().fY, @@ -722,23 +722,22 @@ bool GraphicsLayerAndroid::createAnimationFromKeyframes(const KeyframeValueList& bool isKeyframe = valueList.size() > 2; TLOG("createAnimationFromKeyframes(%d), name(%s) beginTime(%.2f)", isKeyframe, keyframesName.latin1().data(), beginTime); - // TODO: handles keyframe animations correctly switch (valueList.property()) { case AnimatedPropertyInvalid: break; case AnimatedPropertyWebkitTransform: break; case AnimatedPropertyBackgroundColor: break; - case AnimatedPropertyOpacity: { MLOG("ANIMATEDPROPERTYOPACITY"); KeyframeValueList* operationsList = new KeyframeValueList(AnimatedPropertyOpacity); for (unsigned int i = 0; i < valueList.size(); i++) { - FloatAnimationValue* originalValue = (FloatAnimationValue*)valueList.at(i); - FloatAnimationValue* value = new FloatAnimationValue(originalValue->keyTime(), - originalValue->value(), 0); - // TODO: pass the timing function originalValue->timingFunction()); - operationsList->insert(value); + FloatAnimationValue* originalValue = (FloatAnimationValue*)valueList.at(i); + PassRefPtr<TimingFunction> timingFunction(const_cast<TimingFunction*>(originalValue->timingFunction())); + FloatAnimationValue* value = new FloatAnimationValue(originalValue->keyTime(), + originalValue->value(), + timingFunction); + operationsList->insert(value); } RefPtr<AndroidOpacityAnimation> anim = AndroidOpacityAnimation::create(animation, @@ -776,9 +775,10 @@ bool GraphicsLayerAndroid::createTransformAnimationsFromKeyframes(const Keyframe KeyframeValueList* operationsList = new KeyframeValueList(AnimatedPropertyWebkitTransform); for (unsigned int i = 0; i < valueList.size(); i++) { TransformAnimationValue* originalValue = (TransformAnimationValue*)valueList.at(i); + PassRefPtr<TimingFunction> timingFunction(const_cast<TimingFunction*>(originalValue->timingFunction())); TransformAnimationValue* value = new TransformAnimationValue(originalValue->keyTime(), - originalValue->value(), 0); - // TODO: pass the timing function originalValue->timingFunction()); + originalValue->value(), + timingFunction); operationsList->insert(value); } @@ -801,14 +801,14 @@ bool GraphicsLayerAndroid::createTransformAnimationsFromKeyframes(const Keyframe void GraphicsLayerAndroid::removeAnimationsForProperty(AnimatedPropertyID anID) { TLOG("NRO removeAnimationsForProperty(%d)", anID); - m_contentLayer->removeAnimation(propertyIdToString(anID)); + m_contentLayer->removeAnimationsForProperty(anID); askForSync(); } void GraphicsLayerAndroid::removeAnimationsForKeyframes(const String& keyframesName) { TLOG("NRO removeAnimationsForKeyframes(%s)", keyframesName.latin1().data()); - m_contentLayer->removeAnimation(keyframesName); + m_contentLayer->removeAnimationsForKeyframes(keyframesName); askForSync(); } @@ -852,9 +852,9 @@ void GraphicsLayerAndroid::setContentsToMedia(PlatformLayer* mediaLayer) mediaLayer->setSize(m_contentLayer->getWidth(), m_contentLayer->getHeight()); mediaLayer->setDrawTransform(m_contentLayer->drawTransform()); + mediaLayer->ref(); m_contentLayer->unref(); m_contentLayer = mediaLayer; - m_contentLayer->ref(); // If the parent exists then notify it to re-sync it's children if (m_parent) { diff --git a/WebCore/platform/graphics/android/ImageSourceAndroid.cpp b/WebCore/platform/graphics/android/ImageSourceAndroid.cpp index 728ea35..f7fc80c 100644 --- a/WebCore/platform/graphics/android/ImageSourceAndroid.cpp +++ b/WebCore/platform/graphics/android/ImageSourceAndroid.cpp @@ -59,7 +59,7 @@ SkPixelRef* SkCreateRLEPixelRef(const SkBitmap& src); #define MIN_RLE_ALLOC_SIZE (8*1024*1024) // see dox for computeMaxBitmapSizeForCache() - #define MAX_SIZE_BEFORE_SUBSAMPLE (8*1024*1024) + #define MAX_SIZE_BEFORE_SUBSAMPLE (32*1024*1024) // preserve quality for 24/32bit src static const SkBitmap::Config gPrefConfigTable[6] = { diff --git a/WebCore/platform/graphics/android/LayerAndroid.cpp b/WebCore/platform/graphics/android/LayerAndroid.cpp index 7d68f03..76fb2f2 100644 --- a/WebCore/platform/graphics/android/LayerAndroid.cpp +++ b/WebCore/platform/graphics/android/LayerAndroid.cpp @@ -132,8 +132,10 @@ LayerAndroid::LayerAndroid(const LayerAndroid& layer) : SkLayer(layer), addChild(layer.getChild(i)->copy())->unref(); KeyframesMap::const_iterator end = layer.m_animations.end(); - for (KeyframesMap::const_iterator it = layer.m_animations.begin(); it != end; ++it) - m_animations.add((it->second)->name(), (it->second)->copy()); + for (KeyframesMap::const_iterator it = layer.m_animations.begin(); it != end; ++it) { + pair<String, int> key((it->second)->name(), (it->second)->type()); + m_animations.add(key, (it->second)->copy()); + } #ifdef DEBUG_COUNT ClassTracker::instance()->increment("LayerAndroid"); @@ -243,15 +245,35 @@ bool LayerAndroid::evaluateAnimations(double time) const void LayerAndroid::addAnimation(PassRefPtr<AndroidAnimation> prpAnim) { RefPtr<AndroidAnimation> anim = prpAnim; - RefPtr<AndroidAnimation> currentAnim = m_animations.get(anim->name()); - if (currentAnim && currentAnim->type() == anim->type()) - removeAnimation(anim->name()); - m_animations.add(anim->name(), anim); + pair<String, int> key(anim->name(), anim->type()); + removeAnimationsForProperty(anim->type()); + m_animations.add(key, anim); +} + +void LayerAndroid::removeAnimationsForProperty(AnimatedPropertyID property) +{ + KeyframesMap::const_iterator end = m_animations.end(); + Vector<pair<String, int> > toDelete; + for (KeyframesMap::const_iterator it = m_animations.begin(); it != end; ++it) { + if ((it->second)->type() == property) + toDelete.append(it->first); + } + + for (unsigned int i = 0; i < toDelete.size(); i++) + m_animations.remove(toDelete[i]); } -void LayerAndroid::removeAnimation(const String& name) +void LayerAndroid::removeAnimationsForKeyframes(const String& name) { - m_animations.remove(name); + KeyframesMap::const_iterator end = m_animations.end(); + Vector<pair<String, int> > toDelete; + for (KeyframesMap::const_iterator it = m_animations.begin(); it != end; ++it) { + if ((it->second)->name() == name) + toDelete.append(it->first); + } + + for (unsigned int i = 0; i < toDelete.size(); i++) + m_animations.remove(toDelete[i]); } // We only use the bounding rect of the layer as mask... diff --git a/WebCore/platform/graphics/android/LayerAndroid.h b/WebCore/platform/graphics/android/LayerAndroid.h index 42356e9..3e00bfa 100644 --- a/WebCore/platform/graphics/android/LayerAndroid.h +++ b/WebCore/platform/graphics/android/LayerAndroid.h @@ -22,6 +22,7 @@ #include "FloatPoint.h" #include "FloatPoint3D.h" #include "FloatRect.h" +#include "GraphicsLayerClient.h" #include "LayerTexture.h" #include "RefPtr.h" #include "SkColor.h" @@ -179,7 +180,8 @@ public: SkPicture* recordContext(); void addAnimation(PassRefPtr<AndroidAnimation> anim); - void removeAnimation(const String& name); + void removeAnimationsForProperty(AnimatedPropertyID property); + void removeAnimationsForKeyframes(const String& name); bool evaluateAnimations() const; bool evaluateAnimations(double time) const; bool hasAnimations() const; @@ -242,6 +244,7 @@ public: void contentDraw(SkCanvas*); virtual bool isMedia() const { return false; } + virtual bool isVideo() const { return false; } RenderLayer* owningLayer() const { return m_owningLayer; } @@ -301,7 +304,7 @@ private: SkBitmapRef* m_contentsImage; - typedef HashMap<String, RefPtr<AndroidAnimation> > KeyframesMap; + typedef HashMap<pair<String, int>, RefPtr<AndroidAnimation> > KeyframesMap; KeyframesMap m_animations; SkPicture* m_extra; int m_uniqueId; diff --git a/WebCore/platform/graphics/android/MediaPlayerPrivateAndroid.h b/WebCore/platform/graphics/android/MediaPlayerPrivateAndroid.h index e8e29bf..66b35dd 100644 --- a/WebCore/platform/graphics/android/MediaPlayerPrivateAndroid.h +++ b/WebCore/platform/graphics/android/MediaPlayerPrivateAndroid.h @@ -32,6 +32,7 @@ class SkBitmap; #include "MediaPlayerPrivate.h" #include "TimeRanges.h" +#include "VideoLayerAndroid.h" namespace WebCore { @@ -93,6 +94,14 @@ public: virtual void onPosterFetched(SkBitmap*) { } void onBuffering(int percent); void onTimeupdate(int position); + + // These following two functions are used to turn on inline video support + bool supportsAcceleratedRendering() const { return true; } + LayerAndroid* platformLayer() const + { + return m_videoLayer; + } + protected: // Android-specific methods and fields. static MediaPlayerPrivateInterface* create(MediaPlayer* player); @@ -122,6 +131,7 @@ protected: bool m_naturalSizeUnknown; bool m_isVisible; + VideoLayerAndroid* m_videoLayer; }; } // namespace WebCore diff --git a/WebCore/platform/graphics/android/VideoLayerAndroid.cpp b/WebCore/platform/graphics/android/VideoLayerAndroid.cpp new file mode 100644 index 0000000..2eced57 --- /dev/null +++ b/WebCore/platform/graphics/android/VideoLayerAndroid.cpp @@ -0,0 +1,134 @@ +/* + * Copyright 2011 The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "VideoLayerAndroid.h" + +#include "TilesManager.h" +#include <GLES2/gl2.h> +#include <gui/SurfaceTexture.h> + +#if USE(ACCELERATED_COMPOSITING) + +#ifdef DEBUG +#include <cutils/log.h> +#include <wtf/text/CString.h> + +#undef XLOG +#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "VideoLayerAndroid", __VA_ARGS__) + +#else + +#undef XLOG +#define XLOG(...) + +#endif // DEBUG + +namespace WebCore { +GLuint VideoLayerAndroid::m_pauseTextureId = 0; +bool VideoLayerAndroid::m_createdPauseTexture = false; + +VideoLayerAndroid::VideoLayerAndroid() + : LayerAndroid((RenderLayer*)0) +{ + init(); +} + +VideoLayerAndroid::VideoLayerAndroid(const VideoLayerAndroid& layer) + : LayerAndroid(layer) +{ + init(); +} + +void VideoLayerAndroid::init() +{ + // m_surfaceTexture is only useful on UI thread, no need to copy. + // And it will be set at setBaseLayer timeframe + + // m_useSurfTex will be true only after the player is prepared + m_useSurfTex = false; + m_textureId = 0; +} + +// We can use this function to set the Layer to point to surface texture. +void VideoLayerAndroid::setSurfaceTexture(sp<SurfaceTexture> texture, + int textureName, bool useSurfTex) +{ + m_surfaceTexture = texture; + m_textureId = textureName; + m_useSurfTex = useSurfTex; +} + +GLuint VideoLayerAndroid::createPauseTexture() +{ + GLuint texture; + glGenTextures(1, &texture); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + GLubyte pixels[4 *3] = { + 128, 128, 128, + 128, 128, 128, + 128, 128, 128, + 128, 128, 128 + }; + glBindTexture(GL_TEXTURE_2D, texture); + GLUtils::checkGlError("glBindTexture"); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, pixels); + GLUtils::checkGlError("glTexImage2D"); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + return texture; +} + +bool VideoLayerAndroid::drawGL(SkMatrix& matrix) +{ + // Lazy allocated the paused texture. + if (!m_createdPauseTexture) { + m_pauseTextureId = createPauseTexture(); + m_createdPauseTexture = true; + } + + SkRect rect = SkRect::MakeSize(getSize()); + GLfloat surfaceMatrix[16]; + + // Draw the paused image or the Video + if (!m_surfaceTexture.get() || !m_useSurfTex) { + TransformationMatrix identity; + GLUtils::toGLMatrix(surfaceMatrix, identity); + TilesManager::instance()->shader()->drawLayerQuad(drawTransform(), rect, + m_pauseTextureId, + 0.5, true); + } else { + m_surfaceTexture->updateTexImage(); + m_surfaceTexture->getTransformMatrix(surfaceMatrix); + TilesManager::instance()->shader()->drawVideoLayerQuad(drawTransform(), + surfaceMatrix, + rect, m_textureId); + } + + return drawChildrenGL(matrix); +} + +} +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/WebCore/platform/graphics/android/VideoLayerAndroid.h b/WebCore/platform/graphics/android/VideoLayerAndroid.h new file mode 100644 index 0000000..c2a962e --- /dev/null +++ b/WebCore/platform/graphics/android/VideoLayerAndroid.h @@ -0,0 +1,74 @@ +/* + * Copyright 2011 The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef VideoLayerAndroid_h +#define VideoLayerAndroid_h + +#if USE(ACCELERATED_COMPOSITING) + +#include "GLUtils.h" +#include "LayerAndroid.h" +#include <jni.h> + +namespace android { +class SurfaceTexture; +} + +namespace WebCore { + +class VideoLayerAndroid : public LayerAndroid { + +public: + VideoLayerAndroid(); + explicit VideoLayerAndroid(const VideoLayerAndroid& layer); + + virtual bool isVideo() const { return true; } + virtual LayerAndroid* copy() const { return new VideoLayerAndroid(*this); } + + // The following 3 functions are called in UI thread only. + virtual bool drawGL(SkMatrix& matrix); + void setSurfaceTexture(sp<SurfaceTexture> texture, int textureName, bool updateTexture); + GLuint createPauseTexture(); + +private: + void init(); + // Surface texture for showing the video is actually allocated in Java side + // and passed into this native code. + GLuint m_textureId; + sp<android::SurfaceTexture> m_surfaceTexture; + bool m_useSurfTex; + + // Texture for showing the paused image will be created at native side. + // TODO: instead using a shared texture, we could make a texture pool to + // show different screen shots for different videos + static GLuint m_pauseTextureId; + static bool m_createdPauseTexture; +}; + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING) + +#endif // VideoLayerAndroid_h |