1 #define LOG_TAG "LayerAndroid" 2 #define LOG_NDEBUG 1 3 4 #include "config.h" 5 #include "LayerAndroid.h" 6 7 #if USE(ACCELERATED_COMPOSITING) 8 9 #include "AndroidLog.h" 10 #include "AndroidAnimation.h" 11 #include "ClassTracker.h" 12 #include "DrawExtra.h" 13 #include "DumpLayer.h" 14 #include "FixedPositioning.h" 15 #include "GLUtils.h" 16 #include "GLWebViewState.h" 17 #include "ImagesManager.h" 18 #include "InspectorCanvas.h" 19 #include "LayerContent.h" 20 #include "MediaLayer.h" 21 #include "ParseCanvas.h" 22 #include "PictureLayerContent.h" 23 #include "PrerenderedInval.h" 24 #include "SkBitmapRef.h" 25 #include "SkDevice.h" 26 #include "SkDrawFilter.h" 27 #include "SkPaint.h" 28 #include "SkPicture.h" 29 #include "SkTypeface.h" 30 #include "Surface.h" 31 #include "TilesManager.h" 32 33 #include <wtf/CurrentTime.h> 34 #include <wtf/text/CString.h> 35 #include <math.h> 36 37 #define DISABLE_LAYER_MERGE 38 #undef DISABLE_LAYER_MERGE 39 40 #define LAYER_MERGING_DEBUG 41 #undef LAYER_MERGING_DEBUG 42 43 namespace WebCore { 44 45 static int gUniqueId; 46 47 class OpacityDrawFilter : public SkDrawFilter { 48 public: 49 OpacityDrawFilter(int opacity) : m_opacity(opacity) { } 50 virtual bool filter(SkPaint* paint, Type) 51 { 52 paint->setAlpha(m_opacity); 53 return true; 54 } 55 private: 56 int m_opacity; 57 }; 58 59 /////////////////////////////////////////////////////////////////////////////// 60 61 LayerAndroid::LayerAndroid(RenderLayer* owner) : Layer(), 62 m_uniqueId(++gUniqueId), 63 m_haveClip(false), 64 m_backfaceVisibility(true), 65 m_visible(true), 66 m_backgroundColor(0), 67 m_preserves3D(false), 68 m_anchorPointZ(0), 69 m_isPositionAbsolute(false), 70 m_fixedPosition(0), 71 m_zValue(0), 72 m_content(0), 73 m_imageCRC(0), 74 m_scale(1), 75 m_lastComputeTextureSize(0), 76 m_owningLayer(owner), 77 m_type(LayerAndroid::WebCoreLayer), 78 m_intrinsicallyComposited(true), 79 m_surface(0), 80 m_replicatedLayer(0), 81 m_originalLayer(0), 82 m_maskLayer(0) 83 { 84 m_dirtyRegion.setEmpty(); 85 #ifdef DEBUG_COUNT 86 ClassTracker::instance()->increment("LayerAndroid"); 87 ClassTracker::instance()->add(this); 88 #endif 89 } 90 91 LayerAndroid::LayerAndroid(const LayerAndroid& layer) : Layer(layer), 92 m_uniqueId(layer.m_uniqueId), 93 m_haveClip(layer.m_haveClip), 94 m_backfaceVisibility(layer.m_backfaceVisibility), 95 m_visible(layer.m_visible), 96 m_backgroundColor(layer.m_backgroundColor), 97 m_preserves3D(layer.m_preserves3D), 98 m_anchorPointZ(layer.m_anchorPointZ), 99 m_isPositionAbsolute(layer.m_isPositionAbsolute), 100 m_fixedPosition(0), 101 m_zValue(layer.m_zValue), 102 m_content(layer.m_content), 103 m_imageCRC(layer.m_imageCRC), 104 m_scale(layer.m_scale), 105 m_lastComputeTextureSize(0), 106 m_owningLayer(layer.m_owningLayer), 107 m_type(LayerAndroid::UILayer), 108 m_intrinsicallyComposited(layer.m_intrinsicallyComposited), 109 m_surface(0), 110 m_replicatedLayer(0), 111 m_originalLayer(0), 112 m_maskLayer(0) 113 { 114 if (m_imageCRC) 115 ImagesManager::instance()->retainImage(m_imageCRC); 116 117 SkSafeRef(m_content); 118 119 if (layer.m_fixedPosition) { 120 m_fixedPosition = layer.m_fixedPosition->copy(this); 121 Layer::setShouldInheritFromRootTransform(true); 122 } 123 124 m_transform = layer.m_transform; 125 m_drawTransform = layer.m_drawTransform; 126 m_drawTransformUnfudged = layer.m_drawTransformUnfudged; 127 m_childrenTransform = layer.m_childrenTransform; 128 m_dirtyRegion = layer.m_dirtyRegion; 129 130 m_replicatedLayerPosition = layer.m_replicatedLayerPosition; 131 132 #ifdef ABSOLUTE_POSITION 133 // If we have absolute elements, we may need to reorder them if they 134 // are followed by another layer that is not also absolutely positioned. 135 // (as absolutely positioned elements are out of the normal flow) 136 bool hasAbsoluteChildren = false; 137 bool hasOnlyAbsoluteFollowers = true; 138 139 for (int i = 0; i < layer.countChildren(); i++) { 140 if (layer.getChild(i)->isPositionAbsolute()) { 141 hasAbsoluteChildren = true; 142 continue; 143 } 144 if (hasAbsoluteChildren 145 && !layer.getChild(i)->isPositionAbsolute()) { 146 hasOnlyAbsoluteFollowers = false; 147 break; 148 } 149 } 150 151 if (hasAbsoluteChildren && !hasOnlyAbsoluteFollowers) { 152 Vector<LayerAndroid*> normalLayers; 153 Vector<LayerAndroid*> absoluteLayers; 154 for (int i = 0; i < layer.countChildren(); i++) { 155 LayerAndroid* child = layer.getChild(i); 156 if (child->isPositionAbsolute() 157 || child->isPositionFixed()) 158 absoluteLayers.append(child); 159 else 160 normalLayers.append(child); 161 } 162 for (unsigned int i = 0; i < normalLayers.size(); i++) 163 addChild(normalLayers[i]->copy())->unref(); 164 for (unsigned int i = 0; i < absoluteLayers.size(); i++) 165 addChild(absoluteLayers[i]->copy())->unref(); 166 } else { 167 for (int i = 0; i < layer.countChildren(); i++) 168 addChild(layer.getChild(i)->copy())->unref(); 169 } 170 #else 171 for (int i = 0; i < layer.countChildren(); i++) 172 addChild(layer.getChild(i)->copy())->unref(); 173 #endif 174 175 KeyframesMap::const_iterator end = layer.m_animations.end(); 176 for (KeyframesMap::const_iterator it = layer.m_animations.begin(); it != end; ++it) { 177 // Deep copy the key's string, to avoid cross-thread refptr use 178 pair<String, int> newKey(it->first.first.threadsafeCopy(), it->first.second); 179 m_animations.add(newKey, it->second); 180 } 181 182 if (layer.m_replicatedLayer) { 183 // The replicated layer is always the first child 184 m_replicatedLayer = getChild(0); 185 m_replicatedLayer->setOriginalLayer(this); 186 } 187 188 if (layer.m_maskLayer) 189 m_maskLayer = layer.m_maskLayer->copy(); 190 191 #ifdef DEBUG_COUNT 192 ClassTracker::instance()->increment("LayerAndroid - recopy (UI)"); 193 ClassTracker::instance()->add(this); 194 #endif 195 } 196 197 LayerAndroid::~LayerAndroid() 198 { 199 if (m_imageCRC) 200 ImagesManager::instance()->releaseImage(m_imageCRC); 201 if (m_fixedPosition) 202 delete m_fixedPosition; 203 204 SkSafeUnref(m_maskLayer); 205 SkSafeUnref(m_content); 206 // Don't unref m_surface, owned by BaseLayerAndroid 207 m_animations.clear(); 208 #ifdef DEBUG_COUNT 209 ClassTracker::instance()->remove(this); 210 if (m_type == LayerAndroid::WebCoreLayer) 211 ClassTracker::instance()->decrement("LayerAndroid"); 212 else if (m_type == LayerAndroid::UILayer) 213 ClassTracker::instance()->decrement("LayerAndroid - recopy (UI)"); 214 #endif 215 } 216 217 float LayerAndroid::maxZoomScale() const 218 { 219 return m_content ? m_content->maxZoomScale() : 1.0f; 220 } 221 222 static int gDebugNbAnims = 0; 223 224 bool LayerAndroid::evaluateAnimations() 225 { 226 double time = WTF::currentTime(); 227 gDebugNbAnims = 0; 228 return evaluateAnimations(time); 229 } 230 231 bool LayerAndroid::hasAnimations() const 232 { 233 for (int i = 0; i < countChildren(); i++) { 234 if (getChild(i)->hasAnimations()) 235 return true; 236 } 237 return !!m_animations.size(); 238 } 239 240 bool LayerAndroid::evaluateAnimations(double time) 241 { 242 bool hasRunningAnimations = false; 243 for (int i = 0; i < countChildren(); i++) { 244 if (getChild(i)->evaluateAnimations(time)) 245 hasRunningAnimations = true; 246 } 247 248 m_hasRunningAnimations = false; 249 int nbAnims = 0; 250 KeyframesMap::const_iterator end = m_animations.end(); 251 for (KeyframesMap::const_iterator it = m_animations.begin(); it != end; ++it) { 252 gDebugNbAnims++; 253 nbAnims++; 254 LayerAndroid* currentLayer = const_cast<LayerAndroid*>(this); 255 m_hasRunningAnimations |= (it->second)->evaluate(currentLayer, time); 256 } 257 258 return hasRunningAnimations || m_hasRunningAnimations; 259 } 260 261 void LayerAndroid::initAnimations() { 262 // tell auto-initializing animations to start now 263 for (int i = 0; i < countChildren(); i++) 264 getChild(i)->initAnimations(); 265 266 KeyframesMap::const_iterator localBegin = m_animations.begin(); 267 KeyframesMap::const_iterator localEnd = m_animations.end(); 268 for (KeyframesMap::const_iterator localIt = localBegin; localIt != localEnd; ++localIt) 269 (localIt->second)->suggestBeginTime(WTF::currentTime()); 270 } 271 272 void LayerAndroid::addDirtyArea() 273 { 274 if (m_drawTransform.hasPerspective()) { 275 state()->doFrameworkFullInval(); 276 return; 277 } 278 279 // TODO: rewrite this to handle partial invalidate, and to handle base 280 // layer's large clip correctly 281 282 IntSize layerSize(getSize().width(), getSize().height()); 283 284 FloatRect area = 285 TilesManager::instance()->shader()->rectInViewCoord(m_drawTransform, layerSize); 286 FloatRect clippingRect = 287 TilesManager::instance()->shader()->rectInInvViewCoord(m_clippingRect); 288 FloatRect clip = 289 TilesManager::instance()->shader()->convertInvViewCoordToViewCoord(clippingRect); 290 291 area.intersect(clip); 292 IntRect dirtyArea(area.x(), area.y(), area.width(), area.height()); 293 294 state()->addDirtyArea(dirtyArea); 295 296 for (int i = 0; i < countChildren(); i++) 297 getChild(i)->addDirtyArea(); 298 } 299 300 void LayerAndroid::addAnimation(PassRefPtr<AndroidAnimation> prpAnim) 301 { 302 RefPtr<AndroidAnimation> anim = prpAnim; 303 pair<String, int> key(anim->nameCopy(), anim->type()); 304 removeAnimationsForProperty(anim->type()); 305 m_animations.add(key, anim); 306 } 307 308 void LayerAndroid::removeAnimationsForProperty(AnimatedPropertyID property) 309 { 310 KeyframesMap::const_iterator end = m_animations.end(); 311 Vector<pair<String, int> > toDelete; 312 for (KeyframesMap::const_iterator it = m_animations.begin(); it != end; ++it) { 313 if ((it->second)->type() == property) 314 toDelete.append(it->first); 315 } 316 317 for (unsigned int i = 0; i < toDelete.size(); i++) 318 m_animations.remove(toDelete[i]); 319 } 320 321 void LayerAndroid::removeAnimationsForKeyframes(const String& name) 322 { 323 KeyframesMap::const_iterator end = m_animations.end(); 324 Vector<pair<String, int> > toDelete; 325 for (KeyframesMap::const_iterator it = m_animations.begin(); it != end; ++it) { 326 if ((it->second)->isNamed(name)) 327 toDelete.append(it->first); 328 } 329 330 for (unsigned int i = 0; i < toDelete.size(); i++) 331 m_animations.remove(toDelete[i]); 332 } 333 334 // We only use the bounding rect of the layer as mask... 335 // FIXME: use a real mask? 336 void LayerAndroid::setMaskLayer(LayerAndroid* layer) 337 { 338 SkSafeRef(layer); 339 SkSafeUnref(m_maskLayer); 340 m_maskLayer = layer; 341 if (layer) 342 m_haveClip = true; 343 } 344 345 void LayerAndroid::setBackgroundColor(SkColor color) 346 { 347 m_backgroundColor = color; 348 } 349 350 FloatPoint LayerAndroid::translation() const 351 { 352 TransformationMatrix::DecomposedType tDecomp; 353 m_transform.decompose(tDecomp); 354 FloatPoint p(tDecomp.translateX, tDecomp.translateY); 355 return p; 356 } 357 358 IFrameLayerAndroid* LayerAndroid::updatePosition(SkRect viewport, 359 IFrameLayerAndroid* parentIframeLayer) 360 { 361 // subclasses can implement this virtual function to modify their position 362 if (m_fixedPosition) 363 return m_fixedPosition->updatePosition(viewport, parentIframeLayer); 364 return parentIframeLayer; 365 } 366 367 void LayerAndroid::updateLayerPositions(SkRect viewport, IFrameLayerAndroid* parentIframeLayer) 368 { 369 ALOGV("updating fixed positions, using viewport %fx%f - %fx%f", 370 viewport.fLeft, viewport.fTop, 371 viewport.width(), viewport.height()); 372 373 IFrameLayerAndroid* iframeLayer = updatePosition(viewport, parentIframeLayer); 374 375 int count = this->countChildren(); 376 for (int i = 0; i < count; i++) 377 this->getChild(i)->updateLayerPositions(viewport, iframeLayer); 378 } 379 380 void LayerAndroid::updatePositions() 381 { 382 // apply the viewport to us 383 if (!isPositionFixed()) { 384 // turn our fields into a matrix. 385 // 386 // FIXME: this should happen in the caller, and we should remove these 387 // fields from our subclass 388 SkMatrix matrix; 389 GLUtils::toSkMatrix(matrix, m_transform); 390 this->setMatrix(matrix); 391 } 392 393 // now apply it to our children 394 int count = this->countChildren(); 395 for (int i = 0; i < count; i++) 396 this->getChild(i)->updatePositions(); 397 } 398 399 void LayerAndroid::updateLocalTransformAndClip(const TransformationMatrix& parentMatrix, 400 const FloatRect& clipping) 401 { 402 FloatPoint position(getPosition().x() + m_replicatedLayerPosition.x() - getScrollOffset().x(), 403 getPosition().y() + m_replicatedLayerPosition.y() - getScrollOffset().y()); 404 405 if (isPositionFixed()) 406 m_drawTransform.makeIdentity(); 407 else 408 m_drawTransform = parentMatrix; 409 410 if (m_transform.isIdentity()) { 411 m_drawTransform.translate3d(position.x(), 412 position.y(), 413 0); 414 } else { 415 float originX = getAnchorPoint().x() * getWidth(); 416 float originY = getAnchorPoint().y() * getHeight(); 417 m_drawTransform.translate3d(originX + position.x(), 418 originY + position.y(), 419 anchorPointZ()); 420 m_drawTransform.multiply(m_transform); 421 m_drawTransform.translate3d(-originX, 422 -originY, 423 -anchorPointZ()); 424 } 425 426 m_drawTransformUnfudged = m_drawTransform; 427 if (m_drawTransform.isIdentityOrTranslation() 428 && surface() && surface()->allowTransformFudging()) { 429 // adjust the translation coordinates of the draw transform matrix so 430 // that layers (defined in content coordinates) will align to display/view pixels 431 432 // the surface may not allow fudging if it uses the draw transform at paint time 433 float desiredContentX = round(m_drawTransform.m41() * m_scale) / m_scale; 434 float desiredContentY = round(m_drawTransform.m42() * m_scale) / m_scale; 435 ALOGV("fudging translation from %f, %f to %f, %f", 436 m_drawTransform.m41(), m_drawTransform.m42(), 437 desiredContentX, desiredContentY); 438 m_drawTransform.setM41(desiredContentX); 439 m_drawTransform.setM42(desiredContentY); 440 } 441 442 m_zValue = TilesManager::instance()->shader()->zValue(m_drawTransform, 443 getSize().width(), 444 getSize().height()); 445 446 if (m_haveClip) { 447 // The clipping rect calculation and intersetion will be done in content 448 // coordinates. 449 FloatRect rect(0, 0, getWidth(), getHeight()); 450 FloatRect clip = m_drawTransform.mapRect(rect); 451 clip.intersect(clipping); 452 setDrawClip(clip); 453 } else { 454 setDrawClip(clipping); 455 } 456 ALOGV("%s - %d %f %f %f %f", 457 subclassType() == BaseLayer ? "BASE" : "nonbase", 458 m_haveClip, m_clippingRect.x(), m_clippingRect.y(), 459 m_clippingRect.width(), m_clippingRect.height()); 460 461 setVisible(m_backfaceVisibility || m_drawTransform.inverse().m33() >= 0); 462 } 463 464 void LayerAndroid::updateGLPositionsAndScale(const TransformationMatrix& parentMatrix, 465 const FloatRect& clipping, float opacity, 466 float scale, bool forceCalculation, 467 bool disableFixedElemUpdate) 468 { 469 m_scale = scale; 470 471 opacity *= getOpacity(); 472 setDrawOpacity(opacity); 473 474 // constantly recalculate the draw transform of layers that may require it (and their children) 475 forceCalculation |= hasDynamicTransform(); 476 477 forceCalculation &= !(disableFixedElemUpdate && isPositionFixed()); 478 if (forceCalculation) 479 updateLocalTransformAndClip(parentMatrix, clipping); 480 481 if (!countChildren() || !m_visible) 482 return; 483 484 TransformationMatrix childMatrix = m_drawTransformUnfudged; 485 // Flatten to 2D if the layer doesn't preserve 3D. 486 if (!preserves3D()) { 487 childMatrix.setM13(0); 488 childMatrix.setM23(0); 489 childMatrix.setM31(0); 490 childMatrix.setM32(0); 491 childMatrix.setM33(1); 492 childMatrix.setM34(0); 493 childMatrix.setM43(0); 494 } 495 496 // now apply it to our children 497 childMatrix.translate3d(getScrollOffset().x(), getScrollOffset().y(), 0); 498 if (!m_childrenTransform.isIdentity()) { 499 childMatrix.translate(getSize().width() * 0.5f, getSize().height() * 0.5f); 500 childMatrix.multiply(m_childrenTransform); 501 childMatrix.translate(-getSize().width() * 0.5f, -getSize().height() * 0.5f); 502 } 503 for (int i = 0; i < countChildren(); i++) 504 this->getChild(i)->updateGLPositionsAndScale(childMatrix, drawClip(), 505 opacity, scale, forceCalculation, 506 disableFixedElemUpdate); 507 } 508 509 bool LayerAndroid::visible() { 510 // TODO: avoid climbing tree each access 511 LayerAndroid* current = this; 512 while (current->getParent()) { 513 if (!current->m_visible) 514 return false; 515 current = static_cast<LayerAndroid*>(current->getParent()); 516 } 517 return true; 518 } 519 520 void LayerAndroid::setContentsImage(SkBitmapRef* img) 521 { 522 ImageTexture* image = ImagesManager::instance()->setImage(img); 523 ImagesManager::instance()->releaseImage(m_imageCRC); 524 m_imageCRC = image ? image->imageCRC() : 0; 525 } 526 527 void LayerAndroid::setContent(LayerContent* content) 528 { 529 SkSafeRef(content); 530 SkSafeUnref(m_content); 531 m_content = content; 532 } 533 534 bool LayerAndroid::canUpdateWithBlit() 535 { 536 if (!m_content || !m_scale) 537 return false; 538 IntRect clip = clippedRect(); 539 IntRect dirty = m_dirtyRegion.getBounds(); 540 dirty.intersect(clip); 541 PrerenderedInval* prerendered = m_content->prerenderForRect(dirty); 542 if (!prerendered) 543 return false; 544 // Check that the scales are "close enough" to produce the same rects 545 FloatRect screenArea = prerendered->screenArea; 546 screenArea.scale(1 / m_scale); 547 IntRect enclosingDocArea = enclosingIntRect(screenArea); 548 return enclosingDocArea == prerendered->area; 549 } 550 551 bool LayerAndroid::needsTexture() 552 { 553 return (m_content && !m_content->isEmpty()) 554 || (m_originalLayer && m_originalLayer->needsTexture()); 555 } 556 557 IntRect LayerAndroid::clippedRect() const 558 { 559 IntRect r(0, 0, getWidth(), getHeight()); 560 IntRect tr = m_drawTransform.mapRect(r); 561 IntRect cr = TilesManager::instance()->shader()->clippedRectWithVisibleContentRect(tr); 562 IntRect rect = m_drawTransform.inverse().mapRect(cr); 563 return rect; 564 } 565 566 int LayerAndroid::nbLayers() 567 { 568 int nb = 0; 569 int count = this->countChildren(); 570 for (int i = 0; i < count; i++) 571 nb += this->getChild(i)->nbLayers(); 572 return nb+1; 573 } 574 575 int LayerAndroid::nbTexturedLayers() 576 { 577 int nb = 0; 578 int count = this->countChildren(); 579 for (int i = 0; i < count; i++) 580 nb += this->getChild(i)->nbTexturedLayers(); 581 if (needsTexture()) 582 nb++; 583 return nb; 584 } 585 586 void LayerAndroid::showLayer(int indent) 587 { 588 char spaces[256]; 589 memset(spaces, 0, 256); 590 for (int i = 0; i < indent; i++) 591 spaces[i] = ' '; 592 593 if (!indent) { 594 ALOGD("\n\n--- LAYERS TREE ---"); 595 IntRect contentViewport(TilesManager::instance()->shader()->contentViewport()); 596 ALOGD("contentViewport(%d, %d, %d, %d)", 597 contentViewport.x(), contentViewport.y(), 598 contentViewport.width(), contentViewport.height()); 599 } 600 601 IntRect r(0, 0, getWidth(), getHeight()); 602 IntRect tr = m_drawTransform.mapRect(r); 603 IntRect visible = visibleContentArea(); 604 IntRect clip(m_clippingRect.x(), m_clippingRect.y(), 605 m_clippingRect.width(), m_clippingRect.height()); 606 ALOGD("%s s:%x %s %s (%d) [%d:%x - 0x%x] - %s %s - area (%d, %d, %d, %d) - visible (%d, %d, %d, %d) " 607 "clip (%d, %d, %d, %d) %s %s m_content(%x), pic w: %d h: %d originalLayer: %x %d", 608 spaces, m_surface, m_haveClip ? "CLIP LAYER" : "", subclassName(), 609 subclassType(), uniqueId(), this, m_owningLayer, 610 needsTexture() ? "needsTexture" : "", 611 m_imageCRC ? "hasImage" : "", 612 tr.x(), tr.y(), tr.width(), tr.height(), 613 visible.x(), visible.y(), visible.width(), visible.height(), 614 clip.x(), clip.y(), clip.width(), clip.height(), 615 contentIsScrollable() ? "SCROLLABLE" : "", 616 isPositionFixed() ? "FIXED" : "", 617 m_content, 618 m_content ? m_content->width() : -1, 619 m_content ? m_content->height() : -1, 620 m_originalLayer, m_originalLayer ? m_originalLayer->uniqueId() : -1); 621 622 int count = this->countChildren(); 623 for (int i = 0; i < count; i++) 624 this->getChild(i)->showLayer(indent + 2); 625 } 626 627 void LayerAndroid::mergeInvalsInto(LayerAndroid* replacementTree) 628 { 629 int count = this->countChildren(); 630 for (int i = 0; i < count; i++) 631 this->getChild(i)->mergeInvalsInto(replacementTree); 632 633 LayerAndroid* replacementLayer = replacementTree->findById(uniqueId()); 634 if (replacementLayer) 635 replacementLayer->markAsDirty(m_dirtyRegion); 636 } 637 638 static inline bool compareLayerZ(const LayerAndroid* a, const LayerAndroid* b) 639 { 640 return a->zValue() > b->zValue(); 641 } 642 643 bool LayerAndroid::canJoinSurface(Surface* surface) 644 { 645 #ifdef DISABLE_LAYER_MERGE 646 return false; 647 #else 648 // returns true if the layer can be merged onto the surface (group of layers) 649 if (!surface) 650 return false; 651 652 LayerAndroid* lastLayer = surface->getFirstLayer(); 653 654 // isolate intrinsically composited layers 655 if (needsIsolatedSurface() || lastLayer->needsIsolatedSurface()) 656 return false; 657 658 // TODO: investigate potential for combining transformed layers 659 if (!m_drawTransform.isIdentityOrTranslation() 660 || !lastLayer->m_drawTransform.isIdentityOrTranslation()) 661 return false; 662 663 // TODO: compare other layer properties - fixed? overscroll? transformed? 664 return true; 665 #endif 666 } 667 668 void LayerAndroid::assignSurfaces(LayerMergeState* mergeState) 669 { 670 // recurse through layers in draw order, and merge layers when able 671 672 bool needNewSurface = !mergeState->currentSurface 673 || mergeState->nonMergeNestedLevel > 0 674 || !canJoinSurface(mergeState->currentSurface); 675 676 if (needNewSurface) { 677 mergeState->currentSurface = new Surface(); 678 mergeState->surfaceList->append(mergeState->currentSurface); 679 } 680 681 #ifdef LAYER_MERGING_DEBUG 682 ALOGD("%*slayer %p(%d) rl %p %s surface %p lvl: %d, fixed %d, anim %d, intCom %d, haveClip %d scroll %d hasText (layer: %d surface: %d) hasContent %d size %.2f x %.2f", 683 4*mergeState->depth, "", this, m_uniqueId, m_owningLayer, 684 needNewSurface ? "NEW" : "joins", mergeState->currentSurface, 685 mergeState->nonMergeNestedLevel, 686 isPositionFixed(), m_animations.size() != 0, 687 m_intrinsicallyComposited, 688 m_haveClip, 689 contentIsScrollable(), m_content ? m_content->hasText() : -1, 690 mergeState->currentSurface ? mergeState->currentSurface->hasText() : -1, 691 needsTexture(), getWidth(), getHeight()); 692 #endif 693 694 mergeState->currentSurface->addLayer(this, m_drawTransform); 695 m_surface = mergeState->currentSurface; 696 697 if (hasDynamicTransform()) { 698 // disable layer merging within the children of these layer types 699 mergeState->nonMergeNestedLevel++; 700 } 701 702 // pass the surface through children in drawing order, so that they may 703 // attach themselves (and paint on it) if possible, or ignore it and create 704 // a new one if not 705 int count = this->countChildren(); 706 if (count > 0) { 707 mergeState->depth++; 708 Vector <LayerAndroid*> sublayers; 709 for (int i = 0; i < count; i++) 710 sublayers.append(getChild(i)); 711 712 // sort for the transparency 713 std::stable_sort(sublayers.begin(), sublayers.end(), compareLayerZ); 714 for (int i = 0; i < count; i++) 715 sublayers[i]->assignSurfaces(mergeState); 716 mergeState->depth--; 717 } 718 719 if (hasDynamicTransform()) { 720 // re-enable joining 721 mergeState->nonMergeNestedLevel--; 722 723 // disallow layers painting after to join with this surface 724 mergeState->currentSurface = 0; 725 } 726 727 if (needsIsolatedSurface()) 728 mergeState->currentSurface = 0; 729 730 } 731 732 // We call this in WebViewCore, when copying the tree of layers. 733 // As we construct a new tree that will be passed on the UI, 734 // we mark the webkit-side tree as having no more dirty region 735 // (otherwise we would continuously have those dirty region UI-side) 736 void LayerAndroid::clearDirtyRegion() 737 { 738 int count = this->countChildren(); 739 for (int i = 0; i < count; i++) 740 this->getChild(i)->clearDirtyRegion(); 741 742 m_dirtyRegion.setEmpty(); 743 } 744 745 int LayerAndroid::setHwAccelerated(bool hwAccelerated) 746 { 747 int flags = InvalidateNone; 748 int count = this->countChildren(); 749 for (int i = 0; i < count; i++) 750 flags |= this->getChild(i)->setHwAccelerated(hwAccelerated); 751 752 return flags | onSetHwAccelerated(hwAccelerated); 753 } 754 755 FloatRect LayerAndroid::fullContentAreaMapped() const 756 { 757 FloatRect area(0,0, getWidth(), getHeight()); 758 FloatRect globalArea = m_drawTransform.mapRect(area); 759 return globalArea; 760 } 761 762 IntRect LayerAndroid::fullContentArea() const 763 { 764 IntRect area(0,0, getWidth(), getHeight()); 765 return area; 766 } 767 768 IntRect LayerAndroid::visibleContentArea(bool force3dContentVisible) const 769 { 770 IntRect area = fullContentArea(); 771 if (subclassType() == LayerAndroid::FixedBackgroundImageLayer) 772 return area; 773 774 // If transform isn't limited to 2D space, return the entire content area. 775 // Transforming from layers to content coordinates and back doesn't 776 // preserve 3D. 777 if (force3dContentVisible && GLUtils::has3dTransform(m_drawTransform)) 778 return area; 779 780 // First, we get the transformed area of the layer, 781 // in content coordinates 782 IntRect rect = m_drawTransform.mapRect(area); 783 784 // Then we apply the clipping 785 IntRect clip(m_clippingRect); 786 rect.intersect(clip); 787 788 // Now clip with the viewport in content coordinate 789 IntRect contentViewport(TilesManager::instance()->shader()->contentViewport()); 790 rect.intersect(contentViewport); 791 792 // Finally, let's return the visible area, in layers coordinate 793 return m_drawTransform.inverse().mapRect(rect); 794 } 795 796 bool LayerAndroid::drawCanvas(SkCanvas* canvas, bool drawChildren, PaintStyle style) 797 { 798 if (!m_visible) 799 return false; 800 801 bool askScreenUpdate = false; 802 803 { 804 SkAutoCanvasRestore acr(canvas, true); 805 SkRect r; 806 r.set(m_clippingRect.x(), m_clippingRect.y(), 807 m_clippingRect.x() + m_clippingRect.width(), 808 m_clippingRect.y() + m_clippingRect.height()); 809 if (canvas->clipRect(r)) { 810 SkMatrix matrix; 811 GLUtils::toSkMatrix(matrix, m_drawTransform); 812 SkMatrix canvasMatrix = canvas->getTotalMatrix(); 813 matrix.postConcat(canvasMatrix); 814 canvas->setMatrix(matrix); 815 onDraw(canvas, m_drawOpacity, 0, style); 816 } 817 } 818 819 if (!drawChildren) 820 return false; 821 822 // When the layer is dirty, the UI thread should be notified to redraw. 823 askScreenUpdate |= drawChildrenCanvas(canvas, style); 824 return askScreenUpdate; 825 } 826 827 void LayerAndroid::collect3dRenderingContext(Vector<LayerAndroid*>& layersInContext) 828 { 829 layersInContext.append(this); 830 if (preserves3D()) { 831 int count = countChildren(); 832 for (int i = 0; i < count; i++) 833 getChild(i)->collect3dRenderingContext(layersInContext); 834 } 835 } 836 837 bool LayerAndroid::drawSurfaceAndChildrenGL() 838 { 839 bool askScreenUpdate = false; 840 if (surface()->getFirstLayer() == this) 841 askScreenUpdate |= surface()->drawGL(false); 842 843 // return early, since children will be painted directly by drawTreeSurfacesGL 844 if (preserves3D()) 845 return askScreenUpdate; 846 847 int count = countChildren(); 848 Vector <LayerAndroid*> sublayers; 849 for (int i = 0; i < count; i++) 850 sublayers.append(getChild(i)); 851 852 std::stable_sort(sublayers.begin(), sublayers.end(), compareLayerZ); 853 for (int i = 0; i < count; i++) 854 askScreenUpdate |= sublayers[i]->drawTreeSurfacesGL(); 855 856 return askScreenUpdate; 857 } 858 859 bool LayerAndroid::drawTreeSurfacesGL() 860 { 861 bool askScreenUpdate = false; 862 if (preserves3D()) { 863 // hit a preserve-3d layer, so render the entire 3D rendering context in z order 864 Vector<LayerAndroid*> contextLayers; 865 collect3dRenderingContext(contextLayers); 866 std::stable_sort(contextLayers.begin(), contextLayers.end(), compareLayerZ); 867 868 for (unsigned int i = 0; i < contextLayers.size(); i++) 869 askScreenUpdate |= contextLayers[i]->drawSurfaceAndChildrenGL(); 870 } else 871 askScreenUpdate |= drawSurfaceAndChildrenGL(); 872 873 return askScreenUpdate; 874 } 875 876 bool LayerAndroid::drawGL(bool layerTilesDisabled) 877 { 878 if (!layerTilesDisabled && m_imageCRC) { 879 ImageTexture* imageTexture = ImagesManager::instance()->retainImage(m_imageCRC); 880 if (imageTexture) 881 imageTexture->drawGL(this, getOpacity()); 882 ImagesManager::instance()->releaseImage(m_imageCRC); 883 } 884 885 state()->glExtras()->drawGL(this); 886 bool askScreenUpdate = false; 887 888 if (m_hasRunningAnimations) 889 askScreenUpdate = true; 890 891 return askScreenUpdate; 892 } 893 894 bool LayerAndroid::drawChildrenCanvas(SkCanvas* canvas, PaintStyle style) 895 { 896 bool askScreenUpdate = false; 897 int count = this->countChildren(); 898 if (count > 0) { 899 Vector <LayerAndroid*> sublayers; 900 for (int i = 0; i < count; i++) 901 sublayers.append(this->getChild(i)); 902 903 // now we sort for the transparency 904 std::stable_sort(sublayers.begin(), sublayers.end(), compareLayerZ); 905 for (int i = 0; i < count; i++) { 906 LayerAndroid* layer = sublayers[i]; 907 askScreenUpdate |= layer->drawCanvas(canvas, true, style); 908 } 909 } 910 911 return askScreenUpdate; 912 } 913 914 void LayerAndroid::contentDraw(SkCanvas* canvas, PaintStyle style) 915 { 916 if (m_maskLayer && m_maskLayer->m_content) { 917 // TODO: we should use a shader instead of doing 918 // the masking in software 919 920 if (m_originalLayer) 921 m_originalLayer->m_content->draw(canvas); 922 else if (m_content) 923 m_content->draw(canvas); 924 925 SkPaint maskPaint; 926 maskPaint.setXfermodeMode(SkXfermode::kDstIn_Mode); 927 int count = canvas->saveLayer(0, &maskPaint, SkCanvas::kHasAlphaLayer_SaveFlag); 928 m_maskLayer->m_content->draw(canvas); 929 canvas->restoreToCount(count); 930 931 } else if (m_content) 932 m_content->draw(canvas); 933 934 if (TilesManager::instance()->getShowVisualIndicator()) { 935 float w = getSize().width(); 936 float h = getSize().height(); 937 SkPaint paint; 938 939 if (style == MergedLayers) 940 paint.setARGB(255, 255, 255, 0); 941 else if (style == UnmergedLayers) 942 paint.setARGB(255, 255, 0, 0); 943 else if (style == FlattenedLayers) 944 paint.setARGB(255, 255, 0, 255); 945 946 canvas->drawLine(0, 0, w, h, paint); 947 canvas->drawLine(0, h, w, 0, paint); 948 949 canvas->drawLine(0, 0, 0, h-1, paint); 950 canvas->drawLine(0, h-1, w-1, h-1, paint); 951 canvas->drawLine(w-1, h-1, w-1, 0, paint); 952 canvas->drawLine(w-1, 0, 0, 0, paint); 953 954 static SkTypeface* s_typeface = 0; 955 if (!s_typeface) 956 s_typeface = SkTypeface::CreateFromName("", SkTypeface::kBold); 957 paint.setARGB(255, 0, 0, 255); 958 paint.setTextSize(17); 959 char str[256]; 960 snprintf(str, 256, "%d", uniqueId()); 961 paint.setTypeface(s_typeface); 962 canvas->drawText(str, strlen(str), 2, h - 2, paint); 963 } 964 965 if (m_fixedPosition) 966 return m_fixedPosition->contentDraw(canvas, style); 967 } 968 969 void LayerAndroid::onDraw(SkCanvas* canvas, SkScalar opacity, 970 android::DrawExtra* extra, PaintStyle style) 971 { 972 if (m_haveClip) { 973 SkRect r; 974 r.set(0, 0, getSize().width(), getSize().height()); 975 canvas->clipRect(r); 976 return; 977 } 978 979 // only continue drawing if layer is drawable 980 if (!m_content && !m_imageCRC) 981 return; 982 983 // we just have this save/restore for opacity... 984 SkAutoCanvasRestore restore(canvas, true); 985 986 int canvasOpacity = SkScalarRound(opacity * 255); 987 if (canvasOpacity < 255) 988 canvas->setDrawFilter(new OpacityDrawFilter(canvasOpacity)); 989 990 if (m_imageCRC) { 991 ImageTexture* imageTexture = ImagesManager::instance()->retainImage(m_imageCRC); 992 m_dirtyRegion.setEmpty(); 993 if (imageTexture) { 994 SkRect dest; 995 dest.set(0, 0, getSize().width(), getSize().height()); 996 imageTexture->drawCanvas(canvas, dest); 997 } 998 ImagesManager::instance()->releaseImage(m_imageCRC); 999 } 1000 contentDraw(canvas, style); 1001 if (extra) 1002 extra->draw(canvas, this); 1003 } 1004 1005 void LayerAndroid::setFixedPosition(FixedPositioning* position) { 1006 if (m_fixedPosition && m_fixedPosition != position) 1007 delete m_fixedPosition; 1008 m_fixedPosition = position; 1009 } 1010 1011 void LayerAndroid::dumpLayer(LayerDumper* dumper) const 1012 { 1013 dumper->writeIntVal("layerId", m_uniqueId); 1014 dumper->writeIntVal("haveClip", m_haveClip); 1015 dumper->writeIntVal("isFixed", isPositionFixed()); 1016 1017 dumper->writeFloatVal("opacity", getOpacity()); 1018 dumper->writeSize("size", getSize()); 1019 dumper->writePoint("position", getPosition()); 1020 dumper->writePoint("anchor", getAnchorPoint()); 1021 1022 dumper->writeMatrix("drawMatrix", m_drawTransform); 1023 dumper->writeMatrix("transformMatrix", m_transform); 1024 dumper->writeRect("clippingRect", SkRect(m_clippingRect)); 1025 1026 if (m_content) { 1027 dumper->writeIntVal("m_content.width", m_content->width()); 1028 dumper->writeIntVal("m_content.height", m_content->height()); 1029 } 1030 1031 if (m_fixedPosition) 1032 m_fixedPosition->dumpLayer(dumper); 1033 } 1034 1035 void LayerAndroid::dumpLayers(LayerDumper* dumper) const 1036 { 1037 dumper->beginLayer(subclassName(), this); 1038 dumpLayer(dumper); 1039 1040 dumper->beginChildren(countChildren()); 1041 if (countChildren()) { 1042 for (int i = 0; i < countChildren(); i++) 1043 getChild(i)->dumpLayers(dumper); 1044 } 1045 dumper->endChildren(); 1046 dumper->endLayer(); 1047 } 1048 1049 LayerAndroid* LayerAndroid::findById(int match) 1050 { 1051 if (m_uniqueId == match) 1052 return this; 1053 for (int i = 0; i < countChildren(); i++) { 1054 LayerAndroid* result = getChild(i)->findById(match); 1055 if (result) 1056 return result; 1057 } 1058 return 0; 1059 } 1060 1061 } // namespace WebCore 1062 1063 #endif // USE(ACCELERATED_COMPOSITING) 1064