| Index: third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp
|
| diff --git a/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp b/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp
|
| index dca9edb51fab5a44b422ded286e701d4d3603848..a1cc74de781f625044ecdb65a3a4199f5a54656a 100644
|
| --- a/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp
|
| +++ b/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp
|
| @@ -196,6 +196,144 @@ bool Canvas2DLayerBridge::isAccelerated() const
|
| return shouldAccelerate(PreferAcceleration);
|
| }
|
|
|
| +GLenum Canvas2DLayerBridge::getGLFilter()
|
| +{
|
| + return m_filterQuality == kNone_SkFilterQuality ? GL_NEAREST : GL_LINEAR;
|
| +}
|
| +
|
| +bool Canvas2DLayerBridge::prepareIOSurfaceMailboxFromImage(RefPtr<SkImage>& image, WebExternalTextureMailbox* outMailbox)
|
| +{
|
| + GLuint textureId, imageId;
|
| + if (!createIOSurfaceBackedTexture(&textureId, &imageId))
|
| + return false;
|
| +
|
| + GLuint imageTexture = skia::GrBackendObjectToGrGLTextureInfo(image->getTextureHandle(true))->fID;
|
| + context()->copyTextureCHROMIUM(imageTexture, textureId, GL_BGRA_EXT, GL_UNSIGNED_BYTE, GL_FALSE, GL_FALSE, GL_FALSE);
|
| +
|
| + MailboxInfo& info = createMailboxInfo();
|
| + info.m_mailbox.textureTarget = GC3D_TEXTURE_RECTANGLE_ARB;
|
| + context()->genMailboxCHROMIUM(info.m_mailbox.name);
|
| + context()->produceTextureDirectCHROMIUM(textureId, info.m_mailbox.textureTarget, info.m_mailbox.name);
|
| + info.m_mailbox.allowOverlay = true;
|
| + info.m_mailbox.nearestNeighbor = getGLFilter();
|
| +
|
| + const WGC3Duint64 fenceSync = context()->insertFenceSyncCHROMIUM();
|
| + context()->flush();
|
| + info.m_mailbox.validSyncToken = context()->genSyncTokenCHROMIUM(fenceSync, info.m_mailbox.syncToken);
|
| +
|
| + info.m_CHROMIUMImageId = imageId;
|
| + info.m_textureId = textureId;
|
| + *outMailbox = info.m_mailbox;
|
| +
|
| + // Because we are changing the texture binding without going through skia,
|
| + // we must dirty the context.
|
| + GrContext* grContext = m_contextProvider->grContext();
|
| + grContext->resetContext(kTextureBinding_GrGLBackendState);
|
| +
|
| + return true;
|
| +}
|
| +
|
| +bool Canvas2DLayerBridge::createIOSurfaceBackedTexture(GLuint* outTexture, GLuint* outImageId)
|
| +{
|
| + WebGraphicsContext3D* webContext = context();
|
| + GLuint imageId = webContext->createGpuMemoryBufferImageCHROMIUM(m_size.width(), m_size.height(), GL_BGRA_EXT, GC3D_SCANOUT_CHROMIUM);
|
| + if (!imageId)
|
| + return false;
|
| +
|
| + GLuint textureId= webContext->createTexture();
|
| + if (!textureId) {
|
| + webContext->destroyImageCHROMIUM(imageId);
|
| + return false;
|
| + }
|
| +
|
| + GLenum target = GC3D_TEXTURE_RECTANGLE_ARB;
|
| + webContext->bindTexture(target, textureId);
|
| + webContext->texParameteri(target, GL_TEXTURE_MAG_FILTER, getGLFilter());
|
| + webContext->texParameteri(target, GL_TEXTURE_MIN_FILTER, getGLFilter());
|
| + webContext->texParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
| + webContext->texParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
| + webContext->bindTexImage2DCHROMIUM(target, imageId);
|
| +
|
| + *outTexture = textureId;
|
| + *outImageId = imageId;
|
| + return true;
|
| +}
|
| +
|
| +Canvas2DLayerBridge::MailboxInfo& Canvas2DLayerBridge::createMailboxInfo()
|
| +{
|
| + MailboxInfo tmp;
|
| + tmp.m_parentLayerBridge = this;
|
| + m_mailboxes.prepend(tmp);
|
| + MailboxInfo& mailboxInfo = m_mailboxes.first();
|
| + return mailboxInfo;
|
| +}
|
| +
|
| +bool Canvas2DLayerBridge::prepareMailboxFromImage(RefPtr<SkImage>& image, WebExternalTextureMailbox* outMailbox)
|
| +{
|
| + GrContext* grContext = m_contextProvider->grContext();
|
| + if (RuntimeEnabledFeatures::canvas2dImageChromiumEnabled()) {
|
| + if (grContext && prepareIOSurfaceMailboxFromImage(image, outMailbox))
|
| + return true;
|
| + }
|
| +
|
| + MailboxInfo& mailboxInfo = createMailboxInfo();
|
| + mailboxInfo.m_mailbox.nearestNeighbor = getGLFilter() == GL_NEAREST;
|
| + mailboxInfo.m_image = image;
|
| +
|
| + if (!grContext)
|
| + return true; // for testing: skip gl stuff when using a mock graphics context.
|
| +
|
| + if (RuntimeEnabledFeatures::forceDisable2dCanvasCopyOnWriteEnabled())
|
| + m_surface->notifyContentWillChange(SkSurface::kRetain_ContentChangeMode);
|
| +
|
| + // Need to flush skia's internal queue because texture is about to be accessed directly
|
| + grContext->flush();
|
| +
|
| + // 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();
|
| + mailboxInfo.m_mailbox.textureTarget = GL_TEXTURE_2D;
|
| +
|
| + WebGraphicsContext3D* webContext = context();
|
| + GLuint textureID = skia::GrBackendObjectToGrGLTextureInfo(mailboxInfo.m_image->getTextureHandle(true))->fID;
|
| + webContext->bindTexture(GL_TEXTURE_2D, textureID);
|
| + webContext->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, getGLFilter());
|
| + webContext->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, getGLFilter());
|
| + 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 currently the canvas will flicker if we don't flush here.
|
| + const WGC3Duint64 fenceSync = webContext->insertFenceSyncCHROMIUM();
|
| + webContext->flush();
|
| + mailboxInfo.m_mailbox.validSyncToken = webContext->genSyncTokenCHROMIUM(fenceSync, mailboxInfo.m_mailbox.syncToken);
|
| + }
|
| + 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;
|
| +}
|
| +
|
| static void hibernateWrapper(WeakPtr<Canvas2DLayerBridge> bridge, double /*idleDeadline*/)
|
| {
|
| if (bridge) {
|
| @@ -616,75 +754,14 @@ bool Canvas2DLayerBridge::prepareMailbox(WebExternalTextureMailbox* outMailbox,
|
| if (!image || !image->getTexture())
|
| return false;
|
|
|
| - WebGraphicsContext3D* webContext = context();
|
| -
|
| - // Early exit if canvas was not drawn to since last prepareMailbox
|
| - GLenum filter = m_filterQuality == kNone_SkFilterQuality ? GL_NEAREST : GL_LINEAR;
|
| + // Early exit if canvas was not drawn to since last prepareMailbox.
|
| + GLenum filter = getGLFilter();
|
| 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.
|
| -
|
| - if (RuntimeEnabledFeatures::forceDisable2dCanvasCopyOnWriteEnabled())
|
| - m_surface->notifyContentWillChange(SkSurface::kRetain_ContentChangeMode);
|
| -
|
| - // 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();
|
| - mailboxInfo.m_mailbox.textureTarget = GL_TEXTURE_2D;
|
| -
|
| - // Passing true because we need to flush skia's internal queue since texture is about to be accessed directly
|
| - GLuint textureID = skia::GrBackendObjectToGrGLTextureInfo(mailboxInfo.m_image->getTextureHandle(true))->fID;
|
| - webContext->bindTexture(GL_TEXTURE_2D, textureID);
|
| - 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 currently the canvas will flicker if we don't flush here.
|
| - const WGC3Duint64 fenceSync = webContext->insertFenceSyncCHROMIUM();
|
| - webContext->flush();
|
| - mailboxInfo.m_mailbox.validSyncToken = webContext->genSyncTokenCHROMIUM(fenceSync, mailboxInfo.m_mailbox.syncToken);
|
| - }
|
| - 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;
|
| + return prepareMailboxFromImage(image, outMailbox);
|
| }
|
|
|
| void Canvas2DLayerBridge::mailboxReleased(const WebExternalTextureMailbox& mailbox, bool lostResource)
|
| @@ -721,6 +798,27 @@ void Canvas2DLayerBridge::mailboxReleased(const WebExternalTextureMailbox& mailb
|
| }
|
| }
|
| }
|
| +
|
| + if (releasedMailboxInfo->m_CHROMIUMImageId) {
|
| + ASSERT(releasedMailboxInfo->m_textureId);
|
| + ASSERT(!releasedMailboxInfo->m_image);
|
| + if (mailbox.validSyncToken) {
|
| + context()->waitSyncTokenCHROMIUM(mailbox.syncToken);
|
| + }
|
| +
|
| + WebGraphicsContext3D* webContext = context();
|
| + GLenum target = GC3D_TEXTURE_RECTANGLE_ARB;
|
| + webContext->bindTexture(target, releasedMailboxInfo->m_textureId);
|
| + webContext->releaseTexImage2DCHROMIUM(target, releasedMailboxInfo->m_CHROMIUMImageId);
|
| + webContext->destroyImageCHROMIUM(releasedMailboxInfo->m_CHROMIUMImageId);
|
| + webContext->deleteTexture(releasedMailboxInfo->m_textureId);
|
| + webContext->bindTexture(target, 0);
|
| +
|
| + // Because we are changing the texture binding without going through skia,
|
| + // we must dirty the context.
|
| + GrContext* grContext = m_contextProvider->grContext();
|
| + grContext->resetContext(kTextureBinding_GrGLBackendState);
|
| + }
|
| }
|
|
|
| RefPtr<Canvas2DLayerBridge> selfRef;
|
| @@ -833,6 +931,8 @@ Canvas2DLayerBridge::MailboxInfo::MailboxInfo(const MailboxInfo& other)
|
| memcpy(&m_mailbox, &other.m_mailbox, sizeof(m_mailbox));
|
| m_image = other.m_image;
|
| m_parentLayerBridge = other.m_parentLayerBridge;
|
| + m_CHROMIUMImageId = other.m_CHROMIUMImageId;
|
| + m_textureId = other.m_textureId;
|
| }
|
|
|
| void Canvas2DLayerBridge::Logger::reportHibernationEvent(HibernationEvent event)
|
|
|