Example #1
0
void Canvas2DLayerChromium::paintContentsIfDirty(const CCOcclusionTracker* /* occlusion */)
{
    TRACE_EVENT("Canvas2DLayerChromium::paintContentsIfDirty", this, 0);
    if (!drawsContent())
        return;

    if (m_useDoubleBuffering && layerTreeHost()) {
        TextureManager* textureManager = layerTreeHost()->contentsTextureManager();
        if (m_frontTexture)
            m_frontTexture->setTextureManager(textureManager);
        else
            m_frontTexture = ManagedTexture::create(textureManager);
        m_frontTexture->reserve(m_size, GraphicsContext3D::RGBA);
    }

    if (!needsDisplay())
        return;

    m_needsDisplay = false;

    bool success = m_context->makeContextCurrent();
    ASSERT_UNUSED(success, success);

    m_contextLost = m_context->getExtensions()->getGraphicsResetStatusARB() != GraphicsContext3D::NO_ERROR;
    if (m_contextLost)
        return;

    if (m_canvas) {
        TRACE_EVENT("SkCanvas::flush", m_canvas, 0);
        m_canvas->flush();
    }

    TRACE_EVENT("GraphicsContext3D::flush", m_context, 0);
    m_context->flush();
}
Example #2
0
bool VideoLayerChromium::reserveTextures(const VideoFrameChromium* frame, GC3Denum textureFormat)
{
    ASSERT(layerTreeHost());
    ASSERT(frame);
    ASSERT(textureFormat != GraphicsContext3D::INVALID_VALUE);

    int maxTextureSize = layerTreeHost()->layerRendererCapabilities().maxTextureSize;

    for (unsigned plane = 0; plane < frame->planes(); plane++) {
        IntSize requiredTextureSize = frame->requiredTextureSize(plane);

        // If the renderer cannot handle this large of a texture, return false.
        // FIXME: Remove this test when tiled layers are implemented.
        if (requiredTextureSize.isZero() || requiredTextureSize.width() > maxTextureSize || requiredTextureSize.height() > maxTextureSize)
            return false;

        if (!m_textures[plane].m_texture)
            return false;

        if (m_textures[plane].m_texture->size() != requiredTextureSize)
            m_textures[plane].m_visibleSize = computeVisibleSize(frame, plane);

        m_textures[plane].m_texture->reserve(requiredTextureSize, textureFormat);
    }

    return true;
}
Example #3
0
void TextureLayerChromium::setRateLimitContext(bool rateLimit)
{
    if (!rateLimit && m_rateLimitContext && m_client && layerTreeHost())
        layerTreeHost()->stopRateLimiter(m_client->context());

    m_rateLimitContext = rateLimit;
}
Example #4
0
void Canvas2DLayerChromium::setNeedsDisplayRect(const FloatRect& dirtyRect)
{
    LayerChromium::setNeedsDisplayRect(dirtyRect);

    if (layerTreeHost())
        layerTreeHost()->startRateLimiter(m_context.get());
}
Example #5
0
void WebGLLayerChromium::setDrawingBuffer(DrawingBuffer* drawingBuffer)
{
    bool drawingBufferChanged = (m_drawingBuffer != drawingBuffer);

    // The GraphicsContext3D used by the layer is the context associated with
    // the drawing buffer. If the drawing buffer is changing, make sure
    // to stop the rate limiter on the old context, not the new context from the
    // new drawing buffer.
    GraphicsContext3D* context3D = context();
    if (layerTreeHost() && drawingBufferChanged && context3D)
        layerTreeHost()->stopRateLimiter(context3D);

    m_drawingBuffer = drawingBuffer;
    if (!m_drawingBuffer)
        return;

    unsigned int textureId = m_drawingBuffer->platformColorBuffer();
    if (textureId != m_textureId || drawingBufferChanged) {
        m_textureChanged = true;
        m_textureUpdated = true;
    }
    m_textureId = textureId;
    GraphicsContext3D::Attributes attributes = context()->getContextAttributes();
    m_hasAlpha = attributes.alpha;
    m_premultipliedAlpha = attributes.premultipliedAlpha;
    m_contextLost = context()->getExtensions()->getGraphicsResetStatusARB() != GraphicsContext3D::NO_ERROR;
}
Example #6
0
void TextureLayerChromium::setNeedsDisplayRect(const FloatRect& dirtyRect)
{
    LayerChromium::setNeedsDisplayRect(dirtyRect);

    if (m_rateLimitContext && m_client && layerTreeHost())
        layerTreeHost()->startRateLimiter(m_client->context());
}
Example #7
0
GraphicsContext3D* WebGLLayerChromium::layerRendererContext()
{
    // FIXME: In the threaded case, paintRenderedResultsToCanvas must be
    // refactored to be asynchronous. Currently this is unimplemented.
    if (!layerTreeHost() || CCProxy::hasImplThread())
        return 0;
    return layerTreeHost()->context();
}
Example #8
0
void WebGLLayerChromium::contentChanged()
{
    m_textureUpdated = true;
    // If WebGL commands are issued outside of a the animation callbacks, then use
    // call rateLimitOffscreenContextCHROMIUM() to keep the context from getting too far ahead.
    if (layerTreeHost())
        layerTreeHost()->startRateLimiter(context());
}
Example #9
0
TextureLayerChromium::~TextureLayerChromium()
{
    if (layerTreeHost()) {
        if (m_textureId)
            layerTreeHost()->acquireLayerTextures();
        if (m_rateLimitContext && m_client)
            layerTreeHost()->stopRateLimiter(m_client->context());
    }
}
Example #10
0
void TextureLayerChromium::setTextureId(unsigned id)
{
    if (m_textureId == id)
        return;
    if (m_textureId && layerTreeHost())
        layerTreeHost()->acquireLayerTextures();
    m_textureId = id;
    setNeedsCommit();
}
void WebGLLayerChromium::setNeedsDisplayRect(const FloatRect& dirtyRect)
{
    LayerChromium::setNeedsDisplayRect(dirtyRect);

    // If WebGL commands are issued outside of a the animation callbacks, then use
    // call rateLimitOffscreenContextCHROMIUM() to keep the context from getting too far ahead.
    if (layerTreeHost())
        layerTreeHost()->startRateLimiter(context());
}
Example #12
0
void TiledLayerChromium::updateTileSizeAndTilingOption()
{
    if (!m_tiler)
        return;

    const IntSize tileSize(min(defaultTileSize, contentBounds().width()), min(defaultTileSize, contentBounds().height()));

    // Tile if both dimensions large, or any one dimension large and the other
    // extends into a second tile. This heuristic allows for long skinny layers
    // (e.g. scrollbars) that are Nx1 tiles to minimize wasted texture space.
    const bool anyDimensionLarge = contentBounds().width() > maxUntiledSize || contentBounds().height() > maxUntiledSize;
    const bool anyDimensionOneTile = contentBounds().width() <= defaultTileSize || contentBounds().height() <= defaultTileSize;
    const bool autoTiled = anyDimensionLarge && !anyDimensionOneTile;

    bool isTiled;
    if (m_tilingOption == AlwaysTile)
        isTiled = true;
    else if (m_tilingOption == NeverTile)
        isTiled = false;
    else
        isTiled = autoTiled;

    IntSize requestedSize = isTiled ? tileSize : contentBounds();
    const int maxSize = layerTreeHost()->layerRendererCapabilities().maxTextureSize;
    IntSize clampedSize = requestedSize.shrunkTo(IntSize(maxSize, maxSize));
    m_tiler->setTileSize(clampedSize);
}
Example #13
0
void ContentLayerChromium::createTextureUpdaterIfNeeded()
{
    if (m_textureUpdater)
        return;
    if (layerTreeHost()->settings().acceleratePainting)
        m_textureUpdater = FrameBufferSkPictureCanvasLayerTextureUpdater::create(ContentLayerPainter::create(m_client));
    else if (CCSettings::perTilePaintingEnabled())
        m_textureUpdater = BitmapSkPictureCanvasLayerTextureUpdater::create(ContentLayerPainter::create(m_client));
    else
        m_textureUpdater = BitmapCanvasLayerTextureUpdater::create(ContentLayerPainter::create(m_client));
    m_textureUpdater->setOpaque(opaque());

    GC3Denum textureFormat = layerTreeHost()->rendererCapabilities().bestTextureFormat;
    setTextureFormat(textureFormat);
    setSampledTexelFormat(textureUpdater()->sampledTexelFormat(textureFormat));
}
Example #14
0
void TiledLayerChromium::setLayerTreeHost(CCLayerTreeHost* host)
{
    if (host == layerTreeHost())
        return;

    if (layerTreeHost())
        cleanupResources();

    LayerChromium::setLayerTreeHost(host);

    if (!host)
        return;

    createTextureUpdater(host);
    setTextureFormat(host->layerRendererCapabilities().bestTextureFormat);
    m_sampledTexelFormat = textureUpdater()->sampledTexelFormat(m_textureFormat);
}
Example #15
0
void TiledLayerChromium::setLayerTreeHost(CCLayerTreeHost* host)
{
    if (host && host != layerTreeHost()) {
        for (CCLayerTilingData::TileMap::const_iterator iter = m_tiler->tiles().begin(); iter != m_tiler->tiles().end(); ++iter) {
            UpdatableTile* tile = static_cast<UpdatableTile*>(iter->second.get());
            tile->managedTexture()->setTextureManager(host->contentsTextureManager());
        }
    }
    LayerChromium::setLayerTreeHost(host);
}
Example #16
0
void VideoLayerChromium::setLayerTreeHost(CCLayerTreeHost* host)
{
    if (host && layerTreeHost() != host) {
        for (size_t i = 0; i < 3; ++i) {
            m_textures[i].m_visibleSize = IntSize();
            m_textures[i].m_texture = ManagedTexture::create(host->contentsTextureManager());
        }
    }

    LayerChromium::setLayerTreeHost(host);
}
Example #17
0
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);
        }
    }
}
Example #18
0
TextureManager* TiledLayerChromium::textureManager() const
{
    if (!layerTreeHost())
        return 0;
    return layerTreeHost()->contentsTextureManager();
}
WebGLLayerChromium::~WebGLLayerChromium()
{
    if (context() && layerTreeHost())
        layerTreeHost()->stopRateLimiter(context());
}
Example #20
0
Canvas2DLayerChromium::~Canvas2DLayerChromium()
{
    if (m_context && layerTreeHost())
        layerTreeHost()->stopRateLimiter(m_context.get());
}
Example #21
0
void TextureLayerChromium::setLayerTreeHost(CCLayerTreeHost* host)
{
    if (m_textureId && layerTreeHost() && host != layerTreeHost())
        layerTreeHost()->acquireLayerTextures();
    LayerChromium::setLayerTreeHost(host);
}
Example #22
0
void TextureLayerChromium::willModifyTexture()
{
    if (layerTreeHost())
        layerTreeHost()->acquireLayerTextures();
}
Example #23
0
void TiledLayerChromium::prepareToUpdateTiles(bool idle, int left, int top, int right, int bottom)
{
    // Reset m_updateRect for all tiles.
    for (CCLayerTilingData::TileMap::const_iterator iter = m_tiler->tiles().begin(); iter != m_tiler->tiles().end(); ++iter) {
        UpdatableTile* tile = static_cast<UpdatableTile*>(iter->second.get());
        tile->m_updateRect = IntRect();
    }

    // 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);

            // Do post commit deletion of current texture when partial texture
            // updates are not used.
            if (tile->isDirty() && layerTreeHost() && !layerTreeHost()->settings().partialTextureUpdates)
                layerTreeHost()->deleteTextureAfterCommit(tile->managedTexture()->steal());

            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)) {
                m_skipsIdlePaint = true;
                if (!idle) {
                    m_skipsDraw = true;
                    cleanupResources();
                }
                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 opaqueRect; // FIXME: unused. remove this and store in the layer to pass to impl for draw culling
    textureUpdater()->prepareToUpdate(m_paintRect, m_tiler->tileSize(), m_tiler->hasBorderTexels(), contentsScale(), &opaqueRect);
    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();

            // Use m_updateRect as copyAndClearDirty above moved the existing dirty rect to m_updateRect.
            const IntRect& dirtyRect = tile->m_updateRect;
            if (dirtyRect.isEmpty())
                continue;

            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);
        }
    }
}