Exemplo n.º 1
0
bool Canvas2DLayerBridge::restoreSurface()
{
    ASSERT(!m_destructionInProgress);
    if (m_destructionInProgress)
        return false;
    ASSERT(m_layer && !m_isSurfaceValid);

    WebGraphicsContext3D* sharedContext = 0;
    // We must clear the mailboxes before calling m_layer->clearTexture() to prevent
    // re-entry via mailboxReleased from operating on defunct GrContext objects.
    m_mailboxes.clear();
    m_layer->clearTexture();
    m_contextProvider = adoptPtr(Platform::current()->createSharedOffscreenGraphicsContext3DProvider());
    if (m_contextProvider)
        sharedContext = m_contextProvider->context3d();

    if (sharedContext && !sharedContext->isContextLost()) {
        IntSize size(m_canvas->getTopDevice()->width(), m_canvas->getTopDevice()->height());
        RefPtr<SkSurface> surface(createSkSurface(m_contextProvider->grContext(), size, m_msaaSampleCount, m_opacityMode));
        if (surface.get()) {
            m_surface = surface.release();
            m_canvas->setSurface(m_surface.get());
            m_isSurfaceValid = true;
            // FIXME: draw sad canvas picture into new buffer crbug.com/243842
        }
    }

    return m_isSurfaceValid;
}
Exemplo n.º 2
0
bool Canvas2DLayerBridge::restoreSurface()
{
    ASSERT(!m_destructionInProgress);
    if (m_destructionInProgress)
        return false;
    ASSERT(isAccelerated() && !m_surface);

    WebGraphicsContext3D* sharedContext = 0;
    m_layer->clearTexture();
    m_contextProvider = adoptPtr(Platform::current()->createSharedOffscreenGraphicsContext3DProvider());
    if (m_contextProvider)
        sharedContext = m_contextProvider->context3d();

    if (sharedContext && !sharedContext->isContextLost()) {
        GrContext* grCtx = m_contextProvider->grContext();
        bool surfaceIsAccelerated;
        RefPtr<SkSurface> surface(createSkSurface(grCtx, m_size, m_msaaSampleCount, m_opacityMode, &surfaceIsAccelerated));
        // Current paradigm does support switching from accelerated to non-accelerated, which would be tricky
        // due to changes to the layer tree, which can only happen at specific times during the document lifecycle.
        // Therefore, we can only accept the restored surface if it is accelerated.
        if (surface.get() && surfaceIsAccelerated) {
            m_surface = surface.release();
            // FIXME: draw sad canvas picture into new buffer crbug.com/243842
        }
    }

    return m_surface;
}
bool Canvas2DLayerBridge::restoreSurface()
{
    ASSERT(!m_destructionInProgress);
    if (m_destructionInProgress)
        return false;
    ASSERT(m_layer && !m_surface);

    WebGraphicsContext3D* sharedContext = 0;
    m_layer->clearTexture();
    m_contextProvider = adoptPtr(Platform::current()->createSharedOffscreenGraphicsContext3DProvider());
    if (m_contextProvider)
        sharedContext = m_contextProvider->context3d();

    if (sharedContext && !sharedContext->isContextLost()) {
        GrContext* grCtx = m_contextProvider->grContext();
        RefPtr<SkSurface> surface(createSkSurface(grCtx, m_size, m_msaaSampleCount, m_opacityMode));
        if (surface.get()) {
            m_surface = surface.release();
            m_initialSurfaceSaveCount = m_surface->getCanvas()->getSaveCount();
            // FIXME: draw sad canvas picture into new buffer crbug.com/243842
        }
    }

    return m_surface;
}
bool Canvas2DLayerBridge::restoreSurface()
{
    ASSERT(!m_destructionInProgress);
    if (m_destructionInProgress)
        return false;
    ASSERT(m_layer && !m_isSurfaceValid);

    WebGraphicsContext3D* sharedContext = 0;
    m_layer->clearTexture();
    m_contextProvider = adoptPtr(Platform::current()->createSharedOffscreenGraphicsContext3DProvider());
    if (m_contextProvider)
        sharedContext = m_contextProvider->context3d();

    if (sharedContext && !sharedContext->isContextLost()) {
        SkISize skSize = m_canvas->getBaseLayerSize();
        IntSize size(skSize.width(), skSize.height());
        RefPtr<SkSurface> surface(createSkSurface(m_contextProvider->grContext(), size, m_msaaSampleCount, m_opacityMode));
        if (surface.get()) {
            m_surface = surface.release();
            m_canvas->setSurface(m_surface.get());
            m_isSurfaceValid = true;
            // FIXME: draw sad canvas picture into new buffer crbug.com/243842
        }
    }

    return m_isSurfaceValid;
}
Exemplo n.º 5
0
void Canvas2DLayerBridge::flushGpu()
{
    TRACE_EVENT0("cc", "Canvas2DLayerBridge::flushGpu");
    flush();
    WebGraphicsContext3D* webContext = context();
    if (isAccelerated() && webContext)
        webContext->flush();
}
Exemplo n.º 6
0
void WebGLProgram::cacheInfoIfNeeded()
{
    if (m_infoValid)
        return;

    if (!m_object)
        return;

    if (!contextGroup())
        return;
    WebGraphicsContext3D* context = contextGroup()->getAWebGraphicsContext3D();
    if (!context)
        return;
    GLint linkStatus = 0;
    context->getProgramiv(m_object, GL_LINK_STATUS, &linkStatus);
    m_linkStatus = linkStatus;
    if (m_linkStatus)
        cacheActiveAttribLocations(context);
    m_infoValid = true;
}
Exemplo n.º 7
0
bool ImageBuffer::copyToPlatformTexture(WebGraphicsContext3D* context, Platform3DObject texture, GLenum internalFormat, GLenum destType, GLint level, bool premultiplyAlpha, bool flipY)
{
    if (!Extensions3DUtil::canUseCopyTextureCHROMIUM(GL_TEXTURE_2D, internalFormat, destType, level))
        return false;

    if (!isSurfaceValid())
        return false;

    RefPtr<const SkImage> textureImage = m_surface->newImageSnapshot(PreferAcceleration);
    if (!textureImage)
        return false;

    if (!m_surface->isAccelerated())
        return false;


    ASSERT(textureImage->isTextureBacked()); // isAccelerated() check above should guarantee this
    // Get the texture ID, flushing pending operations if needed.
    Platform3DObject textureId = textureImage->getTextureHandle(true);
    if (!textureId)
        return false;

    OwnPtr<WebGraphicsContext3DProvider> provider = adoptPtr(Platform::current()->createSharedOffscreenGraphicsContext3DProvider());
    if (!provider)
        return false;
    WebGraphicsContext3D* sharedContext = provider->context3d();
    if (!sharedContext)
        return false;

    OwnPtr<WebExternalTextureMailbox> mailbox = adoptPtr(new WebExternalTextureMailbox);

    // Contexts may be in a different share group. We must transfer the texture through a mailbox first
    sharedContext->genMailboxCHROMIUM(mailbox->name);
    sharedContext->produceTextureDirectCHROMIUM(textureId, GL_TEXTURE_2D, mailbox->name);
    sharedContext->flush();

    mailbox->validSyncToken = sharedContext->insertSyncPoint(mailbox->syncToken);
    if (mailbox->validSyncToken)
        context->waitSyncToken(mailbox->syncToken);

    Platform3DObject sourceTexture = context->createAndConsumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox->name);

    // The canvas is stored in a premultiplied format, so unpremultiply if necessary.
    // The canvas is stored in an inverted position, so the flip semantics are reversed.
    context->copyTextureCHROMIUM(GL_TEXTURE_2D, sourceTexture, texture, internalFormat, destType, flipY ? GL_FALSE : GL_TRUE, GL_FALSE, premultiplyAlpha ? GL_FALSE : GL_TRUE);

    context->deleteTexture(sourceTexture);

    context->flush();

    WGC3Dbyte syncToken[24];
    if (context->insertSyncPoint(syncToken))
        sharedContext->waitSyncToken(syncToken);

    // Undo grContext texture binding changes introduced in this function
    provider->grContext()->resetContext(kTextureBinding_GrGLBackendState);

    return true;
}
Exemplo n.º 8
0
bool ImageBuffer::copyToPlatformTexture(WebGraphicsContext3D* context, Platform3DObject texture, GLenum internalFormat, GLenum destType, GLint level, bool premultiplyAlpha, bool flipY)
{
    if (!m_surface->isAccelerated() || !getBackingTexture() || !isSurfaceValid())
        return false;

    if (!Extensions3DUtil::canUseCopyTextureCHROMIUM(internalFormat, destType, level))
        return false;

    OwnPtr<WebGraphicsContext3DProvider> provider = adoptPtr(Platform::current()->createSharedOffscreenGraphicsContext3DProvider());
    if (!provider)
        return false;
    WebGraphicsContext3D* sharedContext = provider->context3d();
    if (!sharedContext)
        return false;

    OwnPtr<WebExternalTextureMailbox> mailbox = adoptPtr(new WebExternalTextureMailbox);

    // Contexts may be in a different share group. We must transfer the texture through a mailbox first
    sharedContext->genMailboxCHROMIUM(mailbox->name);
    sharedContext->produceTextureDirectCHROMIUM(getBackingTexture(), GL_TEXTURE_2D, mailbox->name);
    sharedContext->flush();

    mailbox->syncPoint = sharedContext->insertSyncPoint();

    context->waitSyncPoint(mailbox->syncPoint);
    Platform3DObject sourceTexture = context->createAndConsumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox->name);

    // The canvas is stored in a premultiplied format, so unpremultiply if necessary.
    context->pixelStorei(GC3D_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM, !premultiplyAlpha);

    // The canvas is stored in an inverted position, so the flip semantics are reversed.
    context->pixelStorei(GC3D_UNPACK_FLIP_Y_CHROMIUM, !flipY);
    context->copyTextureCHROMIUM(GL_TEXTURE_2D, sourceTexture, texture, level, internalFormat, destType);

    context->pixelStorei(GC3D_UNPACK_FLIP_Y_CHROMIUM, false);
    context->pixelStorei(GC3D_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM, false);

    context->deleteTexture(sourceTexture);

    context->flush();
    sharedContext->waitSyncPoint(context->insertSyncPoint());

    // Undo grContext texture binding changes introduced in this function
    provider->grContext()->resetContext(kTextureBinding_GrGLBackendState);

    return true;
}
Exemplo n.º 9
0
bool Canvas2DLayerBridge::prepareMailbox(WebExternalTextureMailbox* outMailbox, WebExternalBitmap* bitmap)
{
    ASSERT(isAccelerated());
    if (m_destructionInProgress) {
        // It can be hit in the following sequence.
        // 1. Canvas draws something.
        // 2. The compositor begins the frame.
        // 3. Javascript makes a context be lost.
        // 4. Here.
        return false;
    }
    if (bitmap) {
        // Using accelerated 2d canvas with software renderer, which
        // should only happen in tests that use fake graphics contexts
        // or in Android WebView in software mode. In this case, we do
        // not care about producing any results for this canvas.
        skipQueuedDrawCommands();
        m_lastImageId = 0;
        return false;
    }
    if (!checkSurfaceValid())
        return false;

    WebGraphicsContext3D* webContext = context();

    RefPtr<SkImage> image = newImageSnapshot(PreferAcceleration);

    // Early exit if canvas was not drawn to since last prepareMailbox
    GLenum filter = m_filterQuality == kNone_SkFilterQuality ? GL_NEAREST : GL_LINEAR;
    if (image->uniqueID() == m_lastImageId && filter == m_lastFilter)
        return false;
    m_lastImageId = image->uniqueID();
    m_lastFilter = filter;

    {
        MailboxInfo tmp;
        tmp.m_image = image;
        tmp.m_parentLayerBridge = this;
        m_mailboxes.prepend(tmp);
    }
    MailboxInfo& mailboxInfo = m_mailboxes.first();

    mailboxInfo.m_mailbox.nearestNeighbor = filter == GL_NEAREST;

    GrContext* grContext = m_contextProvider->grContext();
    if (!grContext)
        return true; // for testing: skip gl stuff when using a mock graphics context.

    // Need to flush skia's internal queue because texture is about to be accessed directly
    grContext->flush();

    ASSERT(image->getTexture());

    // Because of texture sharing with the compositor, we must invalidate
    // the state cached in skia so that the deferred copy on write
    // in SkSurface_Gpu does not make any false assumptions.
    mailboxInfo.m_image->getTexture()->textureParamsModified();

    webContext->bindTexture(GL_TEXTURE_2D, mailboxInfo.m_image->getTexture()->getTextureHandle());
    webContext->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter);
    webContext->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter);
    webContext->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    webContext->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

    // Re-use the texture's existing mailbox, if there is one.
    if (image->getTexture()->getCustomData()) {
        ASSERT(image->getTexture()->getCustomData()->size() == sizeof(mailboxInfo.m_mailbox.name));
        memcpy(&mailboxInfo.m_mailbox.name[0], image->getTexture()->getCustomData()->data(), sizeof(mailboxInfo.m_mailbox.name));
    } else {
        context()->genMailboxCHROMIUM(mailboxInfo.m_mailbox.name);
        RefPtr<SkData> mailboxNameData = adoptRef(SkData::NewWithCopy(&mailboxInfo.m_mailbox.name[0], sizeof(mailboxInfo.m_mailbox.name)));
        image->getTexture()->setCustomData(mailboxNameData.get());
        webContext->produceTextureCHROMIUM(GL_TEXTURE_2D, mailboxInfo.m_mailbox.name);
    }

    if (isHidden()) {
        // With hidden canvases, we release the SkImage immediately because
        // there is no need for animations to be double buffered.
        mailboxInfo.m_image.clear();
    } else {
        // FIXME: We'd rather insert a syncpoint than perform a flush here,
        // but currentlythe canvas will flicker if we don't flush here.
        webContext->flush();
        // mailboxInfo.m_mailbox.syncPoint = webContext->insertSyncPoint();
    }
    webContext->bindTexture(GL_TEXTURE_2D, 0);
    // Because we are changing the texture binding without going through skia,
    // we must dirty the context.
    grContext->resetContext(kTextureBinding_GrGLBackendState);

    *outMailbox = mailboxInfo.m_mailbox;
    return true;
}
Exemplo n.º 10
0
// static
bool WebGLDrawBuffers::satisfiesWebGLRequirements(WebGLRenderingContextBase* webglContext)
{
    WebGraphicsContext3D* context = webglContext->webContext();
    Extensions3DUtil* extensionsUtil = webglContext->extensionsUtil();

    // This is called after we make sure GL_EXT_draw_buffers is supported.
    GLint maxDrawBuffers = 0;
    GLint maxColorAttachments = 0;
    context->getIntegerv(GL_MAX_DRAW_BUFFERS_EXT, &maxDrawBuffers);
    context->getIntegerv(GL_MAX_COLOR_ATTACHMENTS_EXT, &maxColorAttachments);
    if (maxDrawBuffers < 4 || maxColorAttachments < 4)
        return false;

    Platform3DObject fbo = context->createFramebuffer();
    context->bindFramebuffer(GL_FRAMEBUFFER, fbo);

    const unsigned char* buffer = 0; // Chromium doesn't allow init data for depth/stencil tetxures.
    bool supportsDepth = (extensionsUtil->supportsExtension("GL_CHROMIUM_depth_texture")
        || extensionsUtil->supportsExtension("GL_OES_depth_texture")
        || extensionsUtil->supportsExtension("GL_ARB_depth_texture"));
    bool supportsDepthStencil = (extensionsUtil->supportsExtension("GL_EXT_packed_depth_stencil")
        || extensionsUtil->supportsExtension("GL_OES_packed_depth_stencil"));
    Platform3DObject depthStencil = 0;
    if (supportsDepthStencil) {
        depthStencil = context->createTexture();
        context->bindTexture(GL_TEXTURE_2D, depthStencil);
        context->texImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_STENCIL_OES, 1, 1, 0, GL_DEPTH_STENCIL_OES, GL_UNSIGNED_INT_24_8_OES, buffer);
    }
    Platform3DObject depth = 0;
    if (supportsDepth) {
        depth = context->createTexture();
        context->bindTexture(GL_TEXTURE_2D, depth);
        context->texImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, 1, 1, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, buffer);
    }

    Vector<Platform3DObject> colors;
    bool ok = true;
    GLint maxAllowedBuffers = std::min(maxDrawBuffers, maxColorAttachments);
    for (GLint i = 0; i < maxAllowedBuffers; ++i) {
        Platform3DObject color = context->createTexture();
        colors.append(color);
        context->bindTexture(GL_TEXTURE_2D, color);
        context->texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
        context->framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D, color, 0);
        if (context->checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
            ok = false;
            break;
        }
        if (supportsDepth) {
            context->framebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depth, 0);
            if (context->checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
                ok = false;
                break;
            }
            context->framebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
        }
        if (supportsDepthStencil) {
            context->framebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthStencil, 0);
            context->framebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, depthStencil, 0);
            if (context->checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
                ok = false;
                break;
            }
            context->framebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
            context->framebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
        }
    }

    webglContext->restoreCurrentFramebuffer();
    context->deleteFramebuffer(fbo);
    webglContext->restoreCurrentTexture2D();
    if (supportsDepth)
        context->deleteTexture(depth);
    if (supportsDepthStencil)
        context->deleteTexture(depthStencil);
    for (size_t i = 0; i < colors.size(); ++i)
        context->deleteTexture(colors[i]);
    return ok;
}