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);
        }
    }
}
Beispiel #2
0
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);
        }
      }
    }
  }
}
Beispiel #3
0
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();
}
Beispiel #4
0
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);
}
Beispiel #5
0
// 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;
}
Beispiel #6
0
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();
}
Beispiel #7
0
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();
}
Beispiel #8
0
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;
}
Beispiel #9
0
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));
}