Chromium Code Reviews| 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 bba9e8349ffac1fd7c69953fed21fd245cc181cb..a1cc74de781f625044ecdb65a3a4199f5a54656a 100644 |
| --- a/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp |
| +++ b/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp |
| @@ -201,6 +201,64 @@ 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; |
| @@ -212,11 +270,16 @@ Canvas2DLayerBridge::MailboxInfo& Canvas2DLayerBridge::createMailboxInfo() |
| bool Canvas2DLayerBridge::prepareMailboxFromImage(RefPtr<SkImage>& image, WebExternalTextureMailbox* outMailbox) |
| { |
| + GrContext* grContext = m_contextProvider->grContext(); |
| + if (RuntimeEnabledFeatures::canvas2dImageChromiumEnabled()) { |
| + if (grContext && prepareIOSurfaceMailboxFromImage(image, outMailbox)) |
|
Justin Novosad
2016/03/02 16:33:45
I think what you want here is:
if (!grContext)
|
| + return true; |
| + } |
| + |
| MailboxInfo& mailboxInfo = createMailboxInfo(); |
| mailboxInfo.m_mailbox.nearestNeighbor = getGLFilter() == GL_NEAREST; |
| mailboxInfo.m_image = image; |
| - GrContext* grContext = m_contextProvider->grContext(); |
| if (!grContext) |
| return true; // for testing: skip gl stuff when using a mock graphics context. |
| @@ -735,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); |
|
Justin Novosad
2016/03/02 16:33:45
This synchronisation is probably unnecessary? In t
|
| + } |
| + |
| + WebGraphicsContext3D* webContext = context(); |
| + GLenum target = GC3D_TEXTURE_RECTANGLE_ARB; |
|
Justin Novosad
2016/03/02 16:33:45
Does the extension for this need to be detected?
|
| + 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; |
| @@ -847,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) |