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 #define LOG_TAG "GraphicsLayerAndroid" 18 #define LOG_NDEBUG 1 19 20 #include "config.h" 21 #include "GraphicsLayerAndroid.h" 22 23 #if USE(ACCELERATED_COMPOSITING) 24 25 #include "AndroidAnimation.h" 26 #include "AndroidLog.h" 27 #include "Animation.h" 28 #include "BaseLayerAndroid.h" 29 #include "CachedImage.h" 30 #include "CanvasLayer.h" 31 #include "FixedBackgroundLayerAndroid.h" 32 #include "FixedPositioning.h" 33 #include "FloatRect.h" 34 #include "GraphicsContext.h" 35 #include "IFrameContentLayerAndroid.h" 36 #include "IFrameLayerAndroid.h" 37 #include "Image.h" 38 #include "ImagesManager.h" 39 #include "Layer.h" 40 #include "LayerAndroid.h" 41 #include "Length.h" 42 #include "MediaLayer.h" 43 #include "PictureLayerContent.h" 44 #include "PicturePileLayerContent.h" 45 #include "PlatformBridge.h" 46 #include "PlatformGraphicsContextSkia.h" 47 #include "RenderLayerBacking.h" 48 #include "RenderView.h" 49 #include "RotateTransformOperation.h" 50 #include "ScaleTransformOperation.h" 51 #include "ScrollableLayerAndroid.h" 52 #include "SkCanvas.h" 53 #include "SkRegion.h" 54 #include "StyleCachedImage.h" 55 #include "TransformationMatrix.h" 56 #include "TranslateTransformOperation.h" 57 58 #include <wtf/CurrentTime.h> 59 #include <wtf/text/CString.h> 60 61 using namespace std; 62 63 static bool gPaused; 64 static double gPausedDelay; 65 66 namespace WebCore { 67 68 static int gDebugGraphicsLayerAndroidInstances = 0; 69 inline int GraphicsLayerAndroid::instancesCount() 70 { 71 return gDebugGraphicsLayerAndroidInstances; 72 } 73 74 static String propertyIdToString(AnimatedPropertyID property) 75 { 76 switch (property) { 77 case AnimatedPropertyWebkitTransform: 78 return "transform"; 79 case AnimatedPropertyOpacity: 80 return "opacity"; 81 case AnimatedPropertyBackgroundColor: 82 return "backgroundColor"; 83 case AnimatedPropertyInvalid: 84 ASSERT_NOT_REACHED(); 85 } 86 ASSERT_NOT_REACHED(); 87 return ""; 88 } 89 90 PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerClient* client) 91 { 92 return new GraphicsLayerAndroid(client); 93 } 94 95 static RenderLayer* renderLayerFromClient(GraphicsLayerClient* client) 96 { 97 return client ? client->owningLayer() : 0; 98 } 99 100 GraphicsLayerAndroid::GraphicsLayerAndroid(GraphicsLayerClient* client) : 101 GraphicsLayer(client), 102 m_needsSyncChildren(false), 103 m_needsSyncMask(false), 104 m_needsRepaint(false), 105 m_needsNotifyClient(false), 106 m_haveContents(false), 107 m_newImage(false), 108 m_image(0), 109 m_fixedBackgroundLayer(0), 110 m_foregroundLayer(0), 111 m_foregroundClipLayer(0) 112 { 113 RenderLayer* renderLayer = renderLayerFromClient(m_client); 114 if (renderLayer && renderLayer->renderer()->isCanvas()) { 115 m_contentLayer = new CanvasLayer(renderLayer, 116 static_cast<HTMLCanvasElement*>(renderLayer->renderer()->node())); 117 } else 118 m_contentLayer = new LayerAndroid(renderLayer); 119 gDebugGraphicsLayerAndroidInstances++; 120 } 121 122 GraphicsLayerAndroid::~GraphicsLayerAndroid() 123 { 124 if (m_image) 125 m_image->deref(); 126 127 SkSafeUnref(m_contentLayer); 128 SkSafeUnref(m_fixedBackgroundLayer); 129 SkSafeUnref(m_foregroundLayer); 130 SkSafeUnref(m_foregroundClipLayer); 131 gDebugGraphicsLayerAndroidInstances--; 132 } 133 134 void GraphicsLayerAndroid::setName(const String& name) 135 { 136 GraphicsLayer::setName(name); 137 } 138 139 NativeLayer GraphicsLayerAndroid::nativeLayer() const 140 { 141 ALOGV("(%x) nativeLayer", this); 142 return 0; 143 } 144 145 bool GraphicsLayerAndroid::setChildren(const Vector<GraphicsLayer*>& children) 146 { 147 bool childrenChanged = GraphicsLayer::setChildren(children); 148 if (childrenChanged) { 149 m_needsSyncChildren = true; 150 askForSync(); 151 } 152 153 return childrenChanged; 154 } 155 156 void GraphicsLayerAndroid::addChild(GraphicsLayer* childLayer) 157 { 158 #ifndef NDEBUG 159 const String& name = childLayer->name(); 160 ALOGV("(%x) addChild: %x (%s)", this, childLayer, name.ascii().data()); 161 #endif 162 GraphicsLayer::addChild(childLayer); 163 m_needsSyncChildren = true; 164 askForSync(); 165 } 166 167 void GraphicsLayerAndroid::addChildAtIndex(GraphicsLayer* childLayer, int index) 168 { 169 ALOGV("(%x) addChild %x AtIndex %d", this, childLayer, index); 170 GraphicsLayer::addChildAtIndex(childLayer, index); 171 m_needsSyncChildren = true; 172 askForSync(); 173 } 174 175 void GraphicsLayerAndroid::addChildBelow(GraphicsLayer* childLayer, GraphicsLayer* sibling) 176 { 177 ALOGV("(%x) addChild %x Below %x", this, childLayer, sibling); 178 GraphicsLayer::addChildBelow(childLayer, sibling); 179 m_needsSyncChildren = true; 180 askForSync(); 181 } 182 183 void GraphicsLayerAndroid::addChildAbove(GraphicsLayer* childLayer, GraphicsLayer* sibling) 184 { 185 ALOGV("(%x) addChild %x Above %x", this, childLayer, sibling); 186 GraphicsLayer::addChildAbove(childLayer, sibling); 187 m_needsSyncChildren = true; 188 askForSync(); 189 } 190 191 bool GraphicsLayerAndroid::replaceChild(GraphicsLayer* oldChild, GraphicsLayer* newChild) 192 { 193 ALOGV("(%x) replaceChild %x by %x", this, oldChild, newChild); 194 bool ret = GraphicsLayer::replaceChild(oldChild, newChild); 195 if (ret) { 196 m_needsSyncChildren = true; 197 askForSync(); 198 } 199 return ret; 200 } 201 202 void GraphicsLayerAndroid::setReplicatedLayer(GraphicsLayer* layer) 203 { 204 GraphicsLayer::setReplicatedLayer(layer); 205 if (m_replicatedLayer) { 206 GraphicsLayerAndroid* graphicsLayer = static_cast<GraphicsLayerAndroid*>(m_replicatedLayer); 207 if (graphicsLayer->m_contentLayer) 208 graphicsLayer->m_contentLayer->setReplicatedLayer(m_contentLayer); 209 if (maskLayer()) { 210 GraphicsLayerAndroid* maskLayer = static_cast<GraphicsLayerAndroid*>(GraphicsLayer::maskLayer()); 211 m_contentLayer->setMaskLayer(maskLayer->m_contentLayer); 212 } 213 m_contentLayer->setReplicatedLayerPosition(replicatedLayerPosition()); 214 askForSync(); 215 } 216 } 217 218 void GraphicsLayerAndroid::removeFromParent() 219 { 220 ALOGV("(%x) removeFromParent()", this); 221 GraphicsLayerAndroid* parent = static_cast<GraphicsLayerAndroid*>(m_parent); 222 GraphicsLayer::removeFromParent(); 223 // Update the parent's children. 224 if (parent) { 225 parent->m_needsSyncChildren = true; 226 askForSync(); 227 } 228 } 229 230 void GraphicsLayerAndroid::updatePositionedLayers() 231 { 232 RenderLayer* renderLayer = renderLayerFromClient(m_client); 233 if (!renderLayer) 234 return; 235 RenderView* view = static_cast<RenderView*>(renderLayer->renderer()); 236 237 if (!view) 238 return; 239 240 // We will need the Iframe flag in the LayerAndroid tree for fixed position 241 if (view->isRenderIFrame() && !m_contentLayer->isIFrame()) { 242 LayerAndroid* layer = new IFrameLayerAndroid(*m_contentLayer); 243 m_contentLayer->unref(); 244 m_contentLayer = layer; 245 } 246 247 // If we are a fixed position layer, just set it 248 if (view->isPositioned() && view->style()->position() == FixedPosition) { 249 m_contentLayer->setAbsolutePosition(false); 250 // We need to get the passed CSS properties for the element 251 SkLength left, top, right, bottom; 252 left = SkLength::convertLength(view->style()->left()); 253 top = SkLength::convertLength(view->style()->top()); 254 right = SkLength::convertLength(view->style()->right()); 255 bottom = SkLength::convertLength(view->style()->bottom()); 256 257 // We also need to get the margin... 258 SkLength marginLeft, marginTop, marginRight, marginBottom; 259 marginLeft = SkLength::convertLength(view->style()->marginLeft()); 260 marginTop = SkLength::convertLength(view->style()->marginTop()); 261 marginRight = SkLength::convertLength(view->style()->marginRight()); 262 marginBottom = SkLength::convertLength(view->style()->marginBottom()); 263 264 // In order to compute the fixed element's position, we need the width 265 // and height of the element when bottom or right is defined. 266 // And here we should use the non-overflowed value, that means, the 267 // overflowed content (e.g. outset shadow) will not be counted into the 268 // width and height. 269 int w = view->width(); 270 int h = view->height(); 271 272 int paintingOffsetX = - offsetFromRenderer().width(); 273 int paintingOffsetY = - offsetFromRenderer().height(); 274 275 SkRect viewRect; 276 viewRect.set(paintingOffsetX, paintingOffsetY, paintingOffsetX + w, paintingOffsetY + h); 277 IntPoint renderLayerPos(position().x(), position().y()); 278 279 FixedPositioning* fixedPosition = m_contentLayer->fixedPosition(); 280 if (!fixedPosition) { 281 fixedPosition = new FixedPositioning(); 282 m_contentLayer->setFixedPosition(fixedPosition); 283 } 284 285 fixedPosition->setFixedPosition(left, top, right, bottom, 286 marginLeft, marginTop, 287 marginRight, marginBottom, 288 renderLayerPos, 289 viewRect); 290 } else if (view->isPositioned() && view->style()->position() == AbsolutePosition) { 291 m_contentLayer->setAbsolutePosition(true); 292 } else { 293 m_contentLayer->setFixedPosition(0); 294 m_contentLayer->setAbsolutePosition(false); 295 } 296 } 297 298 void GraphicsLayerAndroid::setPosition(const FloatPoint& point) 299 { 300 if (point == m_position) 301 return; 302 303 GraphicsLayer::setPosition(point); 304 305 ALOGV("(%x) setPosition(%.2f,%.2f) pos(%.2f, %.2f) anchor(%.2f,%.2f) size(%.2f, %.2f)", 306 this, point.x(), point.y(), m_position.x(), m_position.y(), 307 m_anchorPoint.x(), m_anchorPoint.y(), m_size.width(), m_size.height()); 308 309 m_contentLayer->setPosition(point.x(), point.y()); 310 askForSync(); 311 } 312 313 void GraphicsLayerAndroid::setPreserves3D(bool preserves3D) 314 { 315 if (preserves3D == m_preserves3D) 316 return; 317 318 GraphicsLayer::setPreserves3D(preserves3D); 319 m_contentLayer->setPreserves3D(preserves3D); 320 askForSync(); 321 } 322 323 void GraphicsLayerAndroid::setAnchorPoint(const FloatPoint3D& point) 324 { 325 if (point == m_anchorPoint) 326 return; 327 GraphicsLayer::setAnchorPoint(point); 328 m_contentLayer->setAnchorPoint(point.x(), point.y()); 329 m_contentLayer->setAnchorPointZ(point.z()); 330 askForSync(); 331 } 332 333 void GraphicsLayerAndroid::setSize(const FloatSize& size) 334 { 335 if (size == m_size) 336 return; 337 ALOGV("(%x) layer %d setSize (%.2f,%.2f)", this, 338 m_contentLayer->uniqueId(), size.width(), size.height()); 339 GraphicsLayer::setSize(size); 340 341 // If it is a media layer the size may have changed as a result of the media 342 // element (e.g. plugin) gaining focus. Therefore, we must sync the size of 343 // the focus' outline so that our UI thread can draw accordingly. 344 RenderLayer* layer = renderLayerFromClient(m_client); 345 if (layer && m_contentLayer->isMedia()) { 346 RenderBox* box = layer->renderBox(); 347 int outline = box->view()->maximalOutlineSize(); 348 static_cast<MediaLayer*>(m_contentLayer)->setOutlineSize(outline); 349 ALOGV("Media Outline: %d %p %p %p", outline, m_client, layer, box); 350 ALOGV("Media Size: %g,%g", size.width(), size.height()); 351 } 352 353 m_contentLayer->setSize(size.width(), size.height()); 354 setNeedsDisplay(); 355 askForSync(); 356 } 357 358 void GraphicsLayerAndroid::setBackfaceVisibility(bool b) 359 { 360 if (b == m_backfaceVisibility) 361 return; 362 363 GraphicsLayer::setBackfaceVisibility(b); 364 m_contentLayer->setBackfaceVisibility(b); 365 askForSync(); 366 } 367 368 void GraphicsLayerAndroid::setTransform(const TransformationMatrix& t) 369 { 370 if (t == m_transform) 371 return; 372 373 GraphicsLayer::setTransform(t); 374 m_contentLayer->setTransform(t); 375 askForSync(); 376 } 377 378 void GraphicsLayerAndroid::setChildrenTransform(const TransformationMatrix& t) 379 { 380 if (t == m_childrenTransform) 381 return; 382 ALOGV("(%x) setChildrenTransform", this); 383 384 GraphicsLayer::setChildrenTransform(t); 385 m_contentLayer->setChildrenTransform(t); 386 for (unsigned int i = 0; i < m_children.size(); i++) { 387 GraphicsLayer* layer = m_children[i]; 388 layer->setTransform(t); 389 if (layer->children().size()) 390 layer->setChildrenTransform(t); 391 } 392 askForSync(); 393 } 394 395 void GraphicsLayerAndroid::setMaskLayer(GraphicsLayer* layer) 396 { 397 if (layer == m_maskLayer) 398 return; 399 400 GraphicsLayer::setMaskLayer(layer); 401 m_needsSyncMask = true; 402 askForSync(); 403 } 404 405 void GraphicsLayerAndroid::setMasksToBounds(bool masksToBounds) 406 { 407 if (masksToBounds == m_masksToBounds) 408 return; 409 GraphicsLayer::setMasksToBounds(masksToBounds); 410 m_needsSyncMask = true; 411 askForSync(); 412 } 413 414 void GraphicsLayerAndroid::setDrawsContent(bool drawsContent) 415 { 416 if (drawsContent == m_drawsContent) 417 return; 418 GraphicsLayer::setDrawsContent(drawsContent); 419 m_contentLayer->setVisible(drawsContent); 420 if (m_drawsContent) { 421 m_haveContents = true; 422 setNeedsDisplay(); 423 } 424 askForSync(); 425 } 426 427 void GraphicsLayerAndroid::setBackgroundColor(const Color& color) 428 { 429 if (color == m_backgroundColor && m_backgroundColorSet) 430 return; 431 ALOGV("(%x) setBackgroundColor", this); 432 GraphicsLayer::setBackgroundColor(color); 433 SkColor c = SkColorSetARGB(color.alpha(), color.red(), color.green(), color.blue()); 434 m_contentLayer->setBackgroundColor(c); 435 m_haveContents = true; 436 askForSync(); 437 } 438 439 void GraphicsLayerAndroid::clearBackgroundColor() 440 { 441 if (!m_backgroundColorSet) 442 return; 443 444 ALOGV("(%x) clearBackgroundColor", this); 445 GraphicsLayer::clearBackgroundColor(); 446 askForSync(); 447 } 448 449 void GraphicsLayerAndroid::setContentsOpaque(bool opaque) 450 { 451 if (opaque == m_contentsOpaque) 452 return; 453 ALOGV("(%x) setContentsOpaque (%d)", this, opaque); 454 GraphicsLayer::setContentsOpaque(opaque); 455 m_haveContents = true; 456 askForSync(); 457 } 458 459 void GraphicsLayerAndroid::setOpacity(float opacity) 460 { 461 ALOGV("(%x) setOpacity: %.2f", this, opacity); 462 float clampedOpacity = max(0.0f, min(opacity, 1.0f)); 463 464 if (clampedOpacity == m_opacity) 465 return; 466 467 ALOGV("(%x) setFinalOpacity: %.2f=>%.2f (%.2f)", this, 468 opacity, clampedOpacity, m_opacity); 469 GraphicsLayer::setOpacity(clampedOpacity); 470 m_contentLayer->setOpacity(clampedOpacity); 471 askForSync(); 472 } 473 474 void GraphicsLayerAndroid::setNeedsDisplay() 475 { 476 ALOGV("(%x) setNeedsDisplay()", this); 477 FloatRect rect(0, 0, m_size.width(), m_size.height()); 478 setNeedsDisplayInRect(rect); 479 } 480 481 // Helper to set and clear the painting phase as well as auto restore the 482 // original phase. 483 class PaintingPhase { 484 public: 485 PaintingPhase(GraphicsLayer* layer) 486 : m_layer(layer) 487 , m_originalPhase(layer->paintingPhase()) {} 488 489 ~PaintingPhase() 490 { 491 m_layer->setPaintingPhase(m_originalPhase); 492 } 493 494 void set(GraphicsLayerPaintingPhase phase) 495 { 496 m_layer->setPaintingPhase(phase); 497 } 498 499 void clear(GraphicsLayerPaintingPhase phase) 500 { 501 m_layer->setPaintingPhase( 502 (GraphicsLayerPaintingPhase) (m_originalPhase & ~phase)); 503 } 504 private: 505 GraphicsLayer* m_layer; 506 GraphicsLayerPaintingPhase m_originalPhase; 507 }; 508 509 void GraphicsLayerAndroid::updateScrollingLayers() 510 { 511 #if ENABLE(ANDROID_OVERFLOW_SCROLL) 512 RenderLayer* layer = renderLayerFromClient(m_client); 513 if (!layer || !m_haveContents) 514 return; 515 bool hasOverflowScroll = m_foregroundLayer || m_contentLayer->contentIsScrollable(); 516 bool layerNeedsOverflow = layer->hasOverflowScroll(); 517 bool iframeNeedsOverflow = layer->isRootLayer() && 518 layer->renderer()->frame()->ownerRenderer() && 519 layer->renderer()->frame()->view()->hasOverflowScroll(); 520 521 if (hasOverflowScroll && (layerNeedsOverflow || iframeNeedsOverflow)) { 522 // Already has overflow layers. 523 return; 524 } 525 if (!hasOverflowScroll && !layerNeedsOverflow && !iframeNeedsOverflow) { 526 // Does not need overflow layers. 527 return; 528 } 529 if (layerNeedsOverflow || iframeNeedsOverflow) { 530 ASSERT(!hasOverflowScroll); 531 if (layerNeedsOverflow) { 532 ASSERT(!m_foregroundLayer && !m_foregroundClipLayer); 533 m_foregroundLayer = new ScrollableLayerAndroid(layer); 534 m_foregroundLayer->setIntrinsicallyComposited(true); 535 536 m_foregroundClipLayer = new LayerAndroid(layer); 537 m_foregroundClipLayer->setMasksToBounds(true); 538 m_foregroundClipLayer->addChild(m_foregroundLayer); 539 m_contentLayer->addChild(m_foregroundClipLayer); 540 m_contentLayer->setHasOverflowChildren(true); 541 } else { 542 ASSERT(iframeNeedsOverflow && !m_contentLayer->contentIsScrollable()); 543 // No need to copy the children as they will be removed and synced. 544 m_contentLayer->removeChildren(); 545 // Replace the content layer with a scrollable layer. 546 LayerAndroid* layer = new IFrameContentLayerAndroid(*m_contentLayer); 547 m_contentLayer->unref(); 548 m_contentLayer = layer; 549 if (m_parent) { 550 // The content layer has changed so the parent needs to sync 551 // children. 552 static_cast<GraphicsLayerAndroid*>(m_parent)->m_needsSyncChildren = true; 553 } 554 } 555 // Need to rebuild our children based on the new structure. 556 m_needsSyncChildren = true; 557 } else if (!m_contentLayer->isFixedBackground()) { 558 ASSERT(hasOverflowScroll && !layerNeedsOverflow && !iframeNeedsOverflow); 559 ASSERT(m_contentLayer); 560 // Remove the foreground layers. 561 if (m_foregroundLayer) { 562 m_foregroundLayer->unref(); 563 m_foregroundLayer = 0; 564 m_foregroundClipLayer->unref(); 565 m_foregroundClipLayer = 0; 566 } 567 // No need to copy over children. 568 m_contentLayer->removeChildren(); 569 LayerAndroid* layer = new LayerAndroid(*m_contentLayer); 570 m_contentLayer->unref(); 571 m_contentLayer = layer; 572 if (m_parent) { 573 // The content layer has changed so the parent needs to sync 574 // children. 575 static_cast<GraphicsLayerAndroid*>(m_parent)->m_needsSyncChildren = true; 576 } 577 // Children are all re-parented. 578 m_needsSyncChildren = true; 579 } 580 #endif 581 } 582 583 void GraphicsLayerAndroid::updateFixedBackgroundLayers() { 584 RenderLayer* renderLayer = renderLayerFromClient(m_client); 585 if (!renderLayer) 586 return; 587 RenderView* view = static_cast<RenderView*>(renderLayer->renderer()); 588 if (!view) 589 return; 590 if (view->isBody()) // body element is already handled 591 return; 592 if (!view->style()->hasFixedBackgroundImage()) 593 return; 594 if (view->isRenderIFrame()) // not supported 595 return; 596 597 Image* image = FixedBackgroundImageLayerAndroid::GetCachedImage(view->style()); 598 if (!image) 599 return; 600 601 if (image->width() == 1 && image->height() == 1) 602 return; 603 604 SkSafeUnref(m_foregroundClipLayer); 605 SkSafeUnref(m_fixedBackgroundLayer); 606 SkSafeUnref(m_foregroundLayer); 607 608 // we will have: 609 // m_contentLayer 610 // \- m_foregroundClipLayer 611 // \- m_fixedBackgroundLayer 612 // \- m_foregroundLayer 613 614 // use the background image and create a layer for it 615 // the layer will be fixed positioned. 616 617 m_fixedBackgroundLayer = new FixedBackgroundImageLayerAndroid(view->style(), 618 view->width(), 619 view->height()); 620 621 Color color = view->style()->visitedDependentColor(CSSPropertyBackgroundColor); 622 SkColor skiaColor = SkColorSetARGB(color.alpha(), 623 color.red(), 624 color.green(), 625 color.blue()); 626 m_fixedBackgroundLayer->setBackgroundColor(skiaColor); 627 628 // We need to clip the background image to the bounds of the original element 629 m_foregroundClipLayer = new LayerAndroid(renderLayer); 630 m_foregroundClipLayer->setMasksToBounds(true); 631 m_foregroundClipLayer->addChild(m_fixedBackgroundLayer); 632 633 // We then want to display the content above the image background; webkit 634 // allow to paint background and foreground separately. For now, we'll create 635 // two layers; the one containing the background will be painted *without* the 636 // background image (but with the decorations, e.g. border) 637 m_foregroundLayer = new LayerAndroid(renderLayer); 638 m_foregroundLayer->setIntrinsicallyComposited(true); 639 640 // Finally, let's assemble all the layers under a FixedBackgroundLayerAndroid layer 641 if (!m_contentLayer->isFixedBackground()) { 642 m_contentLayer->removeChildren(); 643 LayerAndroid* layer = new FixedBackgroundLayerAndroid(*m_contentLayer); 644 m_contentLayer->unref(); 645 m_contentLayer = layer; 646 } 647 648 if (m_parent) { 649 // The content layer has changed so the parent needs to sync 650 // children. 651 static_cast<GraphicsLayerAndroid*>(m_parent)->m_needsSyncChildren = true; 652 } 653 // Children are all re-parented. 654 m_needsSyncChildren = true; 655 656 setNeedsDisplay(); 657 askForSync(); 658 } 659 660 void GraphicsLayerAndroid::updateScrollOffset() { 661 RenderLayer* layer = renderLayerFromClient(m_client); 662 if (!layer || !(m_foregroundLayer || m_contentLayer->contentIsScrollable())) 663 return; 664 if (m_foregroundLayer) { 665 IntSize scroll = layer->scrolledContentOffset(); 666 m_foregroundLayer->setScrollOffset(IntPoint(scroll.width(), scroll.height())); 667 } else if (m_contentLayer->isIFrameContent()) { 668 IntPoint p(layer->renderer()->frame()->view()->scrollX(), 669 layer->renderer()->frame()->view()->scrollY()); 670 static_cast<IFrameContentLayerAndroid*>(m_contentLayer)->setIFrameScrollOffset(p); 671 } 672 askForSync(); 673 } 674 675 static void setScrollLimits(ScrollableLayerAndroid* scrollableLayer, RenderLayer* renderLayer) 676 { 677 RenderBox* box = renderLayer->renderBox(); 678 scrollableLayer->setScrollLimits(0, 0, 679 renderLayer->scrollWidth() - box->clientWidth(), 680 renderLayer->scrollHeight() - box->clientHeight()); 681 } 682 683 bool GraphicsLayerAndroid::repaint() 684 { 685 ALOGV("(%x) repaint(), gPaused(%d) m_needsRepaint(%d) m_haveContents(%d) ", 686 this, gPaused, m_needsRepaint, m_haveContents); 687 688 if (!gPaused && m_haveContents && m_needsRepaint && !m_image) { 689 // with SkPicture, we request the entire layer's content. 690 IntRect layerBounds(0, 0, m_size.width(), m_size.height()); 691 692 RenderLayer* layer = renderLayerFromClient(m_client); 693 if (!layer) 694 return false; 695 if (m_foregroundLayer && !m_contentLayer->isFixedBackground()) { 696 PaintingPhase phase(this); 697 // Paint the background into a separate context. 698 phase.set(GraphicsLayerPaintBackground); 699 if (!paintContext(m_contentLayer, m_contentLayerContent)) 700 return false; 701 702 // Construct the foreground layer and draw. 703 RenderBox* box = layer->renderBox(); 704 int outline = box->view()->maximalOutlineSize(); 705 IntRect contentsRect(0, 0, 706 box->borderLeft() + box->borderRight() + layer->scrollWidth() 707 + layer->verticalScrollbarWidth(), 708 box->borderTop() + box->borderBottom() + layer->scrollHeight() 709 + layer->horizontalScrollbarHeight()); 710 contentsRect.inflate(outline); 711 // Update the foreground layer size. 712 m_foregroundLayer->setSize(contentsRect.width(), contentsRect.height()); 713 // Paint everything else into the main recording canvas. 714 phase.clear(GraphicsLayerPaintBackground); 715 716 // Invalidate the entire layer for now, as webkit will only send the 717 // setNeedsDisplayInRect() for the visible (clipped) scrollable area, 718 // offsetting the invals by the scroll position would not be enough. 719 // TODO: have webkit send us invals even for non visible area 720 m_foregroundLayerContent.invalidate(IntRect(0, 0, contentsRect.width(), contentsRect.height())); 721 722 // Paint at 0,0. 723 IntSize scroll = layer->scrolledContentOffset(); 724 layer->scrollToOffset(0, 0); 725 // At this point, it doesn't matter if painting failed. 726 (void) paintContext(m_foregroundLayer, m_foregroundLayerContent); 727 layer->scrollToOffset(scroll.width(), scroll.height()); 728 729 // Construct the clip layer for masking the contents. 730 IntRect clip = layer->renderer()->absoluteBoundingBoxRect(); 731 // absoluteBoundingBoxRect does not include the outline so we need 732 // to offset the position. 733 int x = box->borderLeft() + outline; 734 int y = box->borderTop() + outline; 735 int width = clip.width() - box->borderLeft() - box->borderRight(); 736 int height = clip.height() - box->borderTop() - box->borderBottom(); 737 m_foregroundClipLayer->setPosition(x, y); 738 m_foregroundClipLayer->setSize(width, height); 739 740 int rtlOffset = 0; // LTR uses no offset. 741 if (!layer->renderer()->style()->isLeftToRightDirection()) 742 rtlOffset = layer->scrollWidth() - width; // Scroll all the way right. 743 m_foregroundLayer->setScrollOffset(IntPoint(scroll.width() + rtlOffset, 744 scroll.height())); 745 // Need to offset the foreground layer by the clip layer in order 746 // for the contents to be in the correct position. 747 m_foregroundLayer->setPosition(-x, -y); 748 // Set the scrollable bounds of the layer. 749 setScrollLimits(static_cast<ScrollableLayerAndroid*>(m_foregroundLayer), layer); 750 751 m_foregroundLayer->markAsDirty(m_foregroundLayerContent.dirtyRegion()); 752 m_foregroundLayerContent.dirtyRegion().setEmpty(); 753 } else if (m_contentLayer->isFixedBackground()) { 754 SkPicture* picture = new SkPicture(); 755 SkCanvas* canvas = picture->beginRecording(layerBounds.width(), 756 layerBounds.height(), 0); 757 if (canvas) { 758 PaintingPhase phase(this); 759 PlatformGraphicsContextSkia platformContext(canvas); 760 GraphicsContext graphicsContext(&platformContext); 761 762 // Paint the background (without the fixed image)... 763 phase.set(GraphicsLayerPaintBackgroundDecorations); 764 paintGraphicsLayerContents(graphicsContext, layerBounds); 765 phase.clear(GraphicsLayerPaintBackgroundDecorations); 766 767 // Paint the foreground... 768 phase.set(GraphicsLayerPaintForeground); 769 paintGraphicsLayerContents(graphicsContext, layerBounds); 770 picture->endRecording(); 771 772 // Now set the content for that layer. 773 PictureLayerContent* layerContent = new PictureLayerContent(picture); 774 m_foregroundLayer->setContent(layerContent); 775 SkSafeUnref(layerContent); 776 } 777 SkSafeUnref(picture); 778 779 m_foregroundLayer->setSize(layerBounds.width(), layerBounds.height()); 780 m_foregroundClipLayer->setPosition(layerBounds.x(), layerBounds.y()); 781 m_foregroundClipLayer->setSize(layerBounds.width(), layerBounds.height()); 782 } else { 783 784 // If we are replicated, paint the mask 785 if (isReplicated()) { 786 GraphicsLayerAndroid* replicatedLayer = static_cast<GraphicsLayerAndroid*>(replicaLayer()); 787 if (replicatedLayer->maskLayer()) { 788 GraphicsLayerAndroid* mask = static_cast<GraphicsLayerAndroid*>(replicatedLayer->maskLayer()); 789 mask->paintContext(mask->m_contentLayer, mask->m_contentLayerContent); 790 } 791 } 792 793 // If there is no contents clip, we can draw everything into one 794 // picture. 795 bool painting = paintContext(m_contentLayer, m_contentLayerContent); 796 if (!painting) 797 return false; 798 // Check for a scrollable iframe and report the scrolling 799 // limits based on the view size. 800 if (m_contentLayer->isIFrameContent()) { 801 FrameView* view = layer->renderer()->frame()->view(); 802 setScrollLimits(static_cast<ScrollableLayerAndroid*>(m_contentLayer), layer); 803 ALOGV("setScrollLimits(%.2f, %.2f, w: %d h: %d) layer %d, frame scroll position is %d, %d", 804 m_position.x(), m_position.y(), view->layoutWidth(), view->layoutHeight(), 805 m_contentLayer->uniqueId(), view->scrollX(), view->scrollY()); 806 } 807 } 808 809 ALOGV("(%x) repaint() on (%.2f,%.2f) contentlayer(%.2f,%.2f,%.2f,%.2f)paintGraphicsLayer called!", 810 this, m_size.width(), m_size.height(), 811 m_contentLayer->getPosition().fX, 812 m_contentLayer->getPosition().fY, 813 m_contentLayer->getSize().width(), 814 m_contentLayer->getSize().height()); 815 816 m_contentLayer->markAsDirty(m_contentLayerContent.dirtyRegion()); 817 m_contentLayerContent.dirtyRegion().setEmpty(); 818 m_needsRepaint = false; 819 820 return true; 821 } 822 if (m_needsRepaint && m_image && m_newImage) { 823 // We need to tell the GL thread that we will need to repaint the 824 // texture. Only do so if we effectively have a new image! 825 m_contentLayer->markAsDirty(m_contentLayerContent.dirtyRegion()); 826 m_contentLayerContent.dirtyRegion().setEmpty(); 827 m_newImage = false; 828 m_needsRepaint = false; 829 return true; 830 } 831 return false; 832 } 833 834 void GraphicsLayerAndroid::paintContents(GraphicsContext* gc, IntRect& dirty) 835 { 836 paintGraphicsLayerContents(*gc, dirty); 837 } 838 839 bool GraphicsLayerAndroid::paintContext(LayerAndroid* layer, 840 PicturePile& picture) 841 { 842 if (!layer) 843 return false; 844 845 TRACE_METHOD(); 846 847 picture.setSize(IntSize(layer->getWidth(), layer->getHeight())); 848 849 // TODO: add content checks (text, opacity, etc.) 850 picture.updatePicturesIfNeeded(this); 851 852 // store the newly painted content in the layer if it's not empty 853 PicturePileLayerContent* content = new PicturePileLayerContent(picture); 854 layer->setContent(content->isEmpty() ? 0 : content); 855 SkSafeUnref(content); 856 857 return true; 858 } 859 860 void GraphicsLayerAndroid::setNeedsDisplayInRect(const FloatRect& rect) 861 { 862 // rect is in the render object coordinates 863 864 if (!m_image && !drawsContent()) { 865 ALOGV("(%x) setNeedsDisplay(%.2f,%.2f,%.2f,%.2f) doesn't have content, bypass...", 866 this, rect.x(), rect.y(), rect.width(), rect.height()); 867 return; 868 } 869 870 m_contentLayerContent.invalidate(enclosingIntRect(rect)); 871 if (m_foregroundLayer) 872 m_foregroundLayerContent.invalidate(enclosingIntRect(rect)); 873 874 m_needsRepaint = true; 875 askForSync(); 876 } 877 878 void GraphicsLayerAndroid::pauseDisplay(bool state) 879 { 880 gPaused = state; 881 if (gPaused) 882 gPausedDelay = WTF::currentTime() + 1; 883 } 884 885 bool GraphicsLayerAndroid::addAnimation(const KeyframeValueList& valueList, 886 const IntSize& boxSize, 887 const Animation* anim, 888 const String& keyframesName, 889 double beginTime) 890 { 891 if (!anim || anim->isEmptyOrZeroDuration() || valueList.size() < 2) 892 return false; 893 894 bool createdAnimations = false; 895 if (valueList.property() == AnimatedPropertyWebkitTransform) { 896 createdAnimations = createTransformAnimationsFromKeyframes(valueList, 897 anim, 898 keyframesName, 899 beginTime, 900 boxSize); 901 } else { 902 createdAnimations = createAnimationFromKeyframes(valueList, 903 anim, 904 keyframesName, 905 beginTime); 906 } 907 if (createdAnimations) 908 askForSync(); 909 return createdAnimations; 910 } 911 912 bool GraphicsLayerAndroid::createAnimationFromKeyframes(const KeyframeValueList& valueList, 913 const Animation* animation, const String& keyframesName, double beginTime) 914 { 915 bool isKeyframe = valueList.size() > 2; 916 ALOGV("createAnimationFromKeyframes(%d), name(%s) beginTime(%.2f)", 917 isKeyframe, keyframesName.ascii().data(), beginTime); 918 919 switch (valueList.property()) { 920 case AnimatedPropertyInvalid: break; 921 case AnimatedPropertyWebkitTransform: break; 922 case AnimatedPropertyBackgroundColor: break; 923 case AnimatedPropertyOpacity: { 924 ALOGV("ANIMATEDPROPERTYOPACITY"); 925 926 KeyframeValueList* operationsList = new KeyframeValueList(AnimatedPropertyOpacity); 927 for (unsigned int i = 0; i < valueList.size(); i++) { 928 FloatAnimationValue* originalValue = (FloatAnimationValue*)valueList.at(i); 929 RefPtr<TimingFunction> timingFunction(const_cast<TimingFunction*>(originalValue->timingFunction())); 930 FloatAnimationValue* value = new FloatAnimationValue(originalValue->keyTime(), 931 originalValue->value(), 932 timingFunction); 933 operationsList->insert(value); 934 } 935 936 RefPtr<AndroidOpacityAnimation> anim = AndroidOpacityAnimation::create(animation, 937 operationsList, 938 beginTime); 939 if (keyframesName.isEmpty()) 940 anim->setName(propertyIdToString(valueList.property())); 941 else 942 anim->setName(keyframesName); 943 944 m_contentLayer->addAnimation(anim.release()); 945 needsNotifyClient(); 946 return true; 947 } break; 948 } 949 return false; 950 } 951 952 void GraphicsLayerAndroid::needsNotifyClient() 953 { 954 m_needsNotifyClient = true; 955 askForSync(); 956 } 957 958 bool GraphicsLayerAndroid::createTransformAnimationsFromKeyframes(const KeyframeValueList& valueList, 959 const Animation* animation, 960 const String& keyframesName, 961 double beginTime, 962 const IntSize& boxSize) 963 { 964 ASSERT(valueList.property() == AnimatedPropertyWebkitTransform); 965 ALOGV("createTransformAnimationFromKeyframes, name(%s) beginTime(%.2f)", 966 keyframesName.ascii().data(), beginTime); 967 968 KeyframeValueList* operationsList = new KeyframeValueList(AnimatedPropertyWebkitTransform); 969 for (unsigned int i = 0; i < valueList.size(); i++) { 970 TransformAnimationValue* originalValue = (TransformAnimationValue*)valueList.at(i); 971 RefPtr<TimingFunction> timingFunction(const_cast<TimingFunction*>(originalValue->timingFunction())); 972 TransformAnimationValue* value = new TransformAnimationValue(originalValue->keyTime(), 973 originalValue->value(), 974 timingFunction); 975 operationsList->insert(value); 976 } 977 978 RefPtr<AndroidTransformAnimation> anim = AndroidTransformAnimation::create(animation, 979 operationsList, 980 beginTime); 981 982 if (keyframesName.isEmpty()) 983 anim->setName(propertyIdToString(valueList.property())); 984 else 985 anim->setName(keyframesName); 986 987 988 m_contentLayer->addAnimation(anim.release()); 989 990 needsNotifyClient(); 991 return true; 992 } 993 994 void GraphicsLayerAndroid::removeAnimationsForProperty(AnimatedPropertyID anID) 995 { 996 ALOGV("NRO removeAnimationsForProperty(%d)", anID); 997 m_contentLayer->removeAnimationsForProperty(anID); 998 askForSync(); 999 } 1000 1001 void GraphicsLayerAndroid::removeAnimationsForKeyframes(const String& keyframesName) 1002 { 1003 ALOGV("NRO removeAnimationsForKeyframes(%s)", keyframesName.ascii().data()); 1004 m_contentLayer->removeAnimationsForKeyframes(keyframesName); 1005 askForSync(); 1006 } 1007 1008 void GraphicsLayerAndroid::pauseAnimation(const String& keyframesName) 1009 { 1010 ALOGV("NRO pauseAnimation(%s)", keyframesName.ascii().data()); 1011 } 1012 1013 void GraphicsLayerAndroid::suspendAnimations(double time) 1014 { 1015 ALOGV("NRO suspendAnimations(%.2f)", time); 1016 } 1017 1018 void GraphicsLayerAndroid::resumeAnimations() 1019 { 1020 ALOGV("NRO resumeAnimations()"); 1021 } 1022 1023 void GraphicsLayerAndroid::setContentsToImage(Image* image) 1024 { 1025 ALOGV("(%x) setContentsToImage", this, image); 1026 if (image && image != m_image) { 1027 image->ref(); 1028 if (m_image) 1029 m_image->deref(); 1030 m_image = image; 1031 1032 SkBitmapRef* bitmap = image->nativeImageForCurrentFrame(); 1033 m_contentLayer->setContentsImage(bitmap); 1034 1035 m_haveContents = true; 1036 m_newImage = true; 1037 } 1038 if (!image && m_image) { 1039 m_contentLayer->setContentsImage(0); 1040 m_image->deref(); 1041 m_image = 0; 1042 } 1043 1044 setNeedsDisplay(); 1045 askForSync(); 1046 } 1047 1048 void GraphicsLayerAndroid::setContentsToMedia(PlatformLayer* mediaLayer) 1049 { 1050 // Only fullscreen video on Android, so media doesn't get it's own layer. 1051 // We might still have other layers though. 1052 if (m_contentLayer != mediaLayer && mediaLayer) { 1053 1054 // TODO add a copy method to LayerAndroid to sync everything 1055 // copy data from the original content layer to the new one 1056 mediaLayer->setPosition(m_contentLayer->getPosition().fX, 1057 m_contentLayer->getPosition().fY); 1058 mediaLayer->setSize(m_contentLayer->getWidth(), m_contentLayer->getHeight()); 1059 mediaLayer->setDrawTransform(*m_contentLayer->drawTransform()); 1060 1061 mediaLayer->ref(); 1062 m_contentLayer->unref(); 1063 m_contentLayer = mediaLayer; 1064 1065 // If the parent exists then notify it to re-sync it's children 1066 if (m_parent) { 1067 GraphicsLayerAndroid* parent = static_cast<GraphicsLayerAndroid*>(m_parent); 1068 parent->m_needsSyncChildren = true; 1069 } 1070 m_needsSyncChildren = true; 1071 1072 setNeedsDisplay(); 1073 askForSync(); 1074 } 1075 } 1076 1077 PlatformLayer* GraphicsLayerAndroid::platformLayer() const 1078 { 1079 ALOGV("platformLayer"); 1080 return m_contentLayer; 1081 } 1082 1083 #ifndef NDEBUG 1084 void GraphicsLayerAndroid::setDebugBackgroundColor(const Color& color) 1085 { 1086 } 1087 1088 void GraphicsLayerAndroid::setDebugBorder(const Color& color, float borderWidth) 1089 { 1090 } 1091 #endif 1092 1093 void GraphicsLayerAndroid::setZPosition(float position) 1094 { 1095 if (position == m_zPosition) 1096 return; 1097 ALOGV("(%x) setZPosition: %.2f", this, position); 1098 GraphicsLayer::setZPosition(position); 1099 askForSync(); 1100 } 1101 1102 void GraphicsLayerAndroid::askForSync() 1103 { 1104 if (!m_client) 1105 return; 1106 1107 if (m_client) 1108 m_client->notifySyncRequired(this); 1109 } 1110 1111 void GraphicsLayerAndroid::syncChildren() 1112 { 1113 if (m_needsSyncChildren || isReplicated()) { 1114 m_contentLayer->removeChildren(); 1115 LayerAndroid* layer = m_contentLayer; 1116 1117 if (isReplicated()) { 1118 GraphicsLayerAndroid* replicatedLayer = static_cast<GraphicsLayerAndroid*>(replicaLayer()); 1119 m_contentLayer->addChild(replicatedLayer->m_contentLayer); 1120 } 1121 1122 if (m_contentLayer->isFixedBackground()) { 1123 m_contentLayer->addChild(m_foregroundClipLayer); 1124 m_contentLayer->addChild(m_foregroundLayer); 1125 layer = m_foregroundLayer; 1126 layer->removeChildren(); 1127 } else if (m_foregroundClipLayer) { 1128 m_contentLayer->addChild(m_foregroundClipLayer); 1129 // Use the scrollable content layer as the parent of the children so 1130 // that they move with the content. 1131 layer = m_foregroundLayer; 1132 layer->removeChildren(); 1133 } 1134 1135 for (unsigned int i = 0; i < m_children.size(); i++) 1136 layer->addChild(m_children[i]->platformLayer()); 1137 } 1138 m_needsSyncChildren = false; 1139 } 1140 1141 void GraphicsLayerAndroid::syncMask() 1142 { 1143 if (m_needsSyncMask) { 1144 if (m_maskLayer) { 1145 LayerAndroid* mask = m_maskLayer->platformLayer(); 1146 m_contentLayer->setMaskLayer(mask); 1147 } else 1148 m_contentLayer->setMaskLayer(0); 1149 1150 m_contentLayer->setMasksToBounds(m_masksToBounds); 1151 m_needsSyncMask = false; 1152 } 1153 } 1154 1155 void GraphicsLayerAndroid::gatherRootLayers(Vector<const RenderLayer*>& list) 1156 { 1157 RenderLayer* renderLayer = renderLayerFromClient(m_client); 1158 if (renderLayer) { 1159 const RenderLayer* rootLayer = renderLayer->root(); 1160 bool found = false; 1161 for (unsigned int i = 0; i < list.size(); i++) { 1162 const RenderLayer* current = list[i]; 1163 if (current == rootLayer) { 1164 found = true; 1165 break; 1166 } 1167 } 1168 if (!found) 1169 list.append(rootLayer); 1170 } 1171 1172 for (unsigned int i = 0; i < m_children.size(); i++) { 1173 GraphicsLayerAndroid* layer = static_cast<GraphicsLayerAndroid*>(m_children[i]); 1174 layer->gatherRootLayers(list); 1175 } 1176 } 1177 1178 void GraphicsLayerAndroid::syncCompositingStateForThisLayerOnly() 1179 { 1180 if (m_contentLayer) { 1181 RenderLayer* renderLayer = renderLayerFromClient(m_client); 1182 int intrinsicallyComposited = renderLayer ? renderLayer->intrinsicallyComposited() : true; 1183 m_contentLayer->setIntrinsicallyComposited(intrinsicallyComposited); 1184 } 1185 1186 updateScrollingLayers(); 1187 updateFixedBackgroundLayers(); 1188 updatePositionedLayers(); 1189 syncChildren(); 1190 syncMask(); 1191 1192 if (!gPaused || WTF::currentTime() >= gPausedDelay) 1193 repaint(); 1194 } 1195 1196 void GraphicsLayerAndroid::syncCompositingState() 1197 { 1198 for (unsigned int i = 0; i < m_children.size(); i++) 1199 m_children[i]->syncCompositingState(); 1200 1201 syncCompositingStateForThisLayerOnly(); 1202 } 1203 1204 void GraphicsLayerAndroid::notifyClientAnimationStarted() 1205 { 1206 for (unsigned int i = 0; i < m_children.size(); i++) 1207 static_cast<GraphicsLayerAndroid*>(m_children[i])->notifyClientAnimationStarted(); 1208 1209 if (m_needsNotifyClient) { 1210 if (client()) 1211 client()->notifyAnimationStarted(this, WTF::currentTime()); 1212 m_needsNotifyClient = false; 1213 } 1214 } 1215 1216 } // namespace WebCore 1217 1218 #endif // USE(ACCELERATED_COMPOSITING) 1219