void LayerRendererChromium::paintLayerContents(const LayerList& renderSurfaceLayerList) { for (int surfaceIndex = renderSurfaceLayerList.size() - 1; surfaceIndex >= 0 ; --surfaceIndex) { CCLayerImpl* renderSurfaceLayer = renderSurfaceLayerList[surfaceIndex].get(); RenderSurfaceChromium* renderSurface = renderSurfaceLayer->renderSurface(); ASSERT(renderSurface); // Make sure any renderSurfaceLayer is associated with this layerRenderer. // This is a defensive assignment in case the owner of this layer hasn't // set the layerRenderer on this layer already. renderSurfaceLayer->setLayerRenderer(this); // Render surfaces whose drawable area has zero width or height // will have no layers associated with them and should be skipped. if (!renderSurface->m_layerList.size()) continue; LayerList& layerList = renderSurface->m_layerList; ASSERT(layerList.size()); for (unsigned layerIndex = 0; layerIndex < layerList.size(); ++layerIndex) { CCLayerImpl* ccLayerImpl = layerList[layerIndex].get(); // Layers that start a new render surface will be painted when the render // surface's list is processed. if (ccLayerImpl->renderSurface() && ccLayerImpl->renderSurface() != renderSurface) continue; LayerChromium* layer = ccLayerImpl->owner(); layer->setLayerRenderer(this); if (layer->maskLayer()) layer->maskLayer()->setLayerRenderer(this); if (layer->replicaLayer()) { layer->replicaLayer()->setLayerRenderer(this); if (layer->replicaLayer()->maskLayer()) layer->replicaLayer()->maskLayer()->setLayerRenderer(this); } if (layer->bounds().isEmpty()) continue; IntRect targetSurfaceRect = ccLayerImpl->targetRenderSurface() ? ccLayerImpl->targetRenderSurface()->contentRect() : m_defaultRenderSurface->contentRect(); IntRect scissorRect = layer->ccLayerImpl()->scissorRect(); if (!scissorRect.isEmpty()) targetSurfaceRect.intersect(scissorRect); if (layer->drawsContent()) layer->paintContentsIfDirty(targetSurfaceRect); if (layer->maskLayer() && layer->maskLayer()->drawsContent()) layer->maskLayer()->paintContentsIfDirty(targetSurfaceRect); if (layer->replicaLayer() && layer->replicaLayer()->drawsContent()) layer->replicaLayer()->paintContentsIfDirty(targetSurfaceRect); if (layer->replicaLayer() && layer->replicaLayer()->maskLayer() && layer->replicaLayer()->maskLayer()->drawsContent()) layer->replicaLayer()->maskLayer()->paintContentsIfDirty(targetSurfaceRect); } } }
static void move_or_copy_cels( DocApi& api, Op op, const LayerList& srcLayers, const LayerList& dstLayers, const SelectedFrames& srcFrames, const SelectedFrames& dstFrames) { ASSERT(srcLayers.size() == dstLayers.size()); for (layer_t i=0; i<srcLayers.size(); ++i) { auto srcFrame = srcFrames.begin(); auto dstFrame = dstFrames.begin(); auto srcFrameEnd = srcFrames.end(); auto dstFrameEnd = dstFrames.end(); for (; srcFrame != srcFrameEnd && dstFrame != dstFrameEnd; ++srcFrame, ++dstFrame) { if (i >= 0 && i < srcLayers.size() && srcLayers[i]->isImage()) { LayerImage* srcLayer = static_cast<LayerImage*>(srcLayers[i]); if (i < dstLayers.size() && dstLayers[i]->isImage()) { LayerImage* srcLayer = static_cast<LayerImage*>(srcLayers[i]); LayerImage* dstLayer = static_cast<LayerImage*>(dstLayers[i]); #ifdef TRACE_RANGE_OPS std::clog << (op == Move ? "Moving": "Copying") << " cel " << srcLayer->name() << "[" << *srcFrame << "]" << " into " << dstLayer->name() << "[" << *dstFrame << "]\n"; #endif switch (op) { case Move: api.moveCel(srcLayer, *srcFrame, dstLayer, *dstFrame); break; case Copy: api.copyCel(srcLayer, *srcFrame, dstLayer, *dstFrame); break; } } else if (op == Move) { api.clearCel(srcLayer, *srcFrame); } } } } }
void CCLayerTreeHost::updateLayers(LayerChromium* rootLayer, CCTextureUpdater& updater) { TRACE_EVENT("CCLayerTreeHost::updateLayers", this, 0); if (!rootLayer->renderSurface()) rootLayer->createRenderSurface(); rootLayer->renderSurface()->setContentRect(IntRect(IntPoint(0, 0), deviceViewportSize())); IntRect rootClipRect(IntPoint(), deviceViewportSize()); rootLayer->setClipRect(rootClipRect); LayerList updateList; updateList.append(rootLayer); RenderSurfaceChromium* rootRenderSurface = rootLayer->renderSurface(); rootRenderSurface->clearLayerList(); { TRACE_EVENT("CCLayerTreeHost::updateLayers::calcDrawEtc", this, 0); WebTransformationMatrix identityMatrix; WebTransformationMatrix deviceScaleTransform; deviceScaleTransform.scale(m_deviceScaleFactor); CCLayerTreeHostCommon::calculateDrawTransforms(rootLayer, rootLayer, deviceScaleTransform, identityMatrix, updateList, rootRenderSurface->layerList(), layerRendererCapabilities().maxTextureSize); FloatRect rootScissorRect(FloatPoint(0, 0), viewportSize()); CCLayerTreeHostCommon::calculateVisibleAndScissorRects(updateList, rootScissorRect); } // Reset partial texture update requests. m_partialTextureUpdateRequests = 0; reserveTextures(updateList); paintLayerContents(updateList, PaintVisible, updater); if (!m_triggerIdlePaints) return; size_t preferredLimitBytes = m_contentsTextureManager->preferredMemoryLimitBytes(); size_t maxLimitBytes = m_contentsTextureManager->maxMemoryLimitBytes(); m_contentsTextureManager->reduceMemoryToLimit(preferredLimitBytes); if (m_contentsTextureManager->currentMemoryUseBytes() >= preferredLimitBytes) return; // Idle painting should fail when we hit the preferred memory limit, // otherwise it will always push us towards the maximum limit. m_contentsTextureManager->setMaxMemoryLimitBytes(preferredLimitBytes); // The second (idle) paint will be a no-op in layers where painting already occured above. paintLayerContents(updateList, PaintIdle, updater); m_contentsTextureManager->setMaxMemoryLimitBytes(maxLimitBytes); for (size_t i = 0; i < updateList.size(); ++i) updateList[i]->clearRenderSurface(); }
void CCLayerTreeHost::prioritizeTextures(const LayerList& updateList) { // Use BackToFront since it's cheap and this isn't order-dependent. typedef CCLayerIterator<LayerChromium, Vector<RefPtr<LayerChromium> >, RenderSurfaceChromium, CCLayerIteratorActions::BackToFront> CCLayerIteratorType; m_contentsTextureManager->clearPriorities(); CCPriorityCalculator calculator; CCLayerIteratorType end = CCLayerIteratorType::end(&updateList); for (CCLayerIteratorType it = CCLayerIteratorType::begin(&updateList); it != end; ++it) { if (it.representsItself()) it->setTexturePriorities(calculator); else if (it.representsTargetRenderSurface()) { if (it->maskLayer()) it->maskLayer()->setTexturePriorities(calculator); if (it->replicaLayer() && it->replicaLayer()->maskLayer()) it->replicaLayer()->maskLayer()->setTexturePriorities(calculator); } } size_t readbackBytes = 0; size_t maxBackgroundTextureBytes = 0; size_t contentsTextureBytes = 0; // Start iteration at 1 to skip the root surface as it does not have a texture cost. for (size_t i = 1; i < updateList.size(); ++i) { LayerChromium* renderSurfaceLayer = updateList[i].get(); RenderSurfaceChromium* renderSurface = renderSurfaceLayer->renderSurface(); size_t bytes = TextureManager::memoryUseBytes(renderSurface->contentRect().size(), GraphicsContext3D::RGBA); contentsTextureBytes += bytes; if (renderSurface->backgroundFilters().isEmpty()) continue; if (bytes > maxBackgroundTextureBytes) maxBackgroundTextureBytes = bytes; if (!readbackBytes) readbackBytes = TextureManager::memoryUseBytes(m_deviceViewportSize, GraphicsContext3D::RGBA); } size_t renderSurfacesBytes = readbackBytes + maxBackgroundTextureBytes + contentsTextureBytes; m_contentsTextureManager->prioritizeTextures(renderSurfacesBytes); }
// Reports whether the passed in layers have visible damage or are otherwise // dirty because render properties changed. // Assumes that layers in the list belong to same composition. ie. damage to // one layer affects the others. A warning is logged if the assumption is wrong. bool GLXGraphicsystem::needsRedraw(LayerList layers) { // TODO: Ignore damage from completely obscured surfaces for (LayerListConstIterator layer = layers.begin(); layer != layers.end(); layer++) { if ((*layer)->getLayerType() == Hardware && layers.size() > 1) { // Damage in a hardware layer should not imply a redraw in other layers LOG_WARNING("GLXGraphicsystem", "needsRedraw() called with layers not in the same composition"); } if (needsRedraw(*layer)) { return true; } } return false; }
void CCLayerTreeHost::updateLayers(LayerChromium* rootLayer, CCTextureUpdater& updater) { TRACE_EVENT0("cc", "CCLayerTreeHost::updateLayers"); if (!rootLayer->renderSurface()) rootLayer->createRenderSurface(); rootLayer->renderSurface()->setContentRect(IntRect(IntPoint(0, 0), deviceViewportSize())); IntRect rootClipRect(IntPoint(), deviceViewportSize()); rootLayer->setClipRect(rootClipRect); LayerList updateList; updateList.append(rootLayer); RenderSurfaceChromium* rootRenderSurface = rootLayer->renderSurface(); rootRenderSurface->clearLayerList(); { TRACE_EVENT0("cc", "CCLayerTreeHost::updateLayers::calcDrawEtc"); WebTransformationMatrix identityMatrix; WebTransformationMatrix deviceScaleTransform; deviceScaleTransform.scale(m_deviceScaleFactor); CCLayerTreeHostCommon::calculateDrawTransforms(rootLayer, rootLayer, deviceScaleTransform, identityMatrix, updateList, rootRenderSurface->layerList(), layerRendererCapabilities().maxTextureSize); FloatRect rootScissorRect(FloatPoint(0, 0), viewportSize()); CCLayerTreeHostCommon::calculateVisibleAndScissorRects(updateList, rootScissorRect); } // Reset partial texture update requests. m_partialTextureUpdateRequests = 0; prioritizeTextures(updateList); bool needMoreUpdates = paintLayerContents(updateList, updater); if (m_triggerIdleUpdates && needMoreUpdates) setNeedsCommit(); for (size_t i = 0; i < updateList.size(); ++i) updateList[i]->clearRenderSurface(); }
void CCLayerTreeHost::updateLayers(LayerChromium* rootLayer, CCTextureUpdateQueue& queue) { TRACE_EVENT0("cc", "CCLayerTreeHost::updateLayers"); LayerList updateList; { TRACE_EVENT0("cc", "CCLayerTreeHost::updateLayers::calcDrawEtc"); CCLayerTreeHostCommon::calculateDrawTransforms(rootLayer, deviceViewportSize(), m_deviceScaleFactor, rendererCapabilities().maxTextureSize, updateList); CCLayerTreeHostCommon::calculateVisibleRects(updateList); } // Reset partial texture update requests. m_partialTextureUpdateRequests = 0; bool needMoreUpdates = paintLayerContents(updateList, queue); if (m_triggerIdleUpdates && needMoreUpdates) setNeedsCommit(); for (size_t i = 0; i < updateList.size(); ++i) updateList[i]->clearRenderSurface(); }
size_t CCLayerTreeHost::calculateMemoryForRenderSurfaces(const LayerList& updateList) { size_t readbackBytes = 0; size_t maxBackgroundTextureBytes = 0; size_t contentsTextureBytes = 0; // Start iteration at 1 to skip the root surface as it does not have a texture cost. for (size_t i = 1; i < updateList.size(); ++i) { LayerChromium* renderSurfaceLayer = updateList[i].get(); RenderSurfaceChromium* renderSurface = renderSurfaceLayer->renderSurface(); size_t bytes = CCTexture::memorySizeBytes(renderSurface->contentRect().size(), GraphicsContext3D::RGBA); contentsTextureBytes += bytes; if (renderSurfaceLayer->backgroundFilters().isEmpty()) continue; if (bytes > maxBackgroundTextureBytes) maxBackgroundTextureBytes = bytes; if (!readbackBytes) readbackBytes = CCTexture::memorySizeBytes(m_deviceViewportSize, GraphicsContext3D::RGBA); } return readbackBytes + maxBackgroundTextureBytes + contentsTextureBytes; }
TEST(LayerList, AreLayersAdjacent) { std::unique_ptr<Sprite> spr(new Sprite(IMAGE_RGB, 32, 32, 256)); LayerGroup* root = spr->root(); Layer* layer1 = new LayerImage(spr.get()); Layer* layer2 = new LayerImage(spr.get()); Layer* layer3 = new LayerImage(spr.get()); Layer* layer4 = new LayerImage(spr.get()); root->addLayer(layer1); root->addLayer(layer2); root->addLayer(layer3); root->addLayer(layer4); LayerList layers; root->allLayers(layers); EXPECT_EQ(4, layers.size()); EXPECT_TRUE(are_layers_adjacent(layers)); std::reverse(layers.begin(), layers.end()); EXPECT_EQ(4, layers.size()); EXPECT_TRUE(are_layers_adjacent(layers)); layers.erase(layers.begin()); EXPECT_EQ(3, layers.size()); EXPECT_TRUE(are_layers_adjacent(layers)); layers.erase(layers.begin()+1); EXPECT_EQ(2, layers.size()); EXPECT_FALSE(are_layers_adjacent(layers)); std::reverse(layers.begin(), layers.end()); EXPECT_EQ(2, layers.size()); EXPECT_FALSE(are_layers_adjacent(layers)); layers.erase(layers.begin()); EXPECT_EQ(1, layers.size()); EXPECT_TRUE(are_layers_adjacent(layers)); }
void LayerRendererChromium::drawLayers(const LayerList& renderSurfaceLayerList) { TRACE_EVENT("LayerRendererChromium::drawLayers", this, 0); CCLayerImpl* rootDrawLayer = m_rootLayer->ccLayerImpl(); makeContextCurrent(); // The GL viewport covers the entire visible area, including the scrollbars. GLC(m_context.get(), m_context->viewport(0, 0, m_viewportVisibleRect.width(), m_viewportVisibleRect.height())); // Bind the common vertex attributes used for drawing all the layers. m_sharedGeometry->prepareForDraw(); // FIXME: These calls can be made once, when the compositor context is initialized. GLC(m_context.get(), m_context->disable(GraphicsContext3D::DEPTH_TEST)); GLC(m_context.get(), m_context->disable(GraphicsContext3D::CULL_FACE)); // Blending disabled by default. Root layer alpha channel on Windows is incorrect when Skia uses ClearType. GLC(m_context.get(), m_context->disable(GraphicsContext3D::BLEND)); useRenderSurface(m_defaultRenderSurface); // Clear to blue to make it easier to spot unrendered regions. m_context->clearColor(0, 0, 1, 1); m_context->colorMask(true, true, true, true); m_context->clear(GraphicsContext3D::COLOR_BUFFER_BIT); // Mask out writes to alpha channel: subpixel antialiasing via Skia results in invalid // zero alpha values on text glyphs. The root layer is always opaque. m_context->colorMask(true, true, true, false); drawRootLayer(); // Re-enable color writes to layers, which may be partially transparent. m_context->colorMask(true, true, true, true); 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(); ASSERT(renderSurfaceLayer->renderSurface()); // Render surfaces whose drawable area has zero width or height // will have no layers associated with them and should be skipped. if (!renderSurfaceLayer->renderSurface()->m_layerList.size()) continue; if (useRenderSurface(renderSurfaceLayer->renderSurface())) { 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)); } LayerList& layerList = renderSurfaceLayer->renderSurface()->m_layerList; ASSERT(layerList.size()); for (unsigned layerIndex = 0; layerIndex < layerList.size(); ++layerIndex) drawLayer(layerList[layerIndex].get(), renderSurfaceLayer->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)); }