/* MapLine::clearUnneededTextures * Clears any textures not needed on the line (eg. a front upper * texture that would be invisible) *******************************************************************/ void MapLine::clearUnneededTextures() { // Check needed textures int tex = needsTexture(); // Clear any unneeded textures if (side1) { if ((tex & TEX_FRONT_MIDDLE) == 0) setStringProperty("side1.texturemiddle", "-"); if ((tex & TEX_FRONT_UPPER) == 0) setStringProperty("side1.texturetop", "-"); if ((tex & TEX_FRONT_LOWER) == 0) setStringProperty("side1.texturebottom", "-"); } if (side2) { if ((tex & TEX_BACK_MIDDLE) == 0) setStringProperty("side2.texturemiddle", "-"); if ((tex & TEX_BACK_UPPER) == 0) setStringProperty("side2.texturetop", "-"); if ((tex & TEX_BACK_LOWER) == 0) setStringProperty("side2.texturebottom", "-"); } }
int LayerAndroid::nbTexturedLayers() { int nb = 0; int count = this->countChildren(); for (int i = 0; i < count; i++) nb += this->getChild(i)->nbTexturedLayers(); if (needsTexture()) nb++; return nb; }
void Surface::prepareGL(bool layerTilesDisabled, bool updateWithBlit) { bool tilesDisabled = layerTilesDisabled && !isBase(); if (!m_surfaceBacking) { ALOGV("prepareGL on Surf %p, no SurfBack, needsTexture? %d", this, m_surfaceBacking, needsTexture()); if (needsTexture() || (isBase() && layerTilesDisabled)) m_surfaceBacking = new SurfaceBacking(isBase()); else return; } if (tilesDisabled) { m_surfaceBacking->discardTextures(); } else { bool allowZoom = hasText(); // only allow for scale > 1 if painting vectors IntRect prepareArea = computePrepareArea(); IntRect fullArea = fullContentArea(); ALOGV("prepareGL on Surf %p with SurfBack %p, %d layers, first layer %s (%d) " "prepareArea(%d, %d - %d x %d) fullArea(%d, %d - %d x %d)", this, m_surfaceBacking, m_layers.size(), getFirstLayer()->subclassName().ascii().data(), getFirstLayer()->uniqueId(), prepareArea.x(), prepareArea.y(), prepareArea.width(), prepareArea.height(), fullArea.x(), fullArea.y(), fullArea.width(), fullArea.height()); m_surfaceBacking->prepareGL(getFirstLayer()->state(), allowZoom, prepareArea, fullArea, this, useAggressiveRendering(), updateWithBlit); } for (size_t i = 0; i < m_layers.size(); i++) { LayerContent* content = m_layers[i]->content(); if (content) content->clearPrerenders(); } }
bool Surface::canUpdateWithBlit() { // If we don't have a texture, we have nothing to update and thus can take // the fast path if (!needsTexture()) return true; // If we have a surface backing that isn't ready, we can't update with a blit // If it is ready, then check to see if it is dirty. We can only call isDirty() // if isReady() returns true if (!m_surfaceBacking) return false; if (!m_surfaceBacking->isReady()) return false; if (!m_surfaceBacking->isDirty()) return true; if (!singleLayer()) return false; return getFirstLayer()->canUpdateWithBlit(); }
void LayerAndroid::showLayer(int indent) { char spaces[256]; memset(spaces, 0, 256); for (int i = 0; i < indent; i++) spaces[i] = ' '; if (!indent) { ALOGD("\n\n--- LAYERS TREE ---"); IntRect contentViewport(TilesManager::instance()->shader()->contentViewport()); ALOGD("contentViewport(%d, %d, %d, %d)", contentViewport.x(), contentViewport.y(), contentViewport.width(), contentViewport.height()); } IntRect r(0, 0, getWidth(), getHeight()); IntRect tr = m_drawTransform.mapRect(r); IntRect visible = visibleContentArea(); IntRect clip(m_clippingRect.x(), m_clippingRect.y(), m_clippingRect.width(), m_clippingRect.height()); ALOGD("%s s:%x %s %s (%d) [%d:%x - 0x%x] - %s %s - area (%d, %d, %d, %d) - visible (%d, %d, %d, %d) " "clip (%d, %d, %d, %d) %s %s m_content(%x), pic w: %d h: %d originalLayer: %x %d", spaces, m_surface, m_haveClip ? "CLIP LAYER" : "", subclassName().ascii().data(), subclassType(), uniqueId(), this, m_owningLayer, needsTexture() ? "needsTexture" : "", m_imageCRC ? "hasImage" : "", tr.x(), tr.y(), tr.width(), tr.height(), visible.x(), visible.y(), visible.width(), visible.height(), clip.x(), clip.y(), clip.width(), clip.height(), contentIsScrollable() ? "SCROLLABLE" : "", isPositionFixed() ? "FIXED" : "", m_content, m_content ? m_content->width() : -1, m_content ? m_content->height() : -1, m_originalLayer, m_originalLayer ? m_originalLayer->uniqueId() : -1); int count = this->countChildren(); for (int i = 0; i < count; i++) this->getChild(i)->showLayer(indent + 2); }
bool Surface::tryUpdateSurface(Surface* oldSurface) { if (!needsTexture() || !oldSurface->needsTexture()) return false; // merge surfaces based on first layer ID if (getFirstLayer()->uniqueId() != oldSurface->getFirstLayer()->uniqueId()) return false; m_surfaceBacking = oldSurface->m_surfaceBacking; SkSafeRef(m_surfaceBacking); ALOGV("%p taking old SurfBack %p from surface %p, nt %d", this, m_surfaceBacking, oldSurface, oldSurface->needsTexture()); if (!m_surfaceBacking) { // no SurfBack to inval, so don't worry about it. return true; } SkRegion invalRegion; bool fullInval = false; if (singleLayer() && oldSurface->singleLayer()) { // both are single matching layers, simply apply inval SkRegion* layerInval = getFirstLayer()->getInvalRegion(); invalRegion = *layerInval; if (isBase()) { // the base layer paints outside it's content area to ensure the // viewport is convered, so fully invalidate all tiles if its size // changes to ensure no stale content remains LayerContent* newContent = getFirstLayer()->content(); LayerContent* oldContent = oldSurface->getFirstLayer()->content(); fullInval = newContent->width() != oldContent->width() || newContent->height() != oldContent->height(); } } else { fullInval = m_layers.size() != oldSurface->m_layers.size(); if (!fullInval) { for (unsigned int i = 0; i < m_layers.size(); i++) { if ((m_layers[i]->uniqueId() != oldSurface->m_layers[i]->uniqueId()) || (m_layers[i]->fullContentAreaMapped() != oldSurface->m_layers[i]->fullContentAreaMapped())) { // layer list has changed, fully invalidate // TODO: partially invalidate based on layer size/position fullInval = true; break; } else if (!m_layers[i]->getInvalRegion()->isEmpty()) { // merge layer inval - translate the layer's inval region into surface coordinates // TODO: handle scale/3d transform mapping FloatRect layerPos = m_layers[i]->fullContentAreaMapped(); m_layers[i]->getInvalRegion()->translate(layerPos.x(), layerPos.y()); invalRegion.op(*(m_layers[i]->getInvalRegion()), SkRegion::kUnion_Op); } } } } if (fullInval) invalRegion.setRect(-1e8, -1e8, 2e8, 2e8); m_surfaceBacking->markAsDirty(invalRegion); return true; }
void LayerAndroid::assignSurfaces(LayerMergeState* mergeState) { // recurse through layers in draw order, and merge layers when able bool needNewSurface = !mergeState->currentSurface || mergeState->nonMergeNestedLevel > 0 || !canJoinSurface(mergeState->currentSurface); if (needNewSurface) { mergeState->currentSurface = new Surface(); mergeState->surfaceList->append(mergeState->currentSurface); } #ifdef LAYER_MERGING_DEBUG 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", 4*mergeState->depth, "", this, m_uniqueId, m_owningLayer, needNewSurface ? "NEW" : "joins", mergeState->currentSurface, mergeState->nonMergeNestedLevel, isPositionFixed(), m_animations.size() != 0, m_intrinsicallyComposited, m_haveClip, contentIsScrollable(), m_content ? m_content->hasText() : -1, mergeState->currentSurface ? mergeState->currentSurface->hasText() : -1, needsTexture(), getWidth(), getHeight()); #endif mergeState->currentSurface->addLayer(this, m_drawTransform); m_surface = mergeState->currentSurface; if (hasDynamicTransform()) { // disable layer merging within the children of these layer types mergeState->nonMergeNestedLevel++; } // pass the surface through children in drawing order, so that they may // attach themselves (and paint on it) if possible, or ignore it and create // a new one if not int count = this->countChildren(); if (count > 0) { mergeState->depth++; Vector <LayerAndroid*> sublayers; for (int i = 0; i < count; i++) sublayers.append(getChild(i)); // sort for the transparency std::stable_sort(sublayers.begin(), sublayers.end(), compareLayerZ); for (int i = 0; i < count; i++) sublayers[i]->assignSurfaces(mergeState); mergeState->depth--; } if (hasDynamicTransform()) { // re-enable joining mergeState->nonMergeNestedLevel--; // disallow layers painting after to join with this surface mergeState->currentSurface = 0; } if (needsIsolatedSurface()) mergeState->currentSurface = 0; }