void TiledLayerChromium::addSelfToOccludedScreenSpace(Region& occludedScreenSpace) { if (m_skipsDraw || drawOpacity() != 1 || !isPaintedAxisAlignedInScreen()) return; if (opaque()) { LayerChromium::addSelfToOccludedScreenSpace(occludedScreenSpace); return; } IntRect visibleRect = visibleLayerRect(); TransformationMatrix contentTransform = contentToScreenSpaceTransform(); // FIXME: Create/Use a FloatRegion for the occludedScreenSpace, instead of a Region based on ints, to avoid this step and get better accuracy between layers in target space. Region tileRegion; int left, top, right, bottom; m_tiler->layerRectToTileIndices(visibleLayerRect(), left, top, right, bottom); for (int j = top; j <= bottom; ++j) { for (int i = left; i <= right; ++i) { UpdatableTile* tile = tileAt(i, j); if (tile) { IntRect visibleTileOpaqueRect = intersection(visibleRect, tile->m_opaqueRect); FloatRect screenRect = contentTransform.mapRect(FloatRect(visibleTileOpaqueRect)); IntRect screenIntRect = enclosedIntRect(screenRect); if (!screenIntRect.isEmpty()) occludedScreenSpace.unite(screenIntRect); } } } }
PassOwnPtr<CCSharedQuadState> CCLayerImpl::createSharedQuadState() const { IntRect layerClipRect; if (usesLayerClipping()) layerClipRect = clipRect(); return CCSharedQuadState::create(quadTransform(), drawTransform(), visibleLayerRect(), layerClipRect, drawOpacity(), opaque()); }
void ContentLayerChromium::draw(const IntRect& targetSurfaceRect) { const TransformationMatrix transform = tilingTransform(); IntRect layerRect = visibleLayerRect(targetSurfaceRect); if (!layerRect.isEmpty()) m_tiler->draw(layerRect, transform, ccLayerImpl()->drawOpacity()); }
Region TiledLayerChromium::opaqueContentsRegion() const { if (m_skipsDraw) return Region(); return m_tiler->opaqueRegionInLayerRect(visibleLayerRect()); }
void TiledLayerChromium::reserveTextures() { updateBounds(); const IntRect& layerRect = visibleLayerRect(); if (layerRect.isEmpty() || !m_tiler->numTiles()) return; int left, top, right, bottom; m_tiler->layerRectToTileIndices(layerRect, left, top, right, bottom); createTextureUpdaterIfNeeded(); for (int j = top; j <= bottom; ++j) { for (int i = left; i <= right; ++i) { UpdatableTile* tile = tileAt(i, j); if (!tile) tile = createTile(i, j); if (!tile->managedTexture()->isValid(m_tiler->tileSize(), m_textureFormat)) tile->m_dirtyRect = m_tiler->tileRect(tile); if (!tile->managedTexture()->reserve(m_tiler->tileSize(), m_textureFormat)) return; } } }
void ContentLayerChromium::idlePaintContentsIfDirty() { if (!drawsContent()) return; const IntRect& layerRect = visibleLayerRect(); if (layerRect.isEmpty()) return; prepareToUpdateIdle(layerRect); if (needsIdlePaint(layerRect)) setNeedsCommit(); }
void ContentLayerChromium::paintContentsIfDirty() { updateTileSizeAndTilingOption(); IntRect layerRect; // Always call prepareToUpdate() but with an empty layer rectangle when // layer doesn't draw contents. if (drawsContent()) layerRect = visibleLayerRect(); prepareToUpdate(layerRect); m_needsDisplay = false; }
void ContentLayerChromium::paintContentsIfDirty(const IntRect& targetSurfaceRect) { ASSERT(drawsContent()); ASSERT(layerRenderer()); updateLayerSize(layerBounds().size()); IntRect layerRect = visibleLayerRect(targetSurfaceRect); if (layerRect.isEmpty()) return; IntRect dirty = enclosingIntRect(m_dirtyRect); dirty.intersect(layerBounds()); m_tiler->invalidateRect(dirty); m_tiler->prepareToUpdate(layerRect); m_dirtyRect = FloatRect(); }
void ContentLayerChromium::paintContentsIfDirty() { ASSERT(drawsContent()); updateTileSizeAndTilingOption(); const IntRect& layerRect = visibleLayerRect(); if (layerRect.isEmpty()) return; IntRect dirty = enclosingIntRect(m_dirtyRect); dirty.intersect(IntRect(IntPoint(), contentBounds())); invalidateRect(dirty); if (!drawsContent()) return; prepareToUpdate(layerRect); resetNeedsDisplay(); }
Region CCLayerImpl::visibleContentOpaqueRegion() const { if (opaque()) return visibleLayerRect(); return Region(); }
void TiledLayerChromium::prepareToUpdateTiles(bool idle, int left, int top, int right, int bottom, const CCOcclusionTracker* occlusion) { createTextureUpdaterIfNeeded(); // Create tiles as needed, expanding a dirty rect to contain all // the dirty regions currently being drawn. All dirty tiles that are to be painted // get their m_updateRect set to m_dirtyRect and m_dirtyRect cleared. This way if // invalidateRect is invoked during prepareToUpdate we don't lose the request. IntRect dirtyLayerRect; for (int j = top; j <= bottom; ++j) { for (int i = left; i <= right; ++i) { UpdatableTile* tile = tileAt(i, j); if (!tile) tile = createTile(i, j); // When not idle painting, if the visible region of the tile is occluded, don't reserve a texture or mark it for update. // If any part of the tile is visible, then we need to paint it so the tile is pushed to the impl thread. // This will also avoid painting the tile in the next loop, below. if (!idle && occlusion) { IntRect visibleTileRect = intersection(m_tiler->tileBounds(i, j), visibleLayerRect()); if (occlusion->occluded(this, visibleTileRect)) continue; } // FIXME: Decide if partial update should be allowed based on cost // of update. https://bugs.webkit.org/show_bug.cgi?id=77376 if (tileOnlyNeedsPartialUpdate(tile) && layerTreeHost() && layerTreeHost()->requestPartialTextureUpdate()) tile->m_partialUpdate = true; else if (tileNeedsBufferedUpdate(tile) && layerTreeHost()) layerTreeHost()->deleteTextureAfterCommit(tile->managedTexture()->steal()); if (!tile->managedTexture()->isValid(m_tiler->tileSize(), m_textureFormat)) { // Sets the dirty rect to a full-sized tile with border texels. tile->m_dirtyRect = m_tiler->tileRect(tile); } if (!tile->managedTexture()->reserve(m_tiler->tileSize(), m_textureFormat)) { m_skipsIdlePaint = true; if (!idle) { // If the background covers the viewport, always draw this // layer so that checkerboarded tiles will still draw. if (!backgroundCoversViewport()) m_skipsDraw = true; m_tiler->reset(); m_paintRect = IntRect(); m_requestedUpdateTilesRect = IntRect(); } return; } dirtyLayerRect.unite(tile->m_dirtyRect); tile->copyAndClearDirty(); } } m_paintRect = dirtyLayerRect; if (dirtyLayerRect.isEmpty()) return; // Due to borders, when the paint rect is extended to tile boundaries, it // may end up overlapping more tiles than the original content rect. Record // the original tiles so we don't upload more tiles than necessary. if (!m_paintRect.isEmpty()) m_requestedUpdateTilesRect = IntRect(left, top, right - left + 1, bottom - top + 1); // Calling prepareToUpdate() calls into WebKit to paint, which may have the side // effect of disabling compositing, which causes our reference to the texture updater to be deleted. // However, we can't free the memory backing the GraphicsContext until the paint finishes, // so we grab a local reference here to hold the updater alive until the paint completes. RefPtr<LayerTextureUpdater> protector(textureUpdater()); IntRect paintedOpaqueRect; textureUpdater()->prepareToUpdate(m_paintRect, m_tiler->tileSize(), m_tiler->hasBorderTexels(), contentsScale(), &paintedOpaqueRect); for (int j = top; j <= bottom; ++j) { for (int i = left; i <= right; ++i) { UpdatableTile* tile = tileAt(i, j); // Tiles are created before prepareToUpdate() is called. if (!tile) CRASH(); IntRect tileRect = m_tiler->tileBounds(i, j); // Use m_updateRect as copyAndClearDirty above moved the existing dirty rect to m_updateRect if the tile isn't culled. const IntRect& dirtyRect = tile->m_updateRect; if (dirtyRect.isEmpty()) continue; // Save what was painted opaque in the tile. Keep the old area if the paint didn't touch it, and didn't paint some // other part of the tile opaque. IntRect tilePaintedRect = intersection(tileRect, m_paintRect); IntRect tilePaintedOpaqueRect = intersection(tileRect, paintedOpaqueRect); if (!tilePaintedRect.isEmpty()) { IntRect paintInsideTileOpaqueRect = intersection(tile->opaqueRect(), tilePaintedRect); bool paintInsideTileOpaqueRectIsNonOpaque = !tilePaintedOpaqueRect.contains(paintInsideTileOpaqueRect); bool opaquePaintNotInsideTileOpaqueRect = !tilePaintedOpaqueRect.isEmpty() && !tile->opaqueRect().contains(tilePaintedOpaqueRect); if (paintInsideTileOpaqueRectIsNonOpaque || opaquePaintNotInsideTileOpaqueRect) tile->setOpaqueRect(tilePaintedOpaqueRect); } // sourceRect starts as a full-sized tile with border texels included. IntRect sourceRect = m_tiler->tileRect(tile); sourceRect.intersect(dirtyRect); // Paint rect not guaranteed to line up on tile boundaries, so // make sure that sourceRect doesn't extend outside of it. sourceRect.intersect(m_paintRect); tile->m_updateRect = sourceRect; if (sourceRect.isEmpty()) continue; tile->texture()->prepareRect(sourceRect); } } }
void TiledLayerChromium::protectVisibleTileTextures() { protectTileTextures(visibleLayerRect()); }
void FakeTiledLayerChromium::update(CCTextureUpdater& updater, const CCOcclusionTracker* occlusion) { updateLayerRect(updater, visibleLayerRect(), occlusion); }
PassOwnPtr<CCSharedQuadState> CCLayerImpl::createSharedQuadState() const { return CCSharedQuadState::create(quadTransform(), drawTransform(), visibleLayerRect(), m_scissorRect, drawOpacity(), opaque()); }