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 "PlatformBridge.h" 45 #include "PlatformGraphicsContextSkia.h" 46 #include "RenderLayerBacking.h" 47 #include "RenderView.h" 48 #include "RotateTransformOperation.h" 49 #include "ScaleTransformOperation.h" 50 #include "ScrollableLayerAndroid.h" 51 #include "SkCanvas.h" 52 #include "SkRegion.h" 53 #include "StyleCachedImage.h" 54 #include "TransformationMatrix.h" 55 #include "TranslateTransformOperation.h" 56 57 #include <wtf/CurrentTime.h> 58 #include <wtf/text/CString.h> 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 static RenderLayer* renderLayerFromClient(GraphicsLayerClient* client) 95 { 96 return client ? client->owningLayer() : 0; 97 } 98 99 GraphicsLayerAndroid::GraphicsLayerAndroid(GraphicsLayerClient* client) : 100 GraphicsLayer(client), 101 m_needsSyncChildren(false), 102 m_needsSyncMask(false), 103 m_needsRepaint(false), 104 m_needsNotifyClient(false), 105 m_haveContents(false), 106 m_newImage(false), 107 m_image(0), 108 m_fixedBackgroundLayer(0), 109 m_foregroundLayer(0), 110 m_foregroundClipLayer(0) 111 { 112 RenderLayer* renderLayer = renderLayerFromClient(m_client); 113 if (renderLayer && renderLayer->renderer()->isCanvas()) { 114 m_contentLayer = new CanvasLayer(renderLayer, 115 static_cast<HTMLCanvasElement*>(renderLayer->renderer()->node())); 116 } else 117 m_contentLayer = new LayerAndroid(renderLayer); 118 m_dirtyRegion.setEmpty(); 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 595 Image* image = FixedBackgroundImageLayerAndroid::GetCachedImage(view->style()); 596 if (!image) 597 return; 598 599 if (image->width() == 1 && image->height() == 1) 600 return; 601 602 SkSafeUnref(m_foregroundClipLayer); 603 SkSafeUnref(m_fixedBackgroundLayer); 604 SkSafeUnref(m_foregroundLayer); 605 606 // we will have: 607 // m_contentLayer 608 // \- m_foregroundClipLayer 609 // \- m_fixedBackgroundLayer 610 // \- m_foregroundLayer 611 612 // use the background image and create a layer for it 613 // the layer will be fixed positioned. 614 615 m_fixedBackgroundLayer = new FixedBackgroundImageLayerAndroid(view->style(), 616 view->width(), 617 view->height()); 618 619 Color color = view->style()->visitedDependentColor(CSSPropertyBackgroundColor); 620 SkColor skiaColor = SkColorSetARGB(color.alpha(), 621 color.red(), 622 color.green(), 623 color.blue()); 624 m_fixedBackgroundLayer->setBackgroundColor(skiaColor); 625 626 // We need to clip the background image to the bounds of the original element 627 m_foregroundClipLayer = new LayerAndroid(renderLayer); 628 m_foregroundClipLayer->setMasksToBounds(true); 629 m_foregroundClipLayer->addChild(m_fixedBackgroundLayer); 630 631 // We then want to display the content above the image background; webkit 632 // allow to paint background and foreground separately. For now, we'll create 633 // two layers; the one containing the background will be painted *without* the 634 // background image (but with the decorations, e.g. border) 635 m_foregroundLayer = new LayerAndroid(renderLayer); 636 m_foregroundLayer->setIntrinsicallyComposited(true); 637 638 // Finally, let's assemble all the layers under a FixedBackgroundLayerAndroid layer 639 if (!m_contentLayer->isFixedBackground()) { 640 m_contentLayer->removeChildren(); 641 LayerAndroid* layer = new FixedBackgroundLayerAndroid(*m_contentLayer); 642 m_contentLayer->unref(); 643 m_contentLayer = layer; 644 } 645 646 if (m_parent) { 647 // The content layer has changed so the parent needs to sync 648 // children. 649 static_cast<GraphicsLayerAndroid*>(m_parent)->m_needsSyncChildren = true; 650 } 651 // Children are all re-parented. 652 m_needsSyncChildren = true; 653 654 setNeedsDisplay(); 655 askForSync(); 656 } 657 658 void GraphicsLayerAndroid::updateScrollOffset() { 659 RenderLayer* layer = renderLayerFromClient(m_client); 660 if (!layer || !(m_foregroundLayer || m_contentLayer->contentIsScrollable())) 661 return; 662 if (m_foregroundLayer) { 663 IntSize scroll = layer->scrolledContentOffset(); 664 m_foregroundLayer->setScrollOffset(IntPoint(scroll.width(), scroll.height())); 665 } else if (m_contentLayer->isIFrameContent()) { 666 IntPoint p(layer->renderer()->frame()->view()->scrollX(), 667 layer->renderer()->frame()->view()->scrollY()); 668 static_cast<IFrameContentLayerAndroid*>(m_contentLayer)->setIFrameScrollOffset(p); 669 } 670 askForSync(); 671 } 672 673 static void setScrollLimits(ScrollableLayerAndroid* scrollableLayer, RenderLayer* renderLayer) 674 { 675 RenderBox* box = renderLayer->renderBox(); 676 scrollableLayer->setScrollLimits(0, 0, 677 renderLayer->scrollWidth() - box->clientWidth(), 678 renderLayer->scrollHeight() - box->clientHeight()); 679 } 680 681 bool GraphicsLayerAndroid::repaint() 682 { 683 ALOGV("(%x) repaint(), gPaused(%d) m_needsRepaint(%d) m_haveContents(%d) ", 684 this, gPaused, m_needsRepaint, m_haveContents); 685 686 if (!gPaused && m_haveContents && m_needsRepaint && !m_image) { 687 // with SkPicture, we request the entire layer's content. 688 IntRect layerBounds(0, 0, m_size.width(), m_size.height()); 689 690 RenderLayer* layer = renderLayerFromClient(m_client); 691 if (!layer) 692 return false; 693 if (m_foregroundLayer && !m_contentLayer->isFixedBackground()) { 694 PaintingPhase phase(this); 695 // Paint the background into a separate context. 696 phase.set(GraphicsLayerPaintBackground); 697 if (!paintContext(m_contentLayer, layerBounds)) 698 return false; 699 700 // Construct the foreground layer and draw. 701 RenderBox* box = layer->renderBox(); 702 int outline = box->view()->maximalOutlineSize(); 703 IntRect contentsRect(0, 0, 704 box->borderLeft() + box->borderRight() + layer->scrollWidth() 705 + layer->verticalScrollbarWidth(), 706 box->borderTop() + box->borderBottom() + layer->scrollHeight() 707 + layer->horizontalScrollbarHeight()); 708 contentsRect.inflate(outline); 709 // Update the foreground layer size. 710 m_foregroundLayer->setSize(contentsRect.width(), contentsRect.height()); 711 // Paint everything else into the main recording canvas. 712 phase.clear(GraphicsLayerPaintBackground); 713 714 // Paint at 0,0. 715 IntSize scroll = layer->scrolledContentOffset(); 716 layer->scrollToOffset(0, 0); 717 // At this point, it doesn't matter if painting failed. 718 (void) paintContext(m_foregroundLayer, contentsRect); 719 layer->scrollToOffset(scroll.width(), scroll.height()); 720 721 // Construct the clip layer for masking the contents. 722 IntRect clip = layer->renderer()->absoluteBoundingBoxRect(); 723 // absoluteBoundingBoxRect does not include the outline so we need 724 // to offset the position. 725 int x = box->borderLeft() + outline; 726 int y = box->borderTop() + outline; 727 int width = clip.width() - box->borderLeft() - box->borderRight(); 728 int height = clip.height() - box->borderTop() - box->borderBottom(); 729 m_foregroundClipLayer->setPosition(x, y); 730 m_foregroundClipLayer->setSize(width, height); 731 732 int rtlOffset = 0; // LTR uses no offset. 733 if (!layer->renderer()->style()->isLeftToRightDirection()) 734 rtlOffset = layer->scrollWidth() - width; // Scroll all the way right. 735 m_foregroundLayer->setScrollOffset(IntPoint(scroll.width() + rtlOffset, 736 scroll.height())); 737 // Need to offset the foreground layer by the clip layer in order 738 // for the contents to be in the correct position. 739 m_foregroundLayer->setPosition(-x, -y); 740 // Set the scrollable bounds of the layer. 741 setScrollLimits(static_cast<ScrollableLayerAndroid*>(m_foregroundLayer), layer); 742 743 // Invalidate the entire layer for now, as webkit will only send the 744 // setNeedsDisplayInRect() for the visible (clipped) scrollable area, 745 // offsetting the invals by the scroll position would not be enough. 746 // TODO: have webkit send us invals even for non visible area 747 SkRegion region; 748 region.setRect(0, 0, contentsRect.width(), contentsRect.height()); 749 m_foregroundLayer->markAsDirty(region); 750 } else if (m_contentLayer->isFixedBackground()) { 751 SkPicture* picture = new SkPicture(); 752 SkCanvas* canvas = picture->beginRecording(layerBounds.width(), 753 layerBounds.height(), 0); 754 if (canvas) { 755 PaintingPhase phase(this); 756 PlatformGraphicsContextSkia platformContext(canvas); 757 GraphicsContext graphicsContext(&platformContext); 758 759 // Paint the background (without the fixed image)... 760 phase.set(GraphicsLayerPaintBackgroundDecorations); 761 paintGraphicsLayerContents(graphicsContext, layerBounds); 762 phase.clear(GraphicsLayerPaintBackgroundDecorations); 763 764 // Paint the foreground... 765 phase.set(GraphicsLayerPaintForeground); 766 paintGraphicsLayerContents(graphicsContext, layerBounds); 767 picture->endRecording(); 768 769 // Now set the content for that layer. 770 PictureLayerContent* layerContent = new PictureLayerContent(picture); 771 m_foregroundLayer->setContent(layerContent); 772 SkSafeUnref(layerContent); 773 } 774 SkSafeUnref(picture); 775 776 m_foregroundLayer->setSize(layerBounds.width(), layerBounds.height()); 777 m_foregroundClipLayer->setPosition(layerBounds.x(), layerBounds.y()); 778 m_foregroundClipLayer->setSize(layerBounds.width(), layerBounds.height()); 779 } else { 780 781 // If we are replicated, paint the mask 782 if (isReplicated()) { 783 GraphicsLayerAndroid* replicatedLayer = static_cast<GraphicsLayerAndroid*>(replicaLayer()); 784 if (replicatedLayer->maskLayer()) { 785 GraphicsLayerAndroid* mask = static_cast<GraphicsLayerAndroid*>(replicatedLayer->maskLayer()); 786 mask->paintContext(mask->m_contentLayer, layerBounds, false); 787 } 788 } 789 790 // If there is no contents clip, we can draw everything into one 791 // picture. 792 bool painting = paintContext(m_contentLayer, layerBounds); 793 if (!painting) 794 return false; 795 // Check for a scrollable iframe and report the scrolling 796 // limits based on the view size. 797 if (m_contentLayer->isIFrameContent()) { 798 FrameView* view = layer->renderer()->frame()->view(); 799 setScrollLimits(static_cast<ScrollableLayerAndroid*>(m_contentLayer), layer); 800 ALOGV("setScrollLimits(%.2f, %.2f, w: %d h: %d) layer %d, frame scroll position is %d, %d", 801 m_position.x(), m_position.y(), view->layoutWidth(), view->layoutHeight(), 802 m_contentLayer->uniqueId(), view->scrollX(), view->scrollY()); 803 } 804 } 805 806 ALOGV("(%x) repaint() on (%.2f,%.2f) contentlayer(%.2f,%.2f,%.2f,%.2f)paintGraphicsLayer called!", 807 this, m_size.width(), m_size.height(), 808 m_contentLayer->getPosition().fX, 809 m_contentLayer->getPosition().fY, 810 m_contentLayer->getSize().width(), 811 m_contentLayer->getSize().height()); 812 813 m_contentLayer->markAsDirty(m_dirtyRegion); 814 m_dirtyRegion.setEmpty(); 815 m_needsRepaint = false; 816 817 return true; 818 } 819 if (m_needsRepaint && m_image && m_newImage) { 820 // We need to tell the GL thread that we will need to repaint the 821 // texture. Only do so if we effectively have a new image! 822 m_contentLayer->markAsDirty(m_dirtyRegion); 823 m_dirtyRegion.setEmpty(); 824 m_newImage = false; 825 m_needsRepaint = false; 826 return true; 827 } 828 return false; 829 } 830 831 SkPicture* GraphicsLayerAndroid::paintPicture(const IntRect& rect) 832 { 833 SkPicture* picture = new SkPicture(); 834 SkCanvas* canvas = picture->beginRecording(rect.width(), rect.height(), 0); 835 if (!canvas) { 836 picture->endRecording(); 837 SkSafeUnref(picture); 838 return 0; 839 } 840 841 PlatformGraphicsContextSkia platformContext(canvas); 842 GraphicsContext graphicsContext(&platformContext); 843 844 paintGraphicsLayerContents(graphicsContext, rect); 845 846 return picture; 847 } 848 849 bool GraphicsLayerAndroid::paintContext(LayerAndroid* layer, 850 const IntRect& rect, 851 bool checkOptimisations) 852 { 853 if (!layer) 854 return false; 855 856 SkPicture* picture = paintPicture(rect); 857 if (!picture) 858 return false; 859 picture->endRecording(); 860 861 PictureLayerContent* layerContent = new PictureLayerContent(picture); 862 if (checkOptimisations) 863 layerContent->checkForOptimisations(); 864 else 865 layerContent->setCheckForOptimisations(false); 866 layer->setContent(layerContent); 867 SkSafeUnref(layerContent); 868 SkSafeUnref(picture); 869 return true; 870 } 871 872 void GraphicsLayerAndroid::setNeedsDisplayInRect(const FloatRect& rect) 873 { 874 // rect is in the render object coordinates 875 876 if (!m_image && !drawsContent()) { 877 ALOGV("(%x) setNeedsDisplay(%.2f,%.2f,%.2f,%.2f) doesn't have content, bypass...", 878 this, rect.x(), rect.y(), rect.width(), rect.height()); 879 return; 880 } 881 882 SkRegion region; 883 region.setRect(rect.x(), rect.y(), 884 rect.x() + rect.width(), 885 rect.y() + rect.height()); 886 m_dirtyRegion.op(region, SkRegion::kUnion_Op); 887 888 m_needsRepaint = true; 889 askForSync(); 890 } 891 892 void GraphicsLayerAndroid::pauseDisplay(bool state) 893 { 894 gPaused = state; 895 if (gPaused) 896 gPausedDelay = WTF::currentTime() + 1; 897 } 898 899 bool GraphicsLayerAndroid::addAnimation(const KeyframeValueList& valueList, 900 const IntSize& boxSize, 901 const Animation* anim, 902 const String& keyframesName, 903 double beginTime) 904 { 905 if (!anim || anim->isEmptyOrZeroDuration() || valueList.size() < 2) 906 return false; 907 908 bool createdAnimations = false; 909 if (valueList.property() == AnimatedPropertyWebkitTransform) { 910 createdAnimations = createTransformAnimationsFromKeyframes(valueList, 911 anim, 912 keyframesName, 913 beginTime, 914 boxSize); 915 } else { 916 createdAnimations = createAnimationFromKeyframes(valueList, 917 anim, 918 keyframesName, 919 beginTime); 920 } 921 if (createdAnimations) 922 askForSync(); 923 return createdAnimations; 924 } 925 926 bool GraphicsLayerAndroid::createAnimationFromKeyframes(const KeyframeValueList& valueList, 927 const Animation* animation, const String& keyframesName, double beginTime) 928 { 929 bool isKeyframe = valueList.size() > 2; 930 ALOGV("createAnimationFromKeyframes(%d), name(%s) beginTime(%.2f)", 931 isKeyframe, keyframesName.ascii().data(), beginTime); 932 933 switch (valueList.property()) { 934 case AnimatedPropertyInvalid: break; 935 case AnimatedPropertyWebkitTransform: break; 936 case AnimatedPropertyBackgroundColor: break; 937 case AnimatedPropertyOpacity: { 938 ALOGV("ANIMATEDPROPERTYOPACITY"); 939 940 KeyframeValueList* operationsList = new KeyframeValueList(AnimatedPropertyOpacity); 941 for (unsigned int i = 0; i < valueList.size(); i++) { 942 FloatAnimationValue* originalValue = (FloatAnimationValue*)valueList.at(i); 943 RefPtr<TimingFunction> timingFunction(const_cast<TimingFunction*>(originalValue->timingFunction())); 944 FloatAnimationValue* value = new FloatAnimationValue(originalValue->keyTime(), 945 originalValue->value(), 946 timingFunction); 947 operationsList->insert(value); 948 } 949 950 RefPtr<AndroidOpacityAnimation> anim = AndroidOpacityAnimation::create(animation, 951 operationsList, 952 beginTime); 953 if (keyframesName.isEmpty()) 954 anim->setName(propertyIdToString(valueList.property())); 955 else 956 anim->setName(keyframesName); 957 958 m_contentLayer->addAnimation(anim.release()); 959 needsNotifyClient(); 960 return true; 961 } break; 962 } 963 return false; 964 } 965 966 void GraphicsLayerAndroid::needsNotifyClient() 967 { 968 m_needsNotifyClient = true; 969 askForSync(); 970 } 971 972 bool GraphicsLayerAndroid::createTransformAnimationsFromKeyframes(const KeyframeValueList& valueList, 973 const Animation* animation, 974 const String& keyframesName, 975 double beginTime, 976 const IntSize& boxSize) 977 { 978 ASSERT(valueList.property() == AnimatedPropertyWebkitTransform); 979 ALOGV("createTransformAnimationFromKeyframes, name(%s) beginTime(%.2f)", 980 keyframesName.ascii().data(), beginTime); 981 982 KeyframeValueList* operationsList = new KeyframeValueList(AnimatedPropertyWebkitTransform); 983 for (unsigned int i = 0; i < valueList.size(); i++) { 984 TransformAnimationValue* originalValue = (TransformAnimationValue*)valueList.at(i); 985 RefPtr<TimingFunction> timingFunction(const_cast<TimingFunction*>(originalValue->timingFunction())); 986 TransformAnimationValue* value = new TransformAnimationValue(originalValue->keyTime(), 987 originalValue->value(), 988 timingFunction); 989 operationsList->insert(value); 990 } 991 992 RefPtr<AndroidTransformAnimation> anim = AndroidTransformAnimation::create(animation, 993 operationsList, 994 beginTime); 995 996 if (keyframesName.isEmpty()) 997 anim->setName(propertyIdToString(valueList.property())); 998 else 999 anim->setName(keyframesName); 1000 1001 1002 m_contentLayer->addAnimation(anim.release()); 1003 1004 needsNotifyClient(); 1005 return true; 1006 } 1007 1008 void GraphicsLayerAndroid::removeAnimationsForProperty(AnimatedPropertyID anID) 1009 { 1010 ALOGV("NRO removeAnimationsForProperty(%d)", anID); 1011 m_contentLayer->removeAnimationsForProperty(anID); 1012 askForSync(); 1013 } 1014 1015 void GraphicsLayerAndroid::removeAnimationsForKeyframes(const String& keyframesName) 1016 { 1017 ALOGV("NRO removeAnimationsForKeyframes(%s)", keyframesName.ascii().data()); 1018 m_contentLayer->removeAnimationsForKeyframes(keyframesName); 1019 askForSync(); 1020 } 1021 1022 void GraphicsLayerAndroid::pauseAnimation(const String& keyframesName) 1023 { 1024 ALOGV("NRO pauseAnimation(%s)", keyframesName.ascii().data()); 1025 } 1026 1027 void GraphicsLayerAndroid::suspendAnimations(double time) 1028 { 1029 ALOGV("NRO suspendAnimations(%.2f)", time); 1030 } 1031 1032 void GraphicsLayerAndroid::resumeAnimations() 1033 { 1034 ALOGV("NRO resumeAnimations()"); 1035 } 1036 1037 void GraphicsLayerAndroid::setContentsToImage(Image* image) 1038 { 1039 ALOGV("(%x) setContentsToImage", this, image); 1040 if (image && image != m_image) { 1041 image->ref(); 1042 if (m_image) 1043 m_image->deref(); 1044 m_image = image; 1045 1046 SkBitmapRef* bitmap = image->nativeImageForCurrentFrame(); 1047 m_contentLayer->setContentsImage(bitmap); 1048 1049 m_haveContents = true; 1050 m_newImage = true; 1051 } 1052 if (!image && m_image) { 1053 m_contentLayer->setContentsImage(0); 1054 m_image->deref(); 1055 m_image = 0; 1056 } 1057 1058 setNeedsDisplay(); 1059 askForSync(); 1060 } 1061 1062 void GraphicsLayerAndroid::setContentsToMedia(PlatformLayer* mediaLayer) 1063 { 1064 // Only fullscreen video on Android, so media doesn't get it's own layer. 1065 // We might still have other layers though. 1066 if (m_contentLayer != mediaLayer && mediaLayer) { 1067 1068 // TODO add a copy method to LayerAndroid to sync everything 1069 // copy data from the original content layer to the new one 1070 mediaLayer->setPosition(m_contentLayer->getPosition().fX, 1071 m_contentLayer->getPosition().fY); 1072 mediaLayer->setSize(m_contentLayer->getWidth(), m_contentLayer->getHeight()); 1073 mediaLayer->setDrawTransform(*m_contentLayer->drawTransform()); 1074 1075 mediaLayer->ref(); 1076 m_contentLayer->unref(); 1077 m_contentLayer = mediaLayer; 1078 1079 // If the parent exists then notify it to re-sync it's children 1080 if (m_parent) { 1081 GraphicsLayerAndroid* parent = static_cast<GraphicsLayerAndroid*>(m_parent); 1082 parent->m_needsSyncChildren = true; 1083 } 1084 m_needsSyncChildren = true; 1085 1086 setNeedsDisplay(); 1087 askForSync(); 1088 } 1089 } 1090 1091 PlatformLayer* GraphicsLayerAndroid::platformLayer() const 1092 { 1093 ALOGV("platformLayer"); 1094 return m_contentLayer; 1095 } 1096 1097 #ifndef NDEBUG 1098 void GraphicsLayerAndroid::setDebugBackgroundColor(const Color& color) 1099 { 1100 } 1101 1102 void GraphicsLayerAndroid::setDebugBorder(const Color& color, float borderWidth) 1103 { 1104 } 1105 #endif 1106 1107 void GraphicsLayerAndroid::setZPosition(float position) 1108 { 1109 if (position == m_zPosition) 1110 return; 1111 ALOGV("(%x) setZPosition: %.2f", this, position); 1112 GraphicsLayer::setZPosition(position); 1113 askForSync(); 1114 } 1115 1116 void GraphicsLayerAndroid::askForSync() 1117 { 1118 if (!m_client) 1119 return; 1120 1121 if (m_client) 1122 m_client->notifySyncRequired(this); 1123 } 1124 1125 void GraphicsLayerAndroid::syncChildren() 1126 { 1127 if (m_needsSyncChildren || isReplicated()) { 1128 m_contentLayer->removeChildren(); 1129 LayerAndroid* layer = m_contentLayer; 1130 1131 if (isReplicated()) { 1132 GraphicsLayerAndroid* replicatedLayer = static_cast<GraphicsLayerAndroid*>(replicaLayer()); 1133 m_contentLayer->addChild(replicatedLayer->m_contentLayer); 1134 } 1135 1136 if (m_contentLayer->isFixedBackground()) { 1137 m_contentLayer->addChild(m_foregroundClipLayer); 1138 m_contentLayer->addChild(m_foregroundLayer); 1139 layer = m_foregroundLayer; 1140 layer->removeChildren(); 1141 } else if (m_foregroundClipLayer) { 1142 m_contentLayer->addChild(m_foregroundClipLayer); 1143 // Use the scrollable content layer as the parent of the children so 1144 // that they move with the content. 1145 layer = m_foregroundLayer; 1146 layer->removeChildren(); 1147 } 1148 1149 for (unsigned int i = 0; i < m_children.size(); i++) 1150 layer->addChild(m_children[i]->platformLayer()); 1151 } 1152 m_needsSyncChildren = false; 1153 } 1154 1155 void GraphicsLayerAndroid::syncMask() 1156 { 1157 if (m_needsSyncMask) { 1158 if (m_maskLayer) { 1159 LayerAndroid* mask = m_maskLayer->platformLayer(); 1160 m_contentLayer->setMaskLayer(mask); 1161 } else 1162 m_contentLayer->setMaskLayer(0); 1163 1164 m_contentLayer->setMasksToBounds(m_masksToBounds); 1165 m_needsSyncMask = false; 1166 } 1167 } 1168 1169 void GraphicsLayerAndroid::gatherRootLayers(Vector<const RenderLayer*>& list) 1170 { 1171 RenderLayer* renderLayer = renderLayerFromClient(m_client); 1172 if (renderLayer) { 1173 const RenderLayer* rootLayer = renderLayer->root(); 1174 bool found = false; 1175 for (unsigned int i = 0; i < list.size(); i++) { 1176 const RenderLayer* current = list[i]; 1177 if (current == rootLayer) { 1178 found = true; 1179 break; 1180 } 1181 } 1182 if (!found) 1183 list.append(rootLayer); 1184 } 1185 1186 for (unsigned int i = 0; i < m_children.size(); i++) { 1187 GraphicsLayerAndroid* layer = static_cast<GraphicsLayerAndroid*>(m_children[i]); 1188 layer->gatherRootLayers(list); 1189 } 1190 } 1191 1192 void GraphicsLayerAndroid::syncCompositingStateForThisLayerOnly() 1193 { 1194 if (m_contentLayer) { 1195 RenderLayer* renderLayer = renderLayerFromClient(m_client); 1196 int intrinsicallyComposited = renderLayer ? renderLayer->intrinsicallyComposited() : true; 1197 m_contentLayer->setIntrinsicallyComposited(intrinsicallyComposited); 1198 } 1199 1200 updateScrollingLayers(); 1201 updateFixedBackgroundLayers(); 1202 updatePositionedLayers(); 1203 syncChildren(); 1204 syncMask(); 1205 1206 if (!gPaused || WTF::currentTime() >= gPausedDelay) 1207 repaint(); 1208 } 1209 1210 void GraphicsLayerAndroid::syncCompositingState() 1211 { 1212 for (unsigned int i = 0; i < m_children.size(); i++) 1213 m_children[i]->syncCompositingState(); 1214 1215 syncCompositingStateForThisLayerOnly(); 1216 } 1217 1218 void GraphicsLayerAndroid::notifyClientAnimationStarted() 1219 { 1220 for (unsigned int i = 0; i < m_children.size(); i++) 1221 static_cast<GraphicsLayerAndroid*>(m_children[i])->notifyClientAnimationStarted(); 1222 1223 if (m_needsNotifyClient) { 1224 if (client()) 1225 client()->notifyAnimationStarted(this, WTF::currentTime()); 1226 m_needsNotifyClient = false; 1227 } 1228 } 1229 1230 } // namespace WebCore 1231 1232 #endif // USE(ACCELERATED_COMPOSITING) 1233