Chromium Code Reviews| Index: third_party/WebKit/Source/platform/graphics/AcceleratedStaticBitmapImage.cpp |
| diff --git a/third_party/WebKit/Source/platform/graphics/AcceleratedStaticBitmapImage.cpp b/third_party/WebKit/Source/platform/graphics/AcceleratedStaticBitmapImage.cpp |
| index 4edc487659396e3618008b615538eeab3ef0b13e..8fdbd618bb62964920e02252985a4a4a0404f971 100644 |
| --- a/third_party/WebKit/Source/platform/graphics/AcceleratedStaticBitmapImage.cpp |
| +++ b/third_party/WebKit/Source/platform/graphics/AcceleratedStaticBitmapImage.cpp |
| @@ -5,6 +5,7 @@ |
| #include "platform/graphics/AcceleratedStaticBitmapImage.h" |
| #include "gpu/command_buffer/client/gles2_interface.h" |
| +#include "gpu/command_buffer/common/sync_token.h" |
| #include "platform/graphics/StaticBitmapImage.h" |
| #include "platform/graphics/skia/SkiaUtils.h" |
| #include "public/platform/Platform.h" |
| @@ -13,138 +14,118 @@ |
| #include "third_party/skia/include/core/SkImage.h" |
| #include "third_party/skia/include/gpu/GrContext.h" |
| #include "wtf/PtrUtil.h" |
| + |
| #include <memory> |
| +#include <utility> |
| namespace blink { |
| -PassRefPtr<AcceleratedStaticBitmapImage> AcceleratedStaticBitmapImage::create(WebExternalTextureMailbox& mailbox) |
| -{ |
| - return adoptRef(new AcceleratedStaticBitmapImage(mailbox)); |
| -} |
| - |
| PassRefPtr<AcceleratedStaticBitmapImage> AcceleratedStaticBitmapImage::create(PassRefPtr<SkImage> image) |
| { |
| return adoptRef(new AcceleratedStaticBitmapImage(image)); |
| } |
| -AcceleratedStaticBitmapImage::AcceleratedStaticBitmapImage(WebExternalTextureMailbox& mailbox) |
| - : StaticBitmapImage() |
| - , m_mailbox(mailbox) |
| +PassRefPtr<AcceleratedStaticBitmapImage> AcceleratedStaticBitmapImage::create(PassRefPtr<SkImage> image, PassRefPtr<GrContext> grContext, const gpu::Mailbox& mailbox, const gpu::SyncToken& syncToken) |
| { |
| + return adoptRef(new AcceleratedStaticBitmapImage(image, std::move(grContext), mailbox, syncToken)); |
| } |
| AcceleratedStaticBitmapImage::AcceleratedStaticBitmapImage(PassRefPtr<SkImage> image) |
| - : StaticBitmapImage(image) |
| + : StaticBitmapImage(std::move(image)) |
| + , m_imageIsForSharedMainThreadContext(true) |
| { |
| } |
| -IntSize AcceleratedStaticBitmapImage::size() const |
| +AcceleratedStaticBitmapImage::AcceleratedStaticBitmapImage(PassRefPtr<SkImage> image, PassRefPtr<GrContext> grContext, const gpu::Mailbox& mailbox, const gpu::SyncToken& syncToken) |
| + : StaticBitmapImage(std::move(image)) |
| + , m_imageIsForSharedMainThreadContext(false) // TODO(danakj): Could be true though, caller would know. |
| + , m_grContext(std::move(grContext)) |
| + , m_hasMailbox(true) |
| + , m_mailbox(mailbox) |
| + , m_syncToken(syncToken) |
| { |
| - if (m_image) |
| - return IntSize(m_image->width(), m_image->height()); |
| - return IntSize(m_mailbox.textureSize.width, m_mailbox.textureSize.height); |
| + DCHECK(m_grContext); |
| } |
| -void AcceleratedStaticBitmapImage::copyToTexture(WebGraphicsContext3DProvider* provider, GLuint destinationTexture, GLenum internalFormat, GLenum destType, bool flipY) |
| -{ |
| - GLuint textureId = switchStorageToSkImageForWebGL(provider); |
| - gpu::gles2::GLES2Interface* gl = provider->contextGL(); |
| - if (!gl) |
| - return; |
| - gl->CopyTextureCHROMIUM(textureId, destinationTexture, internalFormat, destType, flipY, false, false); |
| - const GLuint64 fenceSync = gl->InsertFenceSyncCHROMIUM(); |
| - gl->Flush(); |
| - GLbyte syncToken[24]; |
| - gl->GenSyncTokenCHROMIUM(fenceSync, syncToken); |
| - // Get a new mailbox because we cannot retain a texture in the WebGL context. |
| - switchStorageToMailbox(provider); |
| -} |
| +AcceleratedStaticBitmapImage::~AcceleratedStaticBitmapImage() = default; |
| -bool AcceleratedStaticBitmapImage::switchStorageToMailbox(WebGraphicsContext3DProvider* provider) |
| +void AcceleratedStaticBitmapImage::copyToTexture(WebGraphicsContext3DProvider* destProvider, GLuint destTextureId, GLenum internalFormat, GLenum destType, bool flipY) |
| { |
| - m_mailbox.textureSize = WebSize(m_image->width(), m_image->height()); |
| - GrContext* grContext = provider->grContext(); |
| - if (!grContext) |
| - return false; |
| - grContext->flush(); |
| - m_mailbox.textureTarget = GL_TEXTURE_2D; |
| - gpu::gles2::GLES2Interface* gl = provider->contextGL(); |
| - if (!gl) |
| - return false; |
| - GLuint textureID = skia::GrBackendObjectToGrGLTextureInfo(m_image->getTextureHandle(true))->fID; |
| - gl->BindTexture(GL_TEXTURE_2D, textureID); |
| - |
| - gl->GenMailboxCHROMIUM(m_mailbox.name); |
| - gl->ProduceTextureCHROMIUM(GL_TEXTURE_2D, m_mailbox.name); |
| - const GLuint64 fenceSync = gl->InsertFenceSyncCHROMIUM(); |
| - gl->Flush(); |
| - gl->GenSyncTokenCHROMIUM(fenceSync, m_mailbox.syncToken); |
| - m_mailbox.validSyncToken = true; |
| - gl->BindTexture(GL_TEXTURE_2D, 0); |
| - grContext->resetContext(kTextureBinding_GrGLBackendState); |
| - m_image = nullptr; |
| - return true; |
| -} |
| + // |destProvider| may not be the same context as the one used for |m_image| so we use a mailbox to |
| + // generate a texture id for |destProvider| to access. |
| + ensureMailbox(); |
| -// This function is called only in the case that m_image is texture backed. |
| -GLuint AcceleratedStaticBitmapImage::switchStorageToSkImageForWebGL(WebGraphicsContext3DProvider* contextProvider) |
| -{ |
| - DCHECK(!m_image || m_image->isTextureBacked()); |
| - GLuint textureId = 0; |
| - if (m_image) { |
| - // SkImage is texture-backed on the shared context |
| - if (!hasMailbox()) { |
| - std::unique_ptr<WebGraphicsContext3DProvider> sharedProvider = wrapUnique(Platform::current()->createSharedOffscreenGraphicsContext3DProvider()); |
| - if (!switchStorageToMailbox(sharedProvider.get())) |
| - return 0; |
| - textureId = switchStorageToSkImage(contextProvider); |
| - return textureId; |
| - } |
| - } |
| - DCHECK(hasMailbox()); |
| - textureId = switchStorageToSkImage(contextProvider); |
| - return textureId; |
| + // Get a texture id that |destProvider| knows about and copy from it. |
| + gpu::gles2::GLES2Interface* destGL = destProvider->contextGL(); |
| + destGL->WaitSyncTokenCHROMIUM(m_syncToken.GetData()); |
| + GLuint sourceTextureId = destGL->CreateAndConsumeTextureCHROMIUM(GL_TEXTURE_2D, m_mailbox.name); |
| + destGL->CopyTextureCHROMIUM(sourceTextureId, destTextureId, internalFormat, destType, flipY, false, false); |
| + // This drops the |destGL| context's reference on our |m_mailbox|, but it's still held alive by our SkImage. |
| + destGL->DeleteTextures(1, &sourceTextureId); |
| } |
| -GLuint AcceleratedStaticBitmapImage::switchStorageToSkImage(WebGraphicsContext3DProvider* provider) |
| +PassRefPtr<SkImage> AcceleratedStaticBitmapImage::imageForCurrentFrame() |
| { |
| - if (!provider) |
| - return 0; |
| - GrContext* grContext = provider->grContext(); |
| - if (!grContext) |
| - return 0; |
| - gpu::gles2::GLES2Interface* gl = provider->contextGL(); |
| - if (!gl) |
| - return 0; |
| - gl->WaitSyncTokenCHROMIUM(m_mailbox.syncToken); |
| - GLuint textureId = gl->CreateAndConsumeTextureCHROMIUM(GL_TEXTURE_2D, m_mailbox.name); |
| + // TODO(xidachen): make this work on a worker thread. |
| + DCHECK(isMainThread()); |
| + |
| + // This must return an SkImage that can be used with the shared main thread context. If |m_image| satisfies that, we are done. |
| + if (m_imageIsForSharedMainThreadContext) |
| + return m_image; |
| + |
| + // If the SkImage came from any other context than the shared main thread one, we expect to be given a mailbox at construction. We |
| + // use the mailbox to generate a texture id for the shared main thread context to use. |
| + DCHECK(m_hasMailbox); |
| + |
| + auto sharedMainThreadContextProvider = wrapUnique(Platform::current()->createSharedOffscreenGraphicsContext3DProvider()); |
| + gpu::gles2::GLES2Interface* sharedGL = sharedMainThreadContextProvider->contextGL(); |
| + GrContext* sharedGrContext = sharedMainThreadContextProvider->grContext(); |
| + if (!sharedGrContext) |
| + return nullptr; // Can happen if the context is lost, the SkImage won't be any good now anyway. |
| + |
| + sharedGL->WaitSyncTokenCHROMIUM(m_syncToken.GetData()); |
| + GLuint sharedContextTextureId = sharedGL->CreateAndConsumeTextureCHROMIUM(GL_TEXTURE_2D, m_mailbox.name); |
| + |
| GrGLTextureInfo textureInfo; |
| textureInfo.fTarget = GL_TEXTURE_2D; |
| - textureInfo.fID = textureId; |
| + textureInfo.fID = sharedContextTextureId; |
| GrBackendTextureDesc backendTexture; |
| backendTexture.fOrigin = kBottomLeft_GrSurfaceOrigin; |
| - backendTexture.fWidth = m_mailbox.textureSize.width; |
| - backendTexture.fHeight = m_mailbox.textureSize.height; |
| + backendTexture.fWidth = size().width(); |
| + backendTexture.fHeight = size().height(); |
| backendTexture.fConfig = kSkia8888_GrPixelConfig; |
| backendTexture.fTextureHandle = skia::GrGLTextureInfoToGrBackendObject(textureInfo); |
| - sk_sp<SkImage> skImage = SkImage::MakeFromAdoptedTexture(grContext, backendTexture); |
| - m_image = fromSkSp(skImage); |
| - return textureId; |
| + return fromSkSp(SkImage::MakeFromAdoptedTexture(sharedGrContext, backendTexture)); |
|
Justin Novosad
2016/08/19 21:51:18
Would it be useful to set m_image to this newly cr
danakj
2016/08/19 21:57:57
Hm ya ok we could do that, and drop the ref on the
danakj
2016/08/19 22:06:20
Done.
danakj
2016/08/20 01:13:30
It looks like doing this causes crashes.
STDERR:
danakj
2016/08/20 01:26:18
Ah this was me holding PassRefPtr wrong, you can't
|
| } |
| -PassRefPtr<SkImage> AcceleratedStaticBitmapImage::imageForCurrentFrame() |
| +void AcceleratedStaticBitmapImage::ensureMailbox() |
| { |
| - if (m_image) |
| - return m_image; |
| - if (!hasMailbox()) |
| - return nullptr; |
| - // Has mailbox, consume mailbox, prepare a new mailbox if contextProvider is not null (3D). |
| - DCHECK(isMainThread()); |
| - // TODO(xidachen): make this work on a worker thread. |
| - std::unique_ptr<WebGraphicsContext3DProvider> sharedProvider = wrapUnique(Platform::current()->createSharedOffscreenGraphicsContext3DProvider()); |
| - if (!switchStorageToSkImage(sharedProvider.get())) |
| - return nullptr; |
| - return m_image; |
| + if (m_hasMailbox) |
| + return; |
| + |
| + // If we weren't given a mailbox at creation, then we were given a SkImage that is assumed to be from the shared main thread context. |
| + DCHECK(m_imageIsForSharedMainThreadContext); |
| + auto sharedMainThreadContextProvider = wrapUnique(Platform::current()->createSharedOffscreenGraphicsContext3DProvider()); |
| + |
| + gpu::gles2::GLES2Interface* sharedGL = sharedMainThreadContextProvider->contextGL(); |
| + GrContext* sharedGrContext = sharedMainThreadContextProvider->grContext(); |
| + if (!sharedGrContext) |
| + return; // Can happen if the context is lost, the SkImage won't be any good now anyway. |
| + |
| + GLuint imageTextureId = skia::GrBackendObjectToGrGLTextureInfo(m_image->getTextureHandle(true))->fID; |
| + sharedGL->BindTexture(GL_TEXTURE_2D, imageTextureId); |
| + |
| + sharedGL->GenMailboxCHROMIUM(m_mailbox.name); |
| + sharedGL->ProduceTextureCHROMIUM(GL_TEXTURE_2D, m_mailbox.name); |
| + const GLuint64 fenceSync = sharedGL->InsertFenceSyncCHROMIUM(); |
| + sharedGL->Flush(); |
| + sharedGL->GenSyncTokenCHROMIUM(fenceSync, m_syncToken.GetData()); |
| + |
| + sharedGL->BindTexture(GL_TEXTURE_2D, 0); |
| + // We changed bound textures in this function, so reset the GrContext. |
| + sharedGrContext->resetContext(kTextureBinding_GrGLBackendState); |
| + |
| + m_hasMailbox = true; |
| } |
| } // namespace blink |