Exemplo n.º 1
0
void VideoLayerChromium::updateContentsIfDirty()
{
    if (!m_contentsDirty)
        return;

    RenderLayerBacking* backing = static_cast<RenderLayerBacking*>(m_owner->client());
    if (!backing || backing->paintingGoesToWindow())
        return;

    ASSERT(drawsContent());

    m_skipsDraw = false;
    VideoFrameChromium* frame = m_provider->getCurrentFrame();
    if (!frame) {
        m_skipsDraw = true;
        m_provider->putCurrentFrame(frame);
        return;
    }

    m_frameFormat = frame->format();
    unsigned textureFormat = determineTextureFormat(frame);
    if (textureFormat == GraphicsContext3D::INVALID_VALUE) {
        // FIXME: Implement other paths.
        notImplemented();
        m_skipsDraw = true;
        m_provider->putCurrentFrame(frame);
        return;
    }

    if (frame->surfaceType() == VideoFrameChromium::TypeTexture) {
        releaseCurrentFrame();
        saveCurrentFrame(frame);
        m_dirtyRect.setSize(FloatSize());
        m_contentsDirty = false;
        return;
    }

    // Allocate textures for planes if they are not allocated already, or
    // reallocate textures that are the wrong size for the frame.
    GraphicsContext3D* context = layerRendererContext();
    bool texturesAllocated = allocateTexturesIfNeeded(context, frame, textureFormat);
    if (!texturesAllocated) {
        m_skipsDraw = true;
        m_provider->putCurrentFrame(frame);
        return;
    }

    // Update texture planes.
    for (unsigned plane = 0; plane < frame->planes(); plane++) {
        ASSERT(frame->requiredTextureSize(plane) == m_textureSizes[plane]);
        updateTexture(context, m_textures[plane], frame->requiredTextureSize(plane), textureFormat, frame->data(plane));
    }

    m_dirtyRect.setSize(FloatSize());
    m_contentsDirty = false;

    m_provider->putCurrentFrame(frame);
}
Exemplo n.º 2
0
void LayerChromium::updateContents()
{
    RenderLayerBacking* backing = static_cast<RenderLayerBacking*>(m_owner->client());

    if (backing && !backing->paintingGoesToWindow() && drawsContent())
        m_owner->paintGraphicsLayerContents(*m_graphicsContext, IntRect(0, 0, m_bounds.width(), m_bounds.height()));

    m_contentsDirty = false;
}
void ContentLayerChromium::updateContents()
{
    RenderLayerBacking* backing = static_cast<RenderLayerBacking*>(m_owner->client());
    if (!backing || backing->paintingGoesToWindow())
        return;

    ASSERT(drawsContent());

    ASSERT(layerRenderer());

    void* pixels = 0;
    IntRect dirtyRect;
    IntRect updateRect;
    IntSize requiredTextureSize;
    IntSize bitmapSize;

    // FIXME: Remove this test when tiled layers are implemented.
    if (requiresClippedUpdateRect()) {
        // A layer with 3D transforms could require an arbitrarily large number
        // of texels to be repainted, so ignore these layers until tiling is
        // implemented.
        if (!drawTransform().isIdentityOrTranslation()) {
            m_skipsDraw = true;
            return;
        }

        calculateClippedUpdateRect(dirtyRect, m_largeLayerDrawRect);
        if (!layerRenderer()->checkTextureSize(m_largeLayerDrawRect.size())) {
            m_skipsDraw = true;
            return;
        }

        // If the portion of the large layer that's visible hasn't changed
        // then we don't need to update it, _unless_ its contents have changed
        // in which case we only update the dirty bits.
        if (m_largeLayerDirtyRect == dirtyRect) {
            if (!m_dirtyRect.intersects(dirtyRect))
                return;
            dirtyRect.intersect(IntRect(m_dirtyRect));
            updateRect = dirtyRect;
            requiredTextureSize = m_largeLayerDirtyRect.size();
        } else {
            m_largeLayerDirtyRect = dirtyRect;
            requiredTextureSize = dirtyRect.size();
            updateRect = IntRect(IntPoint(0, 0), dirtyRect.size());
        }
    } else {
        dirtyRect = IntRect(m_dirtyRect);
        IntRect boundsRect(IntPoint(0, 0), m_bounds);
        requiredTextureSize = m_bounds;
        // If the texture needs to be reallocated then we must redraw the entire
        // contents of the layer.
        if (requiredTextureSize != m_allocatedTextureSize)
            dirtyRect = boundsRect;
        else {
            // Clip the dirtyRect to the size of the layer to avoid drawing
            // outside the bounds of the backing texture.
            dirtyRect.intersect(boundsRect);
        }
        updateRect = dirtyRect;
    }

    if (dirtyRect.isEmpty())
        return;

#if PLATFORM(SKIA)
    const SkBitmap* skiaBitmap = 0;
    OwnPtr<skia::PlatformCanvas> canvas;
    OwnPtr<PlatformContextSkia> skiaContext;
    OwnPtr<GraphicsContext> graphicsContext;

    canvas.set(new skia::PlatformCanvas(dirtyRect.width(), dirtyRect.height(), false));
    skiaContext.set(new PlatformContextSkia(canvas.get()));

    // This is needed to get text to show up correctly.
    // FIXME: Does this take us down a very slow text rendering path?
    skiaContext->setDrawingToImageBuffer(true);

    graphicsContext.set(new GraphicsContext(reinterpret_cast<PlatformGraphicsContext*>(skiaContext.get())));

    // Bring the canvas into the coordinate system of the paint rect.
    canvas->translate(static_cast<SkScalar>(-dirtyRect.x()), static_cast<SkScalar>(-dirtyRect.y()));

    m_owner->paintGraphicsLayerContents(*graphicsContext, dirtyRect);
    const SkBitmap& bitmap = canvas->getDevice()->accessBitmap(false);
    skiaBitmap = &bitmap;
    ASSERT(skiaBitmap);

    SkAutoLockPixels lock(*skiaBitmap);
    SkBitmap::Config skiaConfig = skiaBitmap->config();
    // FIXME: do we need to support more image configurations?
    if (skiaConfig == SkBitmap::kARGB_8888_Config) {
        pixels = skiaBitmap->getPixels();
        bitmapSize = IntSize(skiaBitmap->width(), skiaBitmap->height());
    }
#elif PLATFORM(CG)
    Vector<uint8_t> tempVector;
    int rowBytes = 4 * dirtyRect.width();
    tempVector.resize(rowBytes * dirtyRect.height());
    memset(tempVector.data(), 0, tempVector.size());
    RetainPtr<CGColorSpaceRef> colorSpace(AdoptCF, CGColorSpaceCreateDeviceRGB());
    RetainPtr<CGContextRef> contextCG(AdoptCF, CGBitmapContextCreate(tempVector.data(),
                                                                     dirtyRect.width(), dirtyRect.height(), 8, rowBytes,
                                                                     colorSpace.get(),
                                                                     kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host));
    CGContextTranslateCTM(contextCG.get(), 0, dirtyRect.height());
    CGContextScaleCTM(contextCG.get(), 1, -1);

    GraphicsContext graphicsContext(contextCG.get());

    // Translate the graphics context into the coordinate system of the dirty rect.
    graphicsContext.translate(-dirtyRect.x(), -dirtyRect.y());

    m_owner->paintGraphicsLayerContents(graphicsContext, dirtyRect);

    pixels = tempVector.data();
    bitmapSize = dirtyRect.size();
#else
#error "Need to implement for your platform."
#endif

    unsigned textureId = m_contentsTexture;
    if (!textureId)
        textureId = layerRenderer()->createLayerTexture();

    if (pixels)
        updateTextureRect(pixels, bitmapSize, requiredTextureSize, updateRect, textureId);
}
Exemplo n.º 4
0
void LayerChromium::updateTextureContents(unsigned int textureId)
{
    RenderLayerBacking* backing = static_cast<RenderLayerBacking*>(m_owner->client());

    if (backing && !backing->paintingGoesToWindow()) {
        void* pixels = 0;
        IntRect dirtyRect(m_dirtyRect);
        IntSize requiredTextureSize;
        IntSize bitmapSize;
#if PLATFORM(SKIA)
        const SkBitmap* skiaBitmap = 0;
        OwnPtr<skia::PlatformCanvas> canvas;
        OwnPtr<PlatformContextSkia> skiaContext;
        OwnPtr<GraphicsContext> graphicsContext;
        if (drawsContent()) { // Layer contents must be drawn into a canvas.
            // Clip the dirtyRect to the size of the layer to avoid drawing outside
            // the bounds of the backing texture.
            dirtyRect.intersect(IntRect(IntPoint(0, 0), m_bounds));

            canvas.set(new skia::PlatformCanvas(dirtyRect.width(), dirtyRect.height(), false));
            skiaContext.set(new PlatformContextSkia(canvas.get()));

            // This is needed to get text to show up correctly. Without it,
            // GDI renders with zero alpha and the text becomes invisible.
            // Unfortunately, setting this to true disables cleartype.
            // FIXME: Does this take us down a very slow text rendering path?
            skiaContext->setDrawingToImageBuffer(true);

            graphicsContext.set(new GraphicsContext(reinterpret_cast<PlatformGraphicsContext*>(skiaContext.get())));

            // Bring the canvas into the coordinate system of the paint rect.
            canvas->translate(static_cast<SkScalar>(-dirtyRect.x()), static_cast<SkScalar>(-dirtyRect.y()));

            m_owner->paintGraphicsLayerContents(*graphicsContext, dirtyRect);
            const SkBitmap& bitmap = canvas->getDevice()->accessBitmap(false);
            skiaBitmap = &bitmap;
            requiredTextureSize = m_bounds;
        } else { // Layer is a container.
            // The layer contains an Image.
            NativeImageSkia* skiaImage = static_cast<NativeImageSkia*>(contents());
            skiaBitmap = skiaImage;
            requiredTextureSize = IntSize(skiaBitmap->width(), skiaBitmap->height());
        }

        ASSERT(skiaBitmap);
        SkAutoLockPixels lock(*skiaBitmap);
        SkBitmap::Config skiaConfig = skiaBitmap->config();
        // FIXME: do we need to support more image configurations?
        if (skiaConfig == SkBitmap::kARGB_8888_Config) {
            pixels = skiaBitmap->getPixels();
            bitmapSize = IntSize(skiaBitmap->width(), skiaBitmap->height());
        }
#else
#error "Need to implement for your platform."
#endif
        if (pixels) {
            glBindTexture(GL_TEXTURE_2D, textureId);
            // If the texture id or size changed since last time then we need to tell GL
            // to re-allocate a texture.
            if (m_allocatedTextureId != textureId || requiredTextureSize != m_allocatedTextureSize) {
                ASSERT(bitmapSize == requiredTextureSize);
                glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, requiredTextureSize.width(), requiredTextureSize.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);

                m_allocatedTextureId = textureId;
                m_allocatedTextureSize = requiredTextureSize;
            } else {
                ASSERT(dirtyRect.width() <= m_allocatedTextureSize.width() && dirtyRect.height() <= m_allocatedTextureSize.height());
                ASSERT(dirtyRect.width() == bitmapSize.width() && dirtyRect.height() == bitmapSize.height());
                glTexSubImage2D(GL_TEXTURE_2D, 0, dirtyRect.x(), dirtyRect.y(), dirtyRect.width(), dirtyRect.height(), GL_RGBA, GL_UNSIGNED_BYTE, pixels);
            }
        }
    }

    m_contentsDirty = false;
    m_dirtyRect.setSize(FloatSize());
}