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