void FullscreenVideoController::LayerClient::platformCALayerLayoutSublayersOfLayer(PlatformCALayer* layer) { ASSERT_ARG(layer, layer == m_parent->m_rootChild); HTMLVideoElement* videoElement = m_parent->m_videoElement.get(); if (!videoElement) return; PlatformCALayer* videoLayer = PlatformCALayer::platformCALayer(videoElement->platformLayer()); if (!videoLayer || videoLayer->superlayer() != layer) return; FloatRect layerBounds = layer->bounds(); FloatSize videoSize = videoElement->player()->naturalSize(); float scaleFactor; if (videoSize.aspectRatio() > layerBounds.size().aspectRatio()) scaleFactor = layerBounds.width() / videoSize.width(); else scaleFactor = layerBounds.height() / videoSize.height(); videoSize.scale(scaleFactor); // Calculate the centered position based on the videoBounds and layerBounds: FloatPoint videoPosition; FloatPoint videoOrigin; videoOrigin.setX((layerBounds.width() - videoSize.width()) * 0.5); videoOrigin.setY((layerBounds.height() - videoSize.height()) * 0.5); videoLayer->setPosition(videoOrigin); videoLayer->setBounds(FloatRect(FloatPoint(), videoSize)); }
void TileGrid::drawTileMapContents(CGContextRef context, CGRect layerBounds) const { CGContextSetRGBFillColor(context, 0.3, 0.3, 0.3, 1); CGContextFillRect(context, layerBounds); CGFloat scaleFactor = layerBounds.size.width / m_controller.bounds().width(); CGFloat contextScale = scaleFactor / m_scale; CGContextScaleCTM(context, contextScale, contextScale); for (TileMap::const_iterator it = m_tiles.begin(), end = m_tiles.end(); it != end; ++it) { const TileInfo& tileInfo = it->value; PlatformCALayer* tileLayer = tileInfo.layer.get(); CGFloat red = 1; CGFloat green = 1; CGFloat blue = 1; CGFloat alpha = 1; if (tileInfo.hasStaleContent) { red = 0.25; green = 0.125; blue = 0; } else if (m_controller.shouldAggressivelyRetainTiles() && tileInfo.cohort != VisibleTileCohort) { red = 0.8; green = 0.8; blue = 0.8; } TileCohort newestCohort = newestTileCohort(); TileCohort oldestCohort = oldestTileCohort(); if (!m_controller.shouldAggressivelyRetainTiles() && tileInfo.cohort != VisibleTileCohort && newestCohort > oldestCohort) alpha = 1 - (static_cast<float>((newestCohort - tileInfo.cohort)) / (newestCohort - oldestCohort)); CGContextSetRGBFillColor(context, red, green, blue, alpha); if (tileLayer->superlayer()) { CGContextSetLineWidth(context, 0.5 / contextScale); CGContextSetRGBStrokeColor(context, 0, 0, 0, 1); } else { CGContextSetLineWidth(context, 1 / contextScale); CGContextSetRGBStrokeColor(context, 0.2, 0.1, 0.9, 1); } CGRect frame = CGRectMake(tileLayer->position().x(), tileLayer->position().y(), tileLayer->bounds().size().width(), tileLayer->bounds().size().height()); CGContextFillRect(context, frame); CGContextStrokeRect(context, frame); CGContextSetRGBFillColor(context, 0, 0, 0, 0.5); String repaintCount = String::number(m_tileRepaintCounts.get(tileLayer)); CGContextSaveGState(context); tileLayer->drawTextAtPoint(context, frame.origin.x + 64, frame.origin.y + 192, CGSizeMake(3, -3), 58, repaintCount.ascii().data(), repaintCount.length()); CGContextRestoreGState(context); } }
void PlatformCALayerRemote::replaceSublayer(PlatformCALayer& reference, PlatformCALayer& layer) { ASSERT(reference.superlayer() == this); Ref<PlatformCALayer> layerProtector(layer); layer.removeFromSuperlayer(); size_t referenceIndex = m_children.find(&reference); if (referenceIndex != notFound) { m_children[referenceIndex]->removeFromSuperlayer(); m_children.insert(referenceIndex, &layer); downcast<PlatformCALayerRemote>(layer).m_superlayer = this; } m_properties.notePropertiesChanged(RemoteLayerTreeTransaction::ChildrenChanged); }
void PlatformCALayerWin::replaceSublayer(PlatformCALayer& reference, PlatformCALayer& newLayer) { // This must not use direct calls to allow PlatformCALayerInternal to override. ASSERT_ARG(reference, reference.superlayer() == this); if (&reference == &newLayer) return; int referenceIndex = intern(this)->indexOfSublayer(&reference); ASSERT(referenceIndex != -1); if (referenceIndex == -1) return; reference.removeFromSuperlayer(); newLayer.removeFromSuperlayer(); insertSublayer(newLayer, referenceIndex); }
void TileGrid::setTileNeedsDisplayInRect(const TileIndex& tileIndex, TileInfo& tileInfo, const IntRect& repaintRectInTileCoords, const IntRect& coverageRectInTileCoords) { PlatformCALayer* tileLayer = tileInfo.layer.get(); IntRect tileRect = rectForTileIndex(tileIndex); FloatRect tileRepaintRect = tileRect; tileRepaintRect.intersect(repaintRectInTileCoords); if (tileRepaintRect.isEmpty()) return; tileRepaintRect.moveBy(-tileRect.location()); // We could test for intersection with the visible rect. This would reduce painting yet more, // but may make scrolling stale tiles into view more frequent. if (tileRect.intersects(coverageRectInTileCoords) && tileLayer->superlayer()) { tileLayer->setNeedsDisplayInRect(tileRepaintRect); if (m_controller.rootLayer().owner()->platformCALayerShowRepaintCounter(0)) { FloatRect indicatorRect(0, 0, 52, 27); tileLayer->setNeedsDisplayInRect(indicatorRect); } } else tileInfo.hasStaleContent = true; }
void TileGrid::revalidateTiles(TileValidationPolicy validationPolicy) { FloatRect coverageRect = m_controller.coverageRect(); IntRect bounds = m_controller.bounds(); if (coverageRect.isEmpty() || bounds.isEmpty()) return; FloatRect scaledRect(coverageRect); scaledRect.scale(m_scale); IntRect coverageRectInTileCoords(enclosingIntRect(scaledRect)); TileCohort currCohort = nextTileCohort(); unsigned tilesInCohort = 0; double minimumRevalidationTimerDuration = std::numeric_limits<double>::max(); bool needsTileRevalidation = false; // Move tiles newly outside the coverage rect into the cohort map. for (TileMap::iterator it = m_tiles.begin(), end = m_tiles.end(); it != end; ++it) { TileInfo& tileInfo = it->value; TileIndex tileIndex = it->key; PlatformCALayer* tileLayer = tileInfo.layer.get(); IntRect tileRect = rectForTileIndex(tileIndex); if (tileRect.intersects(coverageRectInTileCoords)) { tileInfo.cohort = VisibleTileCohort; if (tileInfo.hasStaleContent) { // FIXME: store a dirty region per layer? tileLayer->setNeedsDisplay(); tileInfo.hasStaleContent = false; } } else { // Add to the currentCohort if not already in one. if (tileInfo.cohort == VisibleTileCohort) { tileInfo.cohort = currCohort; ++tilesInCohort; if (m_controller.unparentsOffscreenTiles()) tileLayer->removeFromSuperlayer(); } else if (m_controller.unparentsOffscreenTiles() && m_controller.shouldAggressivelyRetainTiles() && tileLayer->superlayer()) { // Aggressive tile retention means we'll never remove cohorts, but we need to make sure they're unparented. // We can't immediately unparent cohorts comprised of secondary tiles that never touch the primary coverage rect, // because that would defeat the usefulness of prepopulateRect(); instead, age prepopulated tiles out as if they were being removed. for (auto& cohort : m_cohortList) { if (cohort.cohort != tileInfo.cohort) continue; double timeUntilCohortExpires = cohort.timeUntilExpiration(); if (timeUntilCohortExpires > 0) { minimumRevalidationTimerDuration = std::min(minimumRevalidationTimerDuration, timeUntilCohortExpires); needsTileRevalidation = true; } else tileLayer->removeFromSuperlayer(); break; } } } } if (needsTileRevalidation) m_controller.scheduleTileRevalidation(minimumRevalidationTimerDuration); if (tilesInCohort) startedNewCohort(currCohort); if (!m_controller.shouldAggressivelyRetainTiles()) { if (m_controller.shouldTemporarilyRetainTileCohorts()) scheduleCohortRemoval(); else if (tilesInCohort) removeTilesInCohort(currCohort); } // Ensure primary tile coverage tiles. m_primaryTileCoverageRect = ensureTilesForRect(coverageRect, CoverageType::PrimaryTiles); if (validationPolicy & PruneSecondaryTiles) { removeAllSecondaryTiles(); m_cohortList.clear(); } else { for (auto& secondaryCoverageRect : m_secondaryTileCoverageRects) { FloatRect secondaryRectInLayerCoordinates(secondaryCoverageRect); secondaryRectInLayerCoordinates.scale(1 / m_scale); ensureTilesForRect(secondaryRectInLayerCoordinates, CoverageType::SecondaryTiles); } m_secondaryTileCoverageRects.clear(); } if (m_controller.unparentsOffscreenTiles() && (validationPolicy & UnparentAllTiles)) { for (TileMap::iterator it = m_tiles.begin(), end = m_tiles.end(); it != end; ++it) it->value.layer->removeFromSuperlayer(); } auto boundsAtLastRevalidate = m_controller.boundsAtLastRevalidate(); if (boundsAtLastRevalidate != bounds) { // If there are margin tiles and the bounds have grown taller or wider, then the tiles that used to // be bottom or right margin tiles need to be invalidated. if (m_controller.hasMargins()) { if (bounds.width() > boundsAtLastRevalidate.width() || bounds.height() > boundsAtLastRevalidate.height()) { IntRect boundsWithoutMargin = m_controller.boundsWithoutMargin(); IntRect oldBoundsWithoutMargin = m_controller.boundsAtLastRevalidateWithoutMargin(); if (bounds.height() > boundsAtLastRevalidate.height()) { IntRect formerBottomMarginRect = IntRect(oldBoundsWithoutMargin.x(), oldBoundsWithoutMargin.height(), oldBoundsWithoutMargin.width(), boundsWithoutMargin.height() - oldBoundsWithoutMargin.height()); setNeedsDisplayInRect(formerBottomMarginRect); } if (bounds.width() > boundsAtLastRevalidate.width()) { IntRect formerRightMarginRect = IntRect(oldBoundsWithoutMargin.width(), oldBoundsWithoutMargin.y(), boundsWithoutMargin.width() - oldBoundsWithoutMargin.width(), oldBoundsWithoutMargin.height()); setNeedsDisplayInRect(formerRightMarginRect); } } } FloatRect scaledBounds(bounds); scaledBounds.scale(m_scale); IntRect boundsInTileCoords(enclosingIntRect(scaledBounds)); TileIndex topLeftForBounds; TileIndex bottomRightForBounds; getTileIndexRangeForRect(boundsInTileCoords, topLeftForBounds, bottomRightForBounds); Vector<TileIndex> tilesToRemove; for (auto& index : m_tiles.keys()) { if (index.y() < topLeftForBounds.y() || index.y() > bottomRightForBounds.y() || index.x() < topLeftForBounds.x() || index.x() > bottomRightForBounds.x()) tilesToRemove.append(index); } removeTiles(tilesToRemove); } m_controller.didRevalidateTiles(); }