1 /* 2 * Copyright (C) 2009 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "config.h" 18 #include "GraphicsLayerAndroid.h" 19 20 #if USE(ACCELERATED_COMPOSITING) 21 22 #include "AndroidAnimation.h" 23 #include "Animation.h" 24 #include "FloatRect.h" 25 #include "GraphicsContext.h" 26 #include "Image.h" 27 #include "ImagesManager.h" 28 #include "Layer.h" 29 #include "Length.h" 30 #include "MediaLayer.h" 31 #include "PlatformBridge.h" 32 #include "PlatformGraphicsContext.h" 33 #include "RenderLayerBacking.h" 34 #include "RenderView.h" 35 #include "RotateTransformOperation.h" 36 #include "ScaleTransformOperation.h" 37 #include "ScrollableLayerAndroid.h" 38 #include "SkCanvas.h" 39 #include "SkRegion.h" 40 #include "TransformationMatrix.h" 41 #include "TranslateTransformOperation.h" 42 43 #include <cutils/log.h> 44 #include <wtf/CurrentTime.h> 45 #include <wtf/text/CString.h> 46 47 #undef LOG 48 #define LOG(...) android_printLog(ANDROID_LOG_DEBUG, "GraphicsLayer", __VA_ARGS__) 49 #define MLOG(...) android_printLog(ANDROID_LOG_DEBUG, "GraphicsLayer", __VA_ARGS__) 50 #define TLOG(...) android_printLog(ANDROID_LOG_DEBUG, "GraphicsLayer", __VA_ARGS__) 51 52 #undef LOG 53 #define LOG(...) 54 #undef MLOG 55 #define MLOG(...) 56 #undef TLOG 57 #define TLOG(...) 58 #undef LAYER_DEBUG 59 60 using namespace std; 61 62 static bool gPaused; 63 static double gPausedDelay; 64 65 namespace WebCore { 66 67 static int gDebugGraphicsLayerAndroidInstances = 0; 68 inline int GraphicsLayerAndroid::instancesCount() 69 { 70 return gDebugGraphicsLayerAndroidInstances; 71 } 72 73 static String propertyIdToString(AnimatedPropertyID property) 74 { 75 switch (property) { 76 case AnimatedPropertyWebkitTransform: 77 return "transform"; 78 case AnimatedPropertyOpacity: 79 return "opacity"; 80 case AnimatedPropertyBackgroundColor: 81 return "backgroundColor"; 82 case AnimatedPropertyInvalid: 83 ASSERT_NOT_REACHED(); 84 } 85 ASSERT_NOT_REACHED(); 86 return ""; 87 } 88 89 PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerClient* client) 90 { 91 return new GraphicsLayerAndroid(client); 92 } 93 94 SkLength convertLength(Length len) 95 { 96 SkLength length; 97 length.type = SkLength::Undefined; 98 length.value = 0; 99 if (len.type() == WebCore::Percent) { 100 length.type = SkLength::Percent; 101 length.value = len.percent(); 102 } 103 if (len.type() == WebCore::Fixed) { 104 length.type = SkLength::Fixed; 105 length.value = len.value(); 106 } 107 return length; 108 } 109 110 static RenderLayer* renderLayerFromClient(GraphicsLayerClient* client) 111 { 112 return client ? client->owningLayer() : 0; 113 } 114 115 GraphicsLayerAndroid::GraphicsLayerAndroid(GraphicsLayerClient* client) : 116 GraphicsLayer(client), 117 m_needsSyncChildren(false), 118 m_needsSyncMask(false), 119 m_needsRepaint(false), 120 m_needsNotifyClient(false), 121 m_haveContents(false), 122 m_haveImage(false), 123 m_newImage(false), 124 m_foregroundLayer(0), 125 m_foregroundClipLayer(0) 126 { 127 RenderLayer* renderLayer = renderLayerFromClient(m_client); 128 m_contentLayer = new LayerAndroid(renderLayer); 129 m_dirtyRegion.setEmpty(); 130 gDebugGraphicsLayerAndroidInstances++; 131 } 132 133 GraphicsLayerAndroid::~GraphicsLayerAndroid() 134 { 135 m_contentLayer->unref(); 136 SkSafeUnref(m_foregroundLayer); 137 SkSafeUnref(m_foregroundClipLayer); 138 gDebugGraphicsLayerAndroidInstances--; 139 } 140 141 void GraphicsLayerAndroid::setName(const String& name) 142 { 143 GraphicsLayer::setName(name); 144 } 145 146 NativeLayer GraphicsLayerAndroid::nativeLayer() const 147 { 148 LOG("(%x) nativeLayer", this); 149 return 0; 150 } 151 152 bool GraphicsLayerAndroid::setChildren(const Vector<GraphicsLayer*>& children) 153 { 154 bool childrenChanged = GraphicsLayer::setChildren(children); 155 if (childrenChanged) { 156 m_needsSyncChildren = true; 157 askForSync(); 158 } 159 160 return childrenChanged; 161 } 162 163 void GraphicsLayerAndroid::addChild(GraphicsLayer* childLayer) 164 { 165 #ifndef NDEBUG 166 const String& name = childLayer->name(); 167 LOG("(%x) addChild: %x (%s)", this, childLayer, name.latin1().data()); 168 #endif 169 GraphicsLayer::addChild(childLayer); 170 m_needsSyncChildren = true; 171 askForSync(); 172 } 173 174 void GraphicsLayerAndroid::addChildAtIndex(GraphicsLayer* childLayer, int index) 175 { 176 LOG("(%x) addChild %x AtIndex %d", this, childLayer, index); 177 GraphicsLayer::addChildAtIndex(childLayer, index); 178 m_needsSyncChildren = true; 179 askForSync(); 180 } 181 182 void GraphicsLayerAndroid::addChildBelow(GraphicsLayer* childLayer, GraphicsLayer* sibling) 183 { 184 LOG("(%x) addChild %x Below %x", this, childLayer, sibling); 185 GraphicsLayer::addChildBelow(childLayer, sibling); 186 m_needsSyncChildren = true; 187 askForSync(); 188 } 189 190 void GraphicsLayerAndroid::addChildAbove(GraphicsLayer* childLayer, GraphicsLayer* sibling) 191 { 192 LOG("(%x) addChild %x Above %x", this, childLayer, sibling); 193 GraphicsLayer::addChildAbove(childLayer, sibling); 194 m_needsSyncChildren = true; 195 askForSync(); 196 } 197 198 bool GraphicsLayerAndroid::replaceChild(GraphicsLayer* oldChild, GraphicsLayer* newChild) 199 { 200 LOG("(%x) replaceChild %x by %x", this, oldChild, newChild); 201 bool ret = GraphicsLayer::replaceChild(oldChild, newChild); 202 if (ret) { 203 m_needsSyncChildren = true; 204 askForSync(); 205 } 206 return ret; 207 } 208 209 void GraphicsLayerAndroid::removeFromParent() 210 { 211 LOG("(%x) removeFromParent()", this); 212 GraphicsLayerAndroid* parent = static_cast<GraphicsLayerAndroid*>(m_parent); 213 GraphicsLayer::removeFromParent(); 214 // Update the parent's children. 215 if (parent) { 216 parent->m_needsSyncChildren = true; 217 askForSync(); 218 } 219 } 220 221 void GraphicsLayerAndroid::updateFixedPosition() 222 { 223 RenderLayer* renderLayer = renderLayerFromClient(m_client); 224 if (!renderLayer) 225 return; 226 RenderView* view = static_cast<RenderView*>(renderLayer->renderer()); 227 228 if (!view) 229 return; 230 231 // We will need the Iframe flag in the LayerAndroid tree for fixed position 232 if (view->isRenderIFrame()) 233 m_contentLayer->setIsIframe(true); 234 // If we are a fixed position layer, just set it 235 if (view->isPositioned() && view->style()->position() == FixedPosition) { 236 // We need to get the passed CSS properties for the element 237 SkLength left, top, right, bottom; 238 left = convertLength(view->style()->left()); 239 top = convertLength(view->style()->top()); 240 right = convertLength(view->style()->right()); 241 bottom = convertLength(view->style()->bottom()); 242 243 // We also need to get the margin... 244 SkLength marginLeft, marginTop, marginRight, marginBottom; 245 marginLeft = convertLength(view->style()->marginLeft()); 246 marginTop = convertLength(view->style()->marginTop()); 247 marginRight = convertLength(view->style()->marginRight()); 248 marginBottom = convertLength(view->style()->marginBottom()); 249 250 // In order to compute the fixed element's position, we need the width 251 // and height of the element when bottom or right is defined. 252 // And here we should use the non-overflowed value, that means, the 253 // overflowed content (e.g. outset shadow) will not be counted into the 254 // width and height. 255 int w = view->width(); 256 int h = view->height(); 257 258 int paintingOffsetX = - offsetFromRenderer().width(); 259 int paintingOffsetY = - offsetFromRenderer().height(); 260 261 SkRect viewRect; 262 viewRect.set(paintingOffsetX, paintingOffsetY, paintingOffsetX + w, paintingOffsetY + h); 263 IntPoint renderLayerPos(renderLayer->x(), renderLayer->y()); 264 m_contentLayer->setFixedPosition(left, top, right, bottom, 265 marginLeft, marginTop, 266 marginRight, marginBottom, 267 renderLayerPos, 268 viewRect); 269 } 270 } 271 272 void GraphicsLayerAndroid::setPosition(const FloatPoint& point) 273 { 274 if (point == m_position) 275 return; 276 277 GraphicsLayer::setPosition(point); 278 279 #ifdef LAYER_DEBUG_2 280 LOG("(%x) setPosition(%.2f,%.2f) pos(%.2f, %.2f) anchor(%.2f,%.2f) size(%.2f, %.2f)", 281 this, point.x(), point.y(), m_position.x(), m_position.y(), 282 m_anchorPoint.x(), m_anchorPoint.y(), m_size.width(), m_size.height()); 283 #endif 284 m_contentLayer->setPosition(point.x(), point.y()); 285 askForSync(); 286 } 287 288 void GraphicsLayerAndroid::setPreserves3D(bool preserves3D) 289 { 290 if (preserves3D == m_preserves3D) 291 return; 292 293 GraphicsLayer::setPreserves3D(preserves3D); 294 m_contentLayer->setPreserves3D(preserves3D); 295 askForSync(); 296 } 297 298 void GraphicsLayerAndroid::setAnchorPoint(const FloatPoint3D& point) 299 { 300 if (point == m_anchorPoint) 301 return; 302 GraphicsLayer::setAnchorPoint(point); 303 m_contentLayer->setAnchorPoint(point.x(), point.y()); 304 m_contentLayer->setAnchorPointZ(point.z()); 305 askForSync(); 306 } 307 308 void GraphicsLayerAndroid::setSize(const FloatSize& size) 309 { 310 if (size == m_size) 311 return; 312 MLOG("(%x) setSize (%.2f,%.2f)", this, size.width(), size.height()); 313 GraphicsLayer::setSize(size); 314 315 // If it is a media layer the size may have changed as a result of the media 316 // element (e.g. plugin) gaining focus. Therefore, we must sync the size of 317 // the focus' outline so that our UI thread can draw accordingly. 318 RenderLayer* layer = renderLayerFromClient(m_client); 319 if (layer && m_contentLayer->isMedia()) { 320 RenderBox* box = layer->renderBox(); 321 int outline = box->view()->maximalOutlineSize(); 322 static_cast<MediaLayer*>(m_contentLayer)->setOutlineSize(outline); 323 LOG("Media Outline: %d %p %p %p", outline, m_client, layer, box); 324 LOG("Media Size: %g,%g", size.width(), size.height()); 325 } 326 327 m_contentLayer->setSize(size.width(), size.height()); 328 setNeedsDisplay(); 329 askForSync(); 330 } 331 332 void GraphicsLayerAndroid::setBackfaceVisibility(bool b) 333 { 334 GraphicsLayer::setBackfaceVisibility(b); 335 m_contentLayer->setBackfaceVisibility(b); 336 askForSync(); 337 } 338 339 void GraphicsLayerAndroid::setTransform(const TransformationMatrix& t) 340 { 341 if (t == m_transform) 342 return; 343 344 GraphicsLayer::setTransform(t); 345 m_contentLayer->setTransform(t); 346 askForSync(); 347 } 348 349 void GraphicsLayerAndroid::setChildrenTransform(const TransformationMatrix& t) 350 { 351 if (t == m_childrenTransform) 352 return; 353 LOG("(%x) setChildrenTransform", this); 354 355 GraphicsLayer::setChildrenTransform(t); 356 m_contentLayer->setChildrenTransform(t); 357 for (unsigned int i = 0; i < m_children.size(); i++) { 358 GraphicsLayer* layer = m_children[i]; 359 layer->setTransform(t); 360 if (layer->children().size()) 361 layer->setChildrenTransform(t); 362 } 363 askForSync(); 364 } 365 366 void GraphicsLayerAndroid::setMaskLayer(GraphicsLayer* layer) 367 { 368 if (layer == m_maskLayer) 369 return; 370 371 GraphicsLayer::setMaskLayer(layer); 372 m_needsSyncMask = true; 373 askForSync(); 374 } 375 376 void GraphicsLayerAndroid::setMasksToBounds(bool masksToBounds) 377 { 378 if (masksToBounds == m_masksToBounds) 379 return; 380 GraphicsLayer::setMasksToBounds(masksToBounds); 381 m_needsSyncMask = true; 382 askForSync(); 383 } 384 385 void GraphicsLayerAndroid::setDrawsContent(bool drawsContent) 386 { 387 if (drawsContent == m_drawsContent) 388 return; 389 GraphicsLayer::setDrawsContent(drawsContent); 390 m_contentLayer->setVisible(drawsContent); 391 if (m_drawsContent) { 392 m_haveContents = true; 393 setNeedsDisplay(); 394 } 395 askForSync(); 396 } 397 398 void GraphicsLayerAndroid::setBackgroundColor(const Color& color) 399 { 400 if (color == m_backgroundColor) 401 return; 402 LOG("(%x) setBackgroundColor", this); 403 GraphicsLayer::setBackgroundColor(color); 404 SkColor c = SkColorSetARGB(color.alpha(), color.red(), color.green(), color.blue()); 405 m_contentLayer->setBackgroundColor(c); 406 m_haveContents = true; 407 askForSync(); 408 } 409 410 void GraphicsLayerAndroid::clearBackgroundColor() 411 { 412 LOG("(%x) clearBackgroundColor", this); 413 GraphicsLayer::clearBackgroundColor(); 414 askForSync(); 415 } 416 417 void GraphicsLayerAndroid::setContentsOpaque(bool opaque) 418 { 419 if (opaque == m_contentsOpaque) 420 return; 421 LOG("(%x) setContentsOpaque (%d)", this, opaque); 422 GraphicsLayer::setContentsOpaque(opaque); 423 m_haveContents = true; 424 askForSync(); 425 } 426 427 void GraphicsLayerAndroid::setOpacity(float opacity) 428 { 429 LOG("(%x) setOpacity: %.2f", this, opacity); 430 float clampedOpacity = max(0.0f, min(opacity, 1.0f)); 431 432 if (clampedOpacity == m_opacity) 433 return; 434 435 MLOG("(%x) setFinalOpacity: %.2f=>%.2f (%.2f)", this, 436 opacity, clampedOpacity, m_opacity); 437 GraphicsLayer::setOpacity(clampedOpacity); 438 m_contentLayer->setOpacity(clampedOpacity); 439 askForSync(); 440 } 441 442 void GraphicsLayerAndroid::setNeedsDisplay() 443 { 444 LOG("(%x) setNeedsDisplay()", this); 445 FloatRect rect(0, 0, m_size.width(), m_size.height()); 446 setNeedsDisplayInRect(rect); 447 } 448 449 // Helper to set and clear the painting phase as well as auto restore the 450 // original phase. 451 class PaintingPhase { 452 public: 453 PaintingPhase(GraphicsLayer* layer) 454 : m_layer(layer) 455 , m_originalPhase(layer->paintingPhase()) {} 456 457 ~PaintingPhase() 458 { 459 m_layer->setPaintingPhase(m_originalPhase); 460 } 461 462 void set(GraphicsLayerPaintingPhase phase) 463 { 464 m_layer->setPaintingPhase(phase); 465 } 466 467 void clear(GraphicsLayerPaintingPhase phase) 468 { 469 m_layer->setPaintingPhase( 470 (GraphicsLayerPaintingPhase) (m_originalPhase & ~phase)); 471 } 472 private: 473 GraphicsLayer* m_layer; 474 GraphicsLayerPaintingPhase m_originalPhase; 475 }; 476 477 void GraphicsLayerAndroid::updateScrollingLayers() 478 { 479 #if ENABLE(ANDROID_OVERFLOW_SCROLL) 480 RenderLayer* layer = renderLayerFromClient(m_client); 481 if (!layer || !m_haveContents) 482 return; 483 bool hasOverflowScroll = m_foregroundLayer || m_contentLayer->contentIsScrollable(); 484 bool layerNeedsOverflow = layer->hasOverflowScroll(); 485 bool iframeNeedsOverflow = layer->isRootLayer() && 486 layer->renderer()->frame()->ownerRenderer() && 487 layer->renderer()->frame()->view()->hasOverflowScroll(); 488 489 if (hasOverflowScroll && (layerNeedsOverflow || iframeNeedsOverflow)) { 490 // Already has overflow layers. 491 return; 492 } 493 if (!hasOverflowScroll && !layerNeedsOverflow && !iframeNeedsOverflow) { 494 // Does not need overflow layers. 495 return; 496 } 497 if (layerNeedsOverflow || iframeNeedsOverflow) { 498 ASSERT(!hasOverflowScroll); 499 if (layerNeedsOverflow) { 500 ASSERT(!m_foregroundLayer && !m_foregroundClipLayer); 501 m_foregroundLayer = new ScrollableLayerAndroid(layer); 502 m_foregroundClipLayer = new LayerAndroid(layer); 503 m_foregroundClipLayer->setMasksToBounds(true); 504 m_foregroundClipLayer->addChild(m_foregroundLayer); 505 m_contentLayer->addChild(m_foregroundClipLayer); 506 m_contentLayer->setHasOverflowChildren(true); 507 } else { 508 ASSERT(iframeNeedsOverflow && !m_contentLayer->contentIsScrollable()); 509 // No need to copy the children as they will be removed and synced. 510 m_contentLayer->removeChildren(); 511 // Replace the content layer with a scrollable layer. 512 LayerAndroid* layer = new ScrollableLayerAndroid(*m_contentLayer); 513 m_contentLayer->unref(); 514 m_contentLayer = layer; 515 if (m_parent) { 516 // The content layer has changed so the parent needs to sync 517 // children. 518 static_cast<GraphicsLayerAndroid*>(m_parent)->m_needsSyncChildren = true; 519 } 520 } 521 // Need to rebuild our children based on the new structure. 522 m_needsSyncChildren = true; 523 } else { 524 ASSERT(hasOverflowScroll && !layerNeedsOverflow && !iframeNeedsOverflow); 525 ASSERT(m_contentLayer); 526 // Remove the foreground layers. 527 if (m_foregroundLayer) { 528 m_foregroundLayer->unref(); 529 m_foregroundLayer = 0; 530 m_foregroundClipLayer->unref(); 531 m_foregroundClipLayer = 0; 532 } 533 // No need to copy over children. 534 m_contentLayer->removeChildren(); 535 LayerAndroid* layer = new LayerAndroid(*m_contentLayer); 536 m_contentLayer->unref(); 537 m_contentLayer = layer; 538 if (m_parent) { 539 // The content layer has changed so the parent needs to sync 540 // children. 541 static_cast<GraphicsLayerAndroid*>(m_parent)->m_needsSyncChildren = true; 542 } 543 // Children are all re-parented. 544 m_needsSyncChildren = true; 545 } 546 #endif 547 } 548 549 bool GraphicsLayerAndroid::repaint() 550 { 551 LOG("(%x) repaint(), gPaused(%d) m_needsRepaint(%d) m_haveContents(%d) ", 552 this, gPaused, m_needsRepaint, m_haveContents); 553 554 if (!gPaused && m_haveContents && m_needsRepaint && !m_haveImage) { 555 // with SkPicture, we request the entire layer's content. 556 IntRect layerBounds(0, 0, m_size.width(), m_size.height()); 557 558 RenderLayer* layer = renderLayerFromClient(m_client); 559 if (!layer) 560 return false; 561 if (m_foregroundLayer) { 562 PaintingPhase phase(this); 563 // Paint the background into a separate context. 564 phase.set(GraphicsLayerPaintBackground); 565 if (!paintContext(m_contentLayer->recordContext(), layerBounds)) 566 return false; 567 568 // Construct the foreground layer and draw. 569 RenderBox* box = layer->renderBox(); 570 int outline = box->view()->maximalOutlineSize(); 571 IntRect contentsRect(0, 0, 572 box->borderLeft() + box->borderRight() + layer->scrollWidth(), 573 box->borderTop() + box->borderBottom() + layer->scrollHeight()); 574 contentsRect.inflate(outline); 575 // Update the foreground layer size. 576 m_foregroundLayer->setSize(contentsRect.width(), contentsRect.height()); 577 // Paint everything else into the main recording canvas. 578 phase.clear(GraphicsLayerPaintBackground); 579 580 // Paint at 0,0. 581 IntSize scroll = layer->scrolledContentOffset(); 582 layer->scrollToOffset(0, 0); 583 // At this point, it doesn't matter if painting failed. 584 (void) paintContext(m_foregroundLayer->recordContext(), contentsRect); 585 layer->scrollToOffset(scroll.width(), scroll.height()); 586 587 // Construct the clip layer for masking the contents. 588 IntRect clip = layer->renderer()->absoluteBoundingBoxRect(); 589 // absoluteBoundingBoxRect does not include the outline so we need 590 // to offset the position. 591 int x = box->borderLeft() + outline; 592 int y = box->borderTop() + outline; 593 int width = clip.width() - box->borderLeft() - box->borderRight(); 594 int height = clip.height() - box->borderTop() - box->borderBottom(); 595 m_foregroundClipLayer->setPosition(x, y); 596 m_foregroundClipLayer->setSize(width, height); 597 598 // Need to offset the foreground layer by the clip layer in order 599 // for the contents to be in the correct position. 600 m_foregroundLayer->setPosition(-x, -y); 601 // Set the scrollable bounds of the layer. 602 m_foregroundLayer->setScrollLimits(-x, -y, m_size.width(), m_size.height()); 603 m_foregroundLayer->markAsDirty(m_dirtyRegion); 604 m_foregroundLayer->needsRepaint(); 605 } else { 606 // If there is no contents clip, we can draw everything into one 607 // picture. 608 if (!paintContext(m_contentLayer->recordContext(), layerBounds)) 609 return false; 610 // Check for a scrollable iframe and report the scrolling 611 // limits based on the view size. 612 if (m_contentLayer->contentIsScrollable()) { 613 FrameView* view = layer->renderer()->frame()->view(); 614 static_cast<ScrollableLayerAndroid*>(m_contentLayer)->setScrollLimits( 615 m_position.x(), m_position.y(), view->layoutWidth(), view->layoutHeight()); 616 } 617 } 618 619 LOG("(%x) repaint() on (%.2f,%.2f) contentlayer(%.2f,%.2f,%.2f,%.2f)paintGraphicsLayer called!", 620 this, m_size.width(), m_size.height(), 621 m_contentLayer->getPosition().fX, 622 m_contentLayer->getPosition().fY, 623 m_contentLayer->getSize().width(), 624 m_contentLayer->getSize().height()); 625 626 m_contentLayer->markAsDirty(m_dirtyRegion); 627 m_dirtyRegion.setEmpty(); 628 m_contentLayer->needsRepaint(); 629 m_needsRepaint = false; 630 631 return true; 632 } 633 if (m_needsRepaint && m_haveImage && m_newImage) { 634 // We need to tell the GL thread that we will need to repaint the 635 // texture. Only do so if we effectively have a new image! 636 m_contentLayer->markAsDirty(m_dirtyRegion); 637 m_dirtyRegion.setEmpty(); 638 m_contentLayer->needsRepaint(); 639 m_newImage = false; 640 m_needsRepaint = false; 641 return true; 642 } 643 return false; 644 } 645 646 bool GraphicsLayerAndroid::paintContext(SkPicture* context, 647 const IntRect& rect) 648 { 649 SkAutoPictureRecord arp(context, rect.width(), rect.height()); 650 SkCanvas* canvas = arp.getRecordingCanvas(); 651 652 if (!canvas) 653 return false; 654 655 PlatformGraphicsContext platformContext(canvas, 0); 656 GraphicsContext graphicsContext(&platformContext); 657 658 paintGraphicsLayerContents(graphicsContext, rect); 659 return true; 660 } 661 662 void GraphicsLayerAndroid::setNeedsDisplayInRect(const FloatRect& rect) 663 { 664 // rect is in the render object coordinates 665 666 if (!m_haveImage && !drawsContent()) { 667 LOG("(%x) setNeedsDisplay(%.2f,%.2f,%.2f,%.2f) doesn't have content, bypass...", 668 this, rect.x(), rect.y(), rect.width(), rect.height()); 669 return; 670 } 671 672 SkRegion region; 673 region.setRect(rect.x(), rect.y(), 674 rect.x() + rect.width(), 675 rect.y() + rect.height()); 676 m_dirtyRegion.op(region, SkRegion::kUnion_Op); 677 678 m_needsRepaint = true; 679 askForSync(); 680 } 681 682 void GraphicsLayerAndroid::pauseDisplay(bool state) 683 { 684 gPaused = state; 685 if (gPaused) 686 gPausedDelay = WTF::currentTime() + 1; 687 } 688 689 bool GraphicsLayerAndroid::addAnimation(const KeyframeValueList& valueList, 690 const IntSize& boxSize, 691 const Animation* anim, 692 const String& keyframesName, 693 double beginTime) 694 { 695 if (!anim || anim->isEmptyOrZeroDuration() || valueList.size() < 2) 696 return false; 697 698 bool createdAnimations = false; 699 if (valueList.property() == AnimatedPropertyWebkitTransform) { 700 createdAnimations = createTransformAnimationsFromKeyframes(valueList, 701 anim, 702 keyframesName, 703 beginTime, 704 boxSize); 705 } else { 706 createdAnimations = createAnimationFromKeyframes(valueList, 707 anim, 708 keyframesName, 709 beginTime); 710 } 711 if (createdAnimations) 712 askForSync(); 713 return createdAnimations; 714 } 715 716 bool GraphicsLayerAndroid::createAnimationFromKeyframes(const KeyframeValueList& valueList, 717 const Animation* animation, const String& keyframesName, double beginTime) 718 { 719 bool isKeyframe = valueList.size() > 2; 720 TLOG("createAnimationFromKeyframes(%d), name(%s) beginTime(%.2f)", 721 isKeyframe, keyframesName.latin1().data(), beginTime); 722 723 switch (valueList.property()) { 724 case AnimatedPropertyInvalid: break; 725 case AnimatedPropertyWebkitTransform: break; 726 case AnimatedPropertyBackgroundColor: break; 727 case AnimatedPropertyOpacity: { 728 MLOG("ANIMATEDPROPERTYOPACITY"); 729 730 KeyframeValueList* operationsList = new KeyframeValueList(AnimatedPropertyOpacity); 731 for (unsigned int i = 0; i < valueList.size(); i++) { 732 FloatAnimationValue* originalValue = (FloatAnimationValue*)valueList.at(i); 733 PassRefPtr<TimingFunction> timingFunction(const_cast<TimingFunction*>(originalValue->timingFunction())); 734 FloatAnimationValue* value = new FloatAnimationValue(originalValue->keyTime(), 735 originalValue->value(), 736 timingFunction); 737 operationsList->insert(value); 738 } 739 740 RefPtr<AndroidOpacityAnimation> anim = AndroidOpacityAnimation::create(animation, 741 operationsList, 742 beginTime); 743 if (keyframesName.isEmpty()) 744 anim->setName(propertyIdToString(valueList.property())); 745 else 746 anim->setName(keyframesName); 747 748 m_contentLayer->addAnimation(anim.release()); 749 needsNotifyClient(); 750 return true; 751 } break; 752 } 753 return false; 754 } 755 756 void GraphicsLayerAndroid::needsNotifyClient() 757 { 758 m_needsNotifyClient = true; 759 askForSync(); 760 } 761 762 bool GraphicsLayerAndroid::createTransformAnimationsFromKeyframes(const KeyframeValueList& valueList, 763 const Animation* animation, 764 const String& keyframesName, 765 double beginTime, 766 const IntSize& boxSize) 767 { 768 ASSERT(valueList.property() == AnimatedPropertyWebkitTransform); 769 TLOG("createTransformAnimationFromKeyframes, name(%s) beginTime(%.2f)", 770 keyframesName.latin1().data(), beginTime); 771 772 KeyframeValueList* operationsList = new KeyframeValueList(AnimatedPropertyWebkitTransform); 773 for (unsigned int i = 0; i < valueList.size(); i++) { 774 TransformAnimationValue* originalValue = (TransformAnimationValue*)valueList.at(i); 775 PassRefPtr<TimingFunction> timingFunction(const_cast<TimingFunction*>(originalValue->timingFunction())); 776 TransformAnimationValue* value = new TransformAnimationValue(originalValue->keyTime(), 777 originalValue->value(), 778 timingFunction); 779 operationsList->insert(value); 780 } 781 782 RefPtr<AndroidTransformAnimation> anim = AndroidTransformAnimation::create(animation, 783 operationsList, 784 beginTime); 785 786 if (keyframesName.isEmpty()) 787 anim->setName(propertyIdToString(valueList.property())); 788 else 789 anim->setName(keyframesName); 790 791 792 m_contentLayer->addAnimation(anim.release()); 793 794 needsNotifyClient(); 795 return true; 796 } 797 798 void GraphicsLayerAndroid::removeAnimationsForProperty(AnimatedPropertyID anID) 799 { 800 TLOG("NRO removeAnimationsForProperty(%d)", anID); 801 m_contentLayer->removeAnimationsForProperty(anID); 802 askForSync(); 803 } 804 805 void GraphicsLayerAndroid::removeAnimationsForKeyframes(const String& keyframesName) 806 { 807 TLOG("NRO removeAnimationsForKeyframes(%s)", keyframesName.latin1().data()); 808 m_contentLayer->removeAnimationsForKeyframes(keyframesName); 809 askForSync(); 810 } 811 812 void GraphicsLayerAndroid::pauseAnimation(const String& keyframesName) 813 { 814 TLOG("NRO pauseAnimation(%s)", keyframesName.latin1().data()); 815 } 816 817 void GraphicsLayerAndroid::suspendAnimations(double time) 818 { 819 TLOG("NRO suspendAnimations(%.2f)", time); 820 } 821 822 void GraphicsLayerAndroid::resumeAnimations() 823 { 824 TLOG("NRO resumeAnimations()"); 825 } 826 827 void GraphicsLayerAndroid::setContentsToImage(Image* image) 828 { 829 TLOG("(%x) setContentsToImage", this, image); 830 if (image) { 831 m_haveContents = true; 832 m_haveImage = true; 833 m_newImage = true; 834 m_contentLayer->setContentsImage(image->nativeImageForCurrentFrame()); 835 } 836 if (m_haveImage && !image) 837 m_contentLayer->setContentsImage(0); 838 839 setNeedsDisplay(); 840 askForSync(); 841 } 842 843 void GraphicsLayerAndroid::setContentsToMedia(PlatformLayer* mediaLayer) 844 { 845 // Only fullscreen video on Android, so media doesn't get it's own layer. 846 // We might still have other layers though. 847 if (m_contentLayer != mediaLayer && mediaLayer) { 848 849 // TODO add a copy method to LayerAndroid to sync everything 850 // copy data from the original content layer to the new one 851 mediaLayer->setPosition(m_contentLayer->getPosition().fX, 852 m_contentLayer->getPosition().fY); 853 mediaLayer->setSize(m_contentLayer->getWidth(), m_contentLayer->getHeight()); 854 mediaLayer->setDrawTransform(*m_contentLayer->drawTransform()); 855 856 mediaLayer->ref(); 857 m_contentLayer->unref(); 858 m_contentLayer = mediaLayer; 859 860 // If the parent exists then notify it to re-sync it's children 861 if (m_parent) { 862 GraphicsLayerAndroid* parent = static_cast<GraphicsLayerAndroid*>(m_parent); 863 parent->m_needsSyncChildren = true; 864 } 865 m_needsSyncChildren = true; 866 867 setNeedsDisplay(); 868 askForSync(); 869 } 870 } 871 872 PlatformLayer* GraphicsLayerAndroid::platformLayer() const 873 { 874 LOG("platformLayer"); 875 return m_contentLayer; 876 } 877 878 #ifndef NDEBUG 879 void GraphicsLayerAndroid::setDebugBackgroundColor(const Color& color) 880 { 881 } 882 883 void GraphicsLayerAndroid::setDebugBorder(const Color& color, float borderWidth) 884 { 885 } 886 #endif 887 888 void GraphicsLayerAndroid::setZPosition(float position) 889 { 890 if (position == m_zPosition) 891 return; 892 LOG("(%x) setZPosition: %.2f", this, position); 893 GraphicsLayer::setZPosition(position); 894 askForSync(); 895 } 896 897 void GraphicsLayerAndroid::askForSync() 898 { 899 if (!m_client) 900 return; 901 902 if (m_client) 903 m_client->notifySyncRequired(this); 904 } 905 906 void GraphicsLayerAndroid::syncChildren() 907 { 908 if (m_needsSyncChildren) { 909 m_contentLayer->removeChildren(); 910 LayerAndroid* layer = m_contentLayer; 911 if (m_foregroundClipLayer) { 912 m_contentLayer->addChild(m_foregroundClipLayer); 913 // Use the scrollable content layer as the parent of the children so 914 // that they move with the content. 915 layer = m_foregroundLayer; 916 layer->removeChildren(); 917 } 918 for (unsigned int i = 0; i < m_children.size(); i++) 919 layer->addChild(m_children[i]->platformLayer()); 920 m_needsSyncChildren = false; 921 } 922 } 923 924 void GraphicsLayerAndroid::syncMask() 925 { 926 if (m_needsSyncMask) { 927 if (m_maskLayer) { 928 LayerAndroid* mask = m_maskLayer->platformLayer(); 929 m_contentLayer->setMaskLayer(mask); 930 } else 931 m_contentLayer->setMaskLayer(0); 932 933 m_contentLayer->setMasksToBounds(m_masksToBounds); 934 m_needsSyncMask = false; 935 } 936 } 937 938 void GraphicsLayerAndroid::syncCompositingState() 939 { 940 for (unsigned int i = 0; i < m_children.size(); i++) 941 m_children[i]->syncCompositingState(); 942 943 updateScrollingLayers(); 944 updateFixedPosition(); 945 syncChildren(); 946 syncMask(); 947 948 if (!gPaused || WTF::currentTime() >= gPausedDelay) 949 repaint(); 950 } 951 952 void GraphicsLayerAndroid::notifyClientAnimationStarted() 953 { 954 for (unsigned int i = 0; i < m_children.size(); i++) 955 static_cast<GraphicsLayerAndroid*>(m_children[i])->notifyClientAnimationStarted(); 956 957 if (m_needsNotifyClient) { 958 if (client()) 959 client()->notifyAnimationStarted(this, WTF::currentTime()); 960 m_needsNotifyClient = false; 961 } 962 } 963 964 } // namespace WebCore 965 966 #endif // USE(ACCELERATED_COMPOSITING) 967