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