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