void GraphicsLayerTextureMapper::updateBackingStoreIfNeeded()
{
    TextureMapper* textureMapper = m_layer.textureMapper();
    if (!textureMapper)
        return;

    if (!shouldHaveBackingStore()) {
        ASSERT(!m_backingStore);
        return;
    }
    ASSERT(m_backingStore);

    IntRect dirtyRect = enclosingIntRect(FloatRect(FloatPoint::zero(), m_size));
    if (!m_needsDisplay)
        dirtyRect.intersect(enclosingIntRect(m_needsDisplayRect));
    if (dirtyRect.isEmpty())
        return;

    TextureMapperTiledBackingStore* backingStore = static_cast<TextureMapperTiledBackingStore*>(m_backingStore.get());
    backingStore->updateContentsScale(pageScaleFactor() * deviceScaleFactor());

    dirtyRect.scale(pageScaleFactor() * deviceScaleFactor());
    backingStore->updateContents(*textureMapper, this, m_size, dirtyRect, BitmapTexture::UpdateCanModifyOriginalImageData);

    m_needsDisplay = false;
    m_needsDisplayRect = IntRect();
}
void GraphicsLayerTextureMapper::updateBackingStoreIfNeeded()
{
    TextureMapper* textureMapper = m_layer->textureMapper();
    if (!textureMapper)
        return;

    if (!shouldHaveBackingStore()) {
        ASSERT(!m_backingStore);
        return;
    }
    ASSERT(m_backingStore);

    IntRect dirtyRect = enclosingIntRect(FloatRect(FloatPoint::zero(), m_size));
    if (!m_needsDisplay)
        dirtyRect.intersect(enclosingIntRect(m_needsDisplayRect));
    if (dirtyRect.isEmpty())
        return;

#if PLATFORM(QT) && !defined(QT_NO_DYNAMIC_CAST)
    ASSERT(dynamic_cast<TextureMapperTiledBackingStore*>(m_backingStore.get()));
#endif
    TextureMapperTiledBackingStore* backingStore = static_cast<TextureMapperTiledBackingStore*>(m_backingStore.get());

    backingStore->updateContents(textureMapper, this, m_size, dirtyRect, BitmapTexture::UpdateCanModifyOriginalImageData);

    m_needsDisplay = false;
    m_needsDisplayRect = IntRect();
}
void CoordinatedGraphicsLayer::syncImageBacking()
{
    if (!m_shouldSyncImageBacking)
        return;
    m_shouldSyncImageBacking = false;

    if (m_compositedNativeImagePtr) {
        ASSERT(!shouldHaveBackingStore());
        ASSERT(m_compositedImage);

        bool imageInstanceReplaced = m_coordinatedImageBacking && (m_coordinatedImageBacking->id() != CoordinatedImageBacking::getCoordinatedImageBackingID(m_compositedImage.get()));
        if (imageInstanceReplaced)
            releaseImageBackingIfNeeded();

        if (!m_coordinatedImageBacking) {
            m_coordinatedImageBacking = m_coordinator->createImageBackingIfNeeded(m_compositedImage.get());
            m_coordinatedImageBacking->addHost(this);
            m_layerState.imageID = m_coordinatedImageBacking->id();
        }

        m_coordinatedImageBacking->markDirty();
        m_layerState.imageChanged = true;
    } else
        releaseImageBackingIfNeeded();

    // syncImageBacking() changed m_layerState.imageID.
    didChangeLayerState();
}
void CoordinatedGraphicsLayer::updateContentBuffers()
{
    if (!shouldHaveBackingStore()) {
        m_mainBackingStore = nullptr;
        m_previousBackingStore = nullptr;
        return;
    }

    if (m_pendingContentsScaleAdjustment) {
        adjustContentsScale();
        m_pendingContentsScaleAdjustment = false;
    }

    // This is the only place we (re)create the main tiled backing store, once we
    // have a remote client and we are ready to send our data to the UI process.
    if (!m_mainBackingStore)
        createBackingStore();

    if (m_pendingVisibleRectAdjustment) {
        m_pendingVisibleRectAdjustment = false;
        m_mainBackingStore->coverWithTilesIfNeeded();
    }

    m_mainBackingStore->updateTileBuffers();

    // The previous backing store is kept around to avoid flickering between
    // removing the existing tiles and painting the new ones. The first time
    // the visibleRect is full painted we remove the previous backing store.
    if (m_mainBackingStore->visibleAreaIsCovered())
        m_previousBackingStore = nullptr;
}
void GraphicsLayerTextureMapper::prepareBackingStore()
{
    TextureMapper* textureMapper = m_layer->textureMapper();
    if (!textureMapper)
        return;

    if (!shouldHaveBackingStore()) {
        m_backingStore.clear();
        return;
    }

    IntRect dirtyRect = enclosingIntRect(FloatRect(FloatPoint::zero(), m_size));
    if (!m_needsDisplay)
        dirtyRect.intersect(enclosingIntRect(m_needsDisplayRect));
    if (dirtyRect.isEmpty())
        return;

    if (!m_backingStore)
        m_backingStore = TextureMapperTiledBackingStore::create();

#if PLATFORM(QT)
    ASSERT(dynamic_cast<TextureMapperTiledBackingStore*>(m_backingStore.get()));
#endif
    TextureMapperTiledBackingStore* backingStore = static_cast<TextureMapperTiledBackingStore*>(m_backingStore.get());

    if (isShowingRepaintCounter())
        incrementRepaintCount();

    // Paint into an intermediate buffer to avoid painting content more than once.
    bool paintOnce = true;
    const IntSize maxTextureSize = textureMapper->maxTextureSize();
    // We need to paint directly if the dirty rect exceeds one of the maximum dimensions.
    if (dirtyRect.width() > maxTextureSize.width() || dirtyRect.height() > maxTextureSize.height())
        paintOnce = false;

    if (paintOnce) {
        OwnPtr<ImageBuffer> imageBuffer = ImageBuffer::create(dirtyRect.size());
        GraphicsContext* context = imageBuffer->context();
        context->setImageInterpolationQuality(textureMapper->imageInterpolationQuality());
        context->setTextDrawingMode(textureMapper->textDrawingMode());
        context->translate(-dirtyRect.x(), -dirtyRect.y());
        paintGraphicsLayerContents(*context, dirtyRect);

        if (isShowingRepaintCounter())
            drawRepaintCounter(context);

        RefPtr<Image> image = imageBuffer->copyImage(DontCopyBackingStore);
        backingStore->updateContents(textureMapper, image.get(), m_size, dirtyRect, BitmapTexture::UpdateCanModifyOriginalImageData);
    } else
        backingStore->updateContents(textureMapper, this, m_size, dirtyRect, BitmapTexture::UpdateCanModifyOriginalImageData);

    backingStore->setShowDebugBorders(isShowingDebugBorder());
    backingStore->setDebugBorder(m_debugBorderColor, m_debugBorderWidth);

    m_needsDisplay = false;
    m_needsDisplayRect = IntRect();
}
void GraphicsLayerTextureMapper::updateDebugBorderAndRepaintCount()
{
    if (isShowingDebugBorder())
        updateDebugIndicators();

    // When this has its own backing store (e.g. Qt WK1), update the repaint count before calling TextureMapperLayer::flushCompositingStateForThisLayerOnly().
    bool needsToRepaint = shouldHaveBackingStore() && (m_needsDisplay || !m_needsDisplayRect.isEmpty());
    if (isShowingRepaintCounter() && needsToRepaint) {
        incrementRepaintCount();
        m_changeMask |= RepaintCountChange;
    }
}
CoordinatedGraphicsLayer* CoordinatedGraphicsLayer::findFirstDescendantWithContentsRecursively()
{
    if (shouldHaveBackingStore())
        return this;

    for (size_t i = 0; i < children().size(); ++i) {
        CoordinatedGraphicsLayer* layer = toCoordinatedGraphicsLayer(children()[i])->findFirstDescendantWithContentsRecursively();
        if (layer)
            return layer;
    }

    return 0;
}
CoordinatedGraphicsLayer* CoordinatedGraphicsLayer::findFirstDescendantWithContentsRecursively()
{
    if (shouldHaveBackingStore())
        return this;

    for (auto& child : children()) {
        CoordinatedGraphicsLayer* layer = toCoordinatedGraphicsLayer(child)->findFirstDescendantWithContentsRecursively();
        if (layer)
            return layer;
    }

    return 0;
}
void GraphicsLayerTextureMapper::prepareBackingStoreIfNeeded()
{
    if (!shouldHaveBackingStore()) {
        m_backingStore.clear();
        m_changeMask |= BackingStoreChange;
    } else {
        if (!m_backingStore) {
            m_backingStore = TextureMapperTiledBackingStore::create();
            m_changeMask |= BackingStoreChange;
        }
    }

    updateDebugBorderAndRepaintCount();
}
void CoordinatedGraphicsLayer::adjustContentsScale()
{
    ASSERT(shouldHaveBackingStore());
    if (!m_mainBackingStore || m_mainBackingStore->contentsScale() == effectiveContentsScale())
        return;

    // Between creating the new backing store and painting the content,
    // we do not want to drop the previous one as that might result in
    // briefly seeing flickering as the old tiles may be dropped before
    // something replaces them.
    m_previousBackingStore = std::move(m_mainBackingStore);

    // No reason to save the previous backing store for non-visible areas.
    m_previousBackingStore->removeAllNonVisibleTiles();
}
void CoordinatedGraphicsLayer::deviceOrPageScaleFactorChanged()
{
    if (shouldHaveBackingStore())
        m_pendingContentsScaleAdjustment = true;
}
void CoordinatedGraphicsLayer::setNeedsVisibleRectAdjustment()
{
    if (shouldHaveBackingStore())
        m_pendingVisibleRectAdjustment = true;
}