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