Exemple #1
0
void DrawingBuffer::paintCompositedResultsToCanvas(ImageBuffer* imageBuffer)
{
    if (!m_context || !m_context->makeContextCurrent() || m_context->getExtensions()->getGraphicsResetStatusARB() != GraphicsContext3D::NO_ERROR)
        return;

    Extensions3D* extensions = m_context->getExtensions();
#if ENABLE(CANVAS_USES_MAILBOX)
    // Since the m_frontColorBuffer was produced and sent to the compositor, it cannot be bound to an fbo.
    // We have to make a copy of it here and bind that copy instead.
    unsigned sourceTexture = createColorTexture(m_size);
    extensions->copyTextureCHROMIUM(GraphicsContext3D::TEXTURE_2D, m_frontColorBuffer, sourceTexture, 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE);
#else
    // FIXME: Re-examine general correctness of this code beacause m_colorBuffer may contain a stale copy of the data
    // that was sent to the compositor at some point in the past.
    unsigned sourceTexture = frontColorBuffer();
#endif // ENABLE(CANVAS_USES_MAILBOX)

    // Since we're using the same context as WebGL, we have to restore any state we change (in this case, just the framebuffer binding).
    // FIXME: The WebGLRenderingContext tracks the current framebuffer binding, it would be slightly more efficient to use this value
    // rather than querying it off of the context.
    GC3Dint previousFramebuffer = 0;
    m_context->getIntegerv(GraphicsContext3D::FRAMEBUFFER_BINDING, &previousFramebuffer);

    Platform3DObject framebuffer = m_context->createFramebuffer();
    m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, framebuffer);
    m_context->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, sourceTexture, 0);

    extensions->paintFramebufferToCanvas(framebuffer, size().width(), size().height(), !m_attributes.premultipliedAlpha, imageBuffer);
    m_context->deleteFramebuffer(framebuffer);
#if ENABLE(CANVAS_USES_MAILBOX)
    m_context->deleteTexture(sourceTexture);
#endif // ENABLE(CANVAS_USES_MAILBOX)

    m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, previousFramebuffer);
}
bool ImageBuffer::copyToPlatformTexture(GraphicsContext3D& context, Platform3DObject texture, GC3Denum internalFormat, bool premultiplyAlpha, bool flipY)
{
    if (!m_data.m_layerBridge || !platformLayer())
        return false;

    Platform3DObject sourceTexture = m_data.m_layerBridge->backBufferTexture();

    if (!context.makeContextCurrent())
        return false;

    Extensions3D* extensions = context.getExtensions();
    if (!extensions->supports("GL_CHROMIUM_copy_texture") || !extensions->supports("GL_CHROMIUM_flipy"))
        return false;

    // The canvas is stored in a premultiplied format, so unpremultiply if necessary.
    context.pixelStorei(Extensions3D::UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM, !premultiplyAlpha);

    // The canvas is stored in an inverted position, so the flip semantics are reversed.
    context.pixelStorei(Extensions3D::UNPACK_FLIP_Y_CHROMIUM, !flipY);

    extensions->copyTextureCHROMIUM(GraphicsContext3D::TEXTURE_2D, sourceTexture, texture, 0, internalFormat);

    context.pixelStorei(Extensions3D::UNPACK_FLIP_Y_CHROMIUM, false);
    context.pixelStorei(Extensions3D::UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM, false);
    context.flush();
    return true;
}
Exemple #3
0
bool DrawingBuffer::prepareMailbox(WebKit::WebExternalTextureMailbox* outMailbox)
{
    if (!m_context || !m_contentsChanged || !m_lastColorBuffer)
        return false;

    m_context->makeContextCurrent();

    // Resolve the multisampled buffer into the texture referenced by m_lastColorBuffer mailbox.
    if (multisample())
        commit();

    // We must restore the texture binding since creating new textures,
    // consuming and producing mailboxes changes it.
    ScopedTextureUnit0BindingRestorer restorer(m_context.get(), m_activeTextureUnit, m_texture2DBinding);

    // First try to recycle an old buffer.
    RefPtr<MailboxInfo> nextFrontColorBuffer = getRecycledMailbox();

    // No buffer available to recycle, create a new one.
    if (!nextFrontColorBuffer) {
        unsigned newColorBuffer = createColorTexture(m_size);
        // Bad things happened, abandon ship.
        if (!newColorBuffer)
            return false;

        nextFrontColorBuffer = createNewMailbox(newColorBuffer);
    }

    if (m_preserveDrawingBuffer == Discard) {
        m_colorBuffer = nextFrontColorBuffer->textureId;
        swap(nextFrontColorBuffer, m_lastColorBuffer);
        // It appears safe to overwrite the context's framebuffer binding in the Discard case since there will always be a
        // WebGLRenderingContext::clearIfComposited() call made before the next draw call which restores the framebuffer binding.
        // If this stops being true at some point, we should track the current framebuffer binding in the DrawingBuffer and restore
        // it after attaching the new back buffer here.
        m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_fbo);
        m_context->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, m_colorBuffer, 0);
    } else {
        Extensions3D* extensions = m_context->getExtensions();
        extensions->copyTextureCHROMIUM(GraphicsContext3D::TEXTURE_2D, m_colorBuffer, nextFrontColorBuffer->textureId, 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE);
    }

    if (multisample() && !m_framebufferBinding)
        bind();
    else
        restoreFramebufferBinding();

    m_contentsChanged = false;

    context()->bindTexture(GraphicsContext3D::TEXTURE_2D, nextFrontColorBuffer->textureId);
    context()->produceTextureCHROMIUM(GraphicsContext3D::TEXTURE_2D, nextFrontColorBuffer->mailbox.name);
    context()->flush();
    m_context->markLayerComposited();

    *outMailbox = nextFrontColorBuffer->mailbox;
    m_frontColorBuffer = nextFrontColorBuffer->textureId;
    return true;
}