void CCLayerTreeHostImpl::setFullRootLayerDamage() { if (rootLayer()) { CCRenderSurface* renderSurface = rootLayer()->renderSurface(); if (renderSurface) renderSurface->damageTracker()->forceFullDamageNextUpdate(); } }
void CCRenderPass::appendQuadsForRenderSurfaceLayer(CCLayerImpl* layer) { // FIXME: render surface layers should be a CCLayerImpl-derived class and // not be handled specially here. CCRenderSurface* surface = layer->renderSurface(); OwnPtr<CCSharedQuadState> sharedQuadState = surface->createSharedQuadState(); m_quadList.append(CCRenderSurfaceDrawQuad::create(sharedQuadState.get(), surface->contentRect(), layer, surfaceDamageRect())); m_sharedQuadStateList.append(sharedQuadState.release()); }
void CCRenderPass::appendQuadsForRenderSurfaceLayer(CCLayerImpl* layer) { // FIXME: render surface layers should be a CCLayerImpl-derived class and // not be handled specially here. CCRenderSurface* surface = layer->renderSurface(); bool isOpaque = false; OwnPtr<CCSharedQuadState> sharedQuadState = CCSharedQuadState::create(surface->drawTransform(), surface->drawTransform(), surface->contentRect(), surface->clipRect(), surface->drawOpacity(), isOpaque); m_quadList.append(CCRenderSurfaceDrawQuad::create(sharedQuadState.get(), surface->contentRect(), layer, surfaceDamageRect())); m_sharedQuadStateList.append(sharedQuadState.release()); }
void CCLayerTreeHostImpl::trackDamageForAllSurfaces(CCLayerImpl* rootDrawLayer, const CCLayerList& renderSurfaceLayerList) { // For now, we use damage tracking to compute a global scissor. To do this, we must // compute all damage tracking before drawing anything, so that we know the root // damage rect. The root damage rect is then used to scissor each surface. for (int surfaceIndex = renderSurfaceLayerList.size() - 1; surfaceIndex >= 0 ; --surfaceIndex) { CCLayerImpl* renderSurfaceLayer = renderSurfaceLayerList[surfaceIndex]; CCRenderSurface* renderSurface = renderSurfaceLayer->renderSurface(); ASSERT(renderSurface); renderSurface->damageTracker()->updateDamageTrackingState(renderSurface->layerList(), renderSurfaceLayer->id(), renderSurfaceLayer->maskLayer()); } }
void CCRenderPass::appendQuadsForRenderSurfaceLayer(CCLayerImpl* layer) { // FIXME: render surface layers should be a CCLayerImpl-derived class and // not be handled specially here. CCRenderSurface* surface = layer->renderSurface(); OwnPtr<CCSharedQuadState> sharedQuadState = surface->createSharedQuadState(); if (layer->hasDebugBorders()) { Color color(debugSurfaceBorderColorRed, debugSurfaceBorderColorGreen, debugSurfaceBorderColorBlue, debugSurfaceBorderAlpha); m_quadList.append(CCDebugBorderDrawQuad::create(sharedQuadState.get(), surface->contentRect(), color, debugSurfaceBorderWidth)); } bool isReplica = false; m_quadList.append(CCRenderSurfaceDrawQuad::create(sharedQuadState.get(), surface->contentRect(), layer, surfaceDamageRect(), isReplica)); m_sharedQuadStateList.append(sharedQuadState.release()); // Add replica after the surface so that it appears below the surface. if (surface->hasReplica()) { OwnPtr<CCSharedQuadState> sharedQuadState = surface->createReplicaSharedQuadState(); if (layer->hasDebugBorders()) { Color color(debugReplicaBorderColorRed, debugReplicaBorderColorGreen, debugReplicaBorderColorBlue, debugSurfaceBorderAlpha); m_quadList.append(CCDebugBorderDrawQuad::create(sharedQuadState.get(), surface->contentRect(), color, debugSurfaceBorderWidth)); } bool isReplica = true; m_quadList.append(CCRenderSurfaceDrawQuad::create(sharedQuadState.get(), surface->contentRect(), layer, surfaceDamageRect(), isReplica)); m_sharedQuadStateList.append(sharedQuadState.release()); } }
void CCLayerTreeHostImpl::calculateRenderPasses(CCRenderPassList& passes, CCLayerList& renderSurfaceLayerList) { renderSurfaceLayerList.append(rootLayer()); if (!rootLayer()->renderSurface()) rootLayer()->createRenderSurface(); rootLayer()->renderSurface()->clearLayerList(); rootLayer()->renderSurface()->setContentRect(IntRect(IntPoint(), viewportSize())); rootLayer()->setClipRect(IntRect(IntPoint(), viewportSize())); { TransformationMatrix identityMatrix; TRACE_EVENT("CCLayerTreeHostImpl::calcDrawEtc", this, 0); CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(rootLayer(), rootLayer(), identityMatrix, identityMatrix, renderSurfaceLayerList, rootLayer()->renderSurface()->layerList(), &m_layerSorter, layerRendererCapabilities().maxTextureSize); } if (layerRendererCapabilities().usingPartialSwap) trackDamageForAllSurfaces(rootLayer(), renderSurfaceLayerList); m_rootDamageRect = rootLayer()->renderSurface()->damageTracker()->currentDamageRect(); for (int surfaceIndex = renderSurfaceLayerList.size() - 1; surfaceIndex >= 0 ; --surfaceIndex) { CCLayerImpl* renderSurfaceLayer = renderSurfaceLayerList[surfaceIndex]; CCRenderSurface* renderSurface = renderSurfaceLayer->renderSurface(); OwnPtr<CCRenderPass> pass = CCRenderPass::create(renderSurface); FloatRect surfaceDamageRect; if (layerRendererCapabilities().usingPartialSwap) surfaceDamageRect = damageInSurfaceSpace(renderSurfaceLayer, m_rootDamageRect); pass->setSurfaceDamageRect(surfaceDamageRect); const CCLayerList& layerList = renderSurface->layerList(); for (unsigned layerIndex = 0; layerIndex < layerList.size(); ++layerIndex) { CCLayerImpl* layer = layerList[layerIndex]; if (layer->visibleLayerRect().isEmpty()) continue; if (CCLayerTreeHostCommon::renderSurfaceContributesToTarget(layer, renderSurfaceLayer->id())) { pass->appendQuadsForRenderSurfaceLayer(layer); continue; } layer->willDraw(m_layerRenderer.get()); pass->appendQuadsForLayer(layer); } passes.append(pass.release()); } }
void CCLayerSorter::createGraphNodes(LayerList::iterator first, LayerList::iterator last) { #if !defined( NDEBUG ) LOG(CCLayerSorter, "Creating graph nodes:\n"); #endif float minZ = FLT_MAX; float maxZ = -FLT_MAX; for (LayerList::const_iterator it = first; it < last; it++) { m_nodes.append(GraphNode(it->get())); GraphNode& node = m_nodes.at(m_nodes.size() - 1); CCRenderSurface* renderSurface = node.layer->renderSurface(); if (!node.layer->drawsContent() && !renderSurface) continue; #if !defined( NDEBUG ) LOG(CCLayerSorter, "Layer %d (%d x %d)\n", node.layer->debugID(), node.layer->bounds().width(), node.layer->bounds().height()); #endif TransformationMatrix drawTransform; float layerWidth, layerHeight; if (renderSurface) { drawTransform = renderSurface->drawTransform(); layerWidth = 0.5 * renderSurface->contentRect().width(); layerHeight = 0.5 * renderSurface->contentRect().height(); } else { drawTransform = node.layer->drawTransform(); layerWidth = 0.5 * node.layer->bounds().width(); layerHeight = 0.5 * node.layer->bounds().height(); } FloatPoint3D c1 = drawTransform.mapPoint(FloatPoint3D(-layerWidth, layerHeight, 0)); FloatPoint3D c2 = drawTransform.mapPoint(FloatPoint3D(layerWidth, layerHeight, 0)); FloatPoint3D c3 = drawTransform.mapPoint(FloatPoint3D(layerWidth, -layerHeight, 0)); FloatPoint3D c4 = drawTransform.mapPoint(FloatPoint3D(-layerWidth, -layerHeight, 0)); node.normal = (c2 - c1).cross(c3 - c1); node.c1 = FloatPoint(c1.x(), c1.y()); node.c2 = FloatPoint(c2.x(), c2.y()); node.c3 = FloatPoint(c3.x(), c3.y()); node.c4 = FloatPoint(c4.x(), c4.y()); node.origin = c1; node.boundingBox.fitToPoints(node.c1, node.c2, node.c3, node.c4); maxZ = max(c4.z(), max(c3.z(), max(c2.z(), max(maxZ, c1.z())))); minZ = min(c4.z(), min(c3.z(), min(c2.z(), min(minZ, c1.z())))); } if (last - first) m_zRange = fabsf(maxZ - minZ); }
static FloatRect damageInSurfaceSpace(CCLayerImpl* renderSurfaceLayer, const FloatRect& rootDamageRect) { FloatRect surfaceDamageRect; // For now, we conservatively use the root damage as the damage for // all surfaces, except perspective transforms. TransformationMatrix screenSpaceTransform = computeScreenSpaceTransformForSurface(renderSurfaceLayer); if (screenSpaceTransform.hasPerspective()) { // Perspective projections do not play nice with mapRect of // inverse transforms. In this uncommon case, its simpler to // just redraw the entire surface. // FIXME: use calculateVisibleRect to handle projections. CCRenderSurface* renderSurface = renderSurfaceLayer->renderSurface(); surfaceDamageRect = renderSurface->contentRect(); } else { TransformationMatrix inverseScreenSpaceTransform = screenSpaceTransform.inverse(); surfaceDamageRect = inverseScreenSpaceTransform.mapRect(rootDamageRect); } return surfaceDamageRect; }
void CCLayerSorter::createGraphNodes(LayerList::iterator first, LayerList::iterator last) { #if !defined( NDEBUG ) LOG(CCLayerSorter, "Creating graph nodes:\n"); #endif float minZ = FLT_MAX; float maxZ = -FLT_MAX; for (LayerList::const_iterator it = first; it < last; it++) { m_nodes.append(GraphNode(*it)); GraphNode& node = m_nodes.at(m_nodes.size() - 1); CCRenderSurface* renderSurface = node.layer->renderSurface(); if (!node.layer->drawsContent() && !renderSurface) continue; #if !defined( NDEBUG ) LOG(CCLayerSorter, "Layer %d (%d x %d)\n", node.layer->debugID(), node.layer->bounds().width(), node.layer->bounds().height()); #endif TransformationMatrix drawTransform; float layerWidth, layerHeight; if (renderSurface) { drawTransform = renderSurface->drawTransform(); layerWidth = renderSurface->contentRect().width(); layerHeight = renderSurface->contentRect().height(); } else { drawTransform = node.layer->drawTransform(); layerWidth = node.layer->bounds().width(); layerHeight = node.layer->bounds().height(); } node.shape = LayerShape(layerWidth, layerHeight, drawTransform); maxZ = max(maxZ, node.shape.transformOrigin.z()); minZ = min(minZ, node.shape.transformOrigin.z()); } m_zRange = fabsf(maxZ - minZ); }
void CCDamageTracker::extendDamageForRenderSurface(CCLayerImpl* layer, FloatRect& targetDamageRect) { // There are two ways a "descendant surface" can damage regions of the "target surface": // 1. Property change: // - a surface's geometry can change because of // - changes to descendants (i.e. the subtree) that affect the surface's content rect // - changes to ancestor layers that propagate their property changes to their entire subtree. // - just like layers, both the old surface rect and new surface rect will // damage the target surface in this case. // // 2. Damage rect: This surface may have been damaged by its own layerList as well, and that damage // should propagate to the target surface. // CCRenderSurface* renderSurface = layer->renderSurface(); bool surfaceIsNew = false; FloatRect oldSurfaceRect = removeRectFromCurrentFrame(layer->id(), surfaceIsNew); FloatRect surfaceRectInTargetSpace = renderSurface->drawableContentRect(); // already includes replica if it exists. saveRectForNextFrame(layer->id(), surfaceRectInTargetSpace); FloatRect damageRectInLocalSpace; if (surfaceIsNew || renderSurface->surfacePropertyChanged() || layer->layerSurfacePropertyChanged()) { // The entire surface contributes damage. damageRectInLocalSpace = renderSurface->contentRect(); // The surface's old region is now exposed on the target surface, too. targetDamageRect.uniteIfNonZero(oldSurfaceRect); } else { // Only the surface's damageRect will damage the target surface. damageRectInLocalSpace = renderSurface->damageTracker()->currentDamageRect(); } // If there was damage, transform it to target space, and possibly contribute its reflection if needed. if (!damageRectInLocalSpace.isEmpty()) { const WebTransformationMatrix& drawTransform = renderSurface->drawTransform(); FloatRect damageRectInTargetSpace = CCMathUtil::mapClippedRect(drawTransform, damageRectInLocalSpace); targetDamageRect.uniteIfNonZero(damageRectInTargetSpace); if (layer->replicaLayer()) { const WebTransformationMatrix& replicaDrawTransform = renderSurface->replicaDrawTransform(); targetDamageRect.uniteIfNonZero(CCMathUtil::mapClippedRect(replicaDrawTransform, damageRectInLocalSpace)); } } // If there was damage on the replica's mask, then the target surface receives that damage as well. if (layer->replicaLayer() && layer->replicaLayer()->maskLayer()) { CCLayerImpl* replicaMaskLayer = layer->replicaLayer()->maskLayer(); bool replicaIsNew = false; removeRectFromCurrentFrame(replicaMaskLayer->id(), replicaIsNew); const WebTransformationMatrix& replicaDrawTransform = renderSurface->replicaDrawTransform(); FloatRect replicaMaskLayerRect = CCMathUtil::mapClippedRect(replicaDrawTransform, FloatRect(FloatPoint::zero(), FloatSize(replicaMaskLayer->bounds().width(), replicaMaskLayer->bounds().height()))); saveRectForNextFrame(replicaMaskLayer->id(), replicaMaskLayerRect); // In the current implementation, a change in the replica mask damages the entire replica region. if (replicaIsNew || replicaMaskLayer->layerPropertyChanged() || !replicaMaskLayer->updateRect().isEmpty()) targetDamageRect.uniteIfNonZero(replicaMaskLayerRect); } // If the layer has a background filter, this may cause pixels in our surface to be expanded, so we will need to expand any damage // at or below this layer. We expand the damage from this layer too, as we need to readback those pixels from the surface with only // the contents of layers below this one in them. This means we need to redraw any pixels in the surface being used for the blur in // this layer this frame. if (layer->backgroundFilters().hasFilterThatMovesPixels()) expandDamageRectInsideRectWithFilters(targetDamageRect, surfaceRectInTargetSpace, layer->backgroundFilters()); }
void CCDamageTracker::extendDamageForRenderSurface(CCLayerImpl* layer, FloatRect& targetDamageRect) { // There are two ways a "descendant surface" can damage regions of the "target surface": // 1. Property change: // - a surface's geometry can change because of // - changes to descendants (i.e. the subtree) that affect the surface's content rect // - changes to ancestor layers that propagate their property changes to their entire subtree. // - just like layers, both the old surface rect and new surface rect will // damage the target surface in this case. // // 2. Damage rect: This surface may have been damaged by its own layerList as well, and that damage // should propagate to the target surface. // CCRenderSurface* renderSurface = layer->renderSurface(); bool surfaceIsNew = false; FloatRect oldSurfaceRect = removeRectFromCurrentFrame(layer->id(), surfaceIsNew); FloatRect surfaceRectInTargetSpace = renderSurface->drawableContentRect(); // already includes replica if it exists. saveRectForNextFrame(layer->id(), surfaceRectInTargetSpace); FloatRect damageRectInLocalSpace; if (surfaceIsNew || renderSurface->surfacePropertyChanged()) { // The entire surface contributes damage. damageRectInLocalSpace = renderSurface->contentRect(); // The surface's old region is now exposed on the target surface, too. targetDamageRect.uniteIfNonZero(oldSurfaceRect); } else { // Only the surface's damageRect will damage the target surface. damageRectInLocalSpace = renderSurface->damageTracker()->currentDamageRect(); } // If there was damage, transform it to target space, and possibly contribute its reflection if needed. if (!damageRectInLocalSpace.isEmpty()) { const TransformationMatrix& originTransform = renderSurface->originTransform(); FloatRect damageRectInTargetSpace = CCMathUtil::mapClippedRect(originTransform, damageRectInLocalSpace); targetDamageRect.uniteIfNonZero(damageRectInTargetSpace); if (layer->replicaLayer()) { const TransformationMatrix& replicaOriginTransform = renderSurface->replicaOriginTransform(); targetDamageRect.uniteIfNonZero(CCMathUtil::mapClippedRect(replicaOriginTransform, damageRectInLocalSpace)); } } // If there was damage on the replica's mask, then the target surface receives that damage as well. if (layer->replicaLayer() && layer->replicaLayer()->maskLayer()) { CCLayerImpl* replicaMaskLayer = layer->replicaLayer()->maskLayer(); bool replicaIsNew = false; removeRectFromCurrentFrame(replicaMaskLayer->id(), replicaIsNew); // Compute the replica's "originTransform" that maps from the replica's origin space to the target surface origin space. const TransformationMatrix& replicaOriginTransform = renderSurface->replicaOriginTransform(); FloatRect replicaMaskLayerRect = CCMathUtil::mapClippedRect(replicaOriginTransform, FloatRect(FloatPoint::zero(), FloatSize(replicaMaskLayer->bounds().width(), replicaMaskLayer->bounds().height()))); saveRectForNextFrame(replicaMaskLayer->id(), replicaMaskLayerRect); // In the current implementation, a change in the replica mask damages the entire replica region. if (replicaIsNew || replicaMaskLayer->layerPropertyChanged() || !replicaMaskLayer->updateRect().isEmpty()) targetDamageRect.uniteIfNonZero(replicaMaskLayerRect); } }
void LayerRendererChromium::drawLayersInternal() { if (viewportSize().isEmpty() || !rootLayer()) return; TRACE_EVENT("LayerRendererChromium::drawLayers", this, 0); CCLayerImpl* rootDrawLayer = rootLayer(); makeContextCurrent(); if (!rootDrawLayer->renderSurface()) rootDrawLayer->createRenderSurface(); rootDrawLayer->renderSurface()->setContentRect(IntRect(IntPoint(), viewportSize())); rootDrawLayer->setScissorRect(IntRect(IntPoint(), viewportSize())); CCLayerList renderSurfaceLayerList; renderSurfaceLayerList.append(rootDrawLayer); m_defaultRenderSurface = rootDrawLayer->renderSurface(); m_defaultRenderSurface->clearLayerList(); { TRACE_EVENT("LayerRendererChromium::drawLayersInternal::calcDrawEtc", this, 0); CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(rootDrawLayer, rootDrawLayer, m_zoomAnimatorTransform, m_zoomAnimatorTransform, renderSurfaceLayerList, m_defaultRenderSurface->layerList(), &m_layerSorter, m_capabilities.maxTextureSize); } // The GL viewport covers the entire visible area, including the scrollbars. GLC(m_context.get(), m_context->viewport(0, 0, viewportWidth(), viewportHeight())); m_windowMatrix = screenMatrix(0, 0, viewportWidth(), viewportHeight()); // Bind the common vertex attributes used for drawing all the layers. m_sharedGeometry->prepareForDraw(); GLC(m_context.get(), m_context->disable(GraphicsContext3D::SCISSOR_TEST)); GLC(m_context.get(), m_context->disable(GraphicsContext3D::DEPTH_TEST)); GLC(m_context.get(), m_context->disable(GraphicsContext3D::CULL_FACE)); useRenderSurface(m_defaultRenderSurface); if (m_zoomAnimatorTransform.isIdentity()) // Clear to blue to make it easier to spot unrendered regions. m_context->clearColor(0, 0, 1, 1); else // Clear to grey, as zoom animation may leave unrendered regions. // FIXME(wjmaclean): Render some interesting texture in unrendered regions. m_context->clearColor(0.25, 0.25, 0.25, 1); m_context->colorMask(true, true, true, true); m_context->clear(GraphicsContext3D::COLOR_BUFFER_BIT); GLC(m_context.get(), m_context->enable(GraphicsContext3D::BLEND)); GLC(m_context.get(), m_context->blendFunc(GraphicsContext3D::ONE, GraphicsContext3D::ONE_MINUS_SRC_ALPHA)); GLC(m_context.get(), m_context->enable(GraphicsContext3D::SCISSOR_TEST)); // Update the contents of the render surfaces. We traverse the array from // back to front to guarantee that nested render surfaces get rendered in the // correct order. for (int surfaceIndex = renderSurfaceLayerList.size() - 1; surfaceIndex >= 0 ; --surfaceIndex) { CCLayerImpl* renderSurfaceLayer = renderSurfaceLayerList[surfaceIndex].get(); CCRenderSurface* renderSurface = renderSurfaceLayer->renderSurface(); ASSERT(renderSurface); renderSurface->setSkipsDraw(true); // Render surfaces whose drawable area has zero width or height // will have no layers associated with them and should be skipped. if (!renderSurface->layerList().size()) continue; // Skip completely transparent render surfaces. if (!renderSurface->drawOpacity()) continue; if (useRenderSurface(renderSurface)) { renderSurface->setSkipsDraw(false); if (renderSurfaceLayer != rootDrawLayer) { GLC(m_context.get(), m_context->disable(GraphicsContext3D::SCISSOR_TEST)); GLC(m_context.get(), m_context->clearColor(0, 0, 0, 0)); GLC(m_context.get(), m_context->clear(GraphicsContext3D::COLOR_BUFFER_BIT)); GLC(m_context.get(), m_context->enable(GraphicsContext3D::SCISSOR_TEST)); } const CCLayerList& layerList = renderSurface->layerList(); for (unsigned layerIndex = 0; layerIndex < layerList.size(); ++layerIndex) drawLayer(layerList[layerIndex].get(), renderSurface); } } if (m_headsUpDisplay->enabled()) { GLC(m_context.get(), m_context->enable(GraphicsContext3D::BLEND)); GLC(m_context.get(), m_context->blendFunc(GraphicsContext3D::ONE, GraphicsContext3D::ONE_MINUS_SRC_ALPHA)); GLC(m_context.get(), m_context->disable(GraphicsContext3D::SCISSOR_TEST)); useRenderSurface(m_defaultRenderSurface); m_headsUpDisplay->draw(); } GLC(m_context.get(), m_context->disable(GraphicsContext3D::SCISSOR_TEST)); GLC(m_context.get(), m_context->disable(GraphicsContext3D::BLEND)); }