Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1330)

Unified Diff: third_party/WebKit/Source/platform/graphics/StaticBitmapImage.cpp

Issue 2026803002: Avoid GPU readback in tex(Sub)Image2D(ImageBitmap) (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: layout test timeout in a strange way Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/platform/graphics/StaticBitmapImage.cpp
diff --git a/third_party/WebKit/Source/platform/graphics/StaticBitmapImage.cpp b/third_party/WebKit/Source/platform/graphics/StaticBitmapImage.cpp
index ac88b3d3d8c066136131b2f7aa9719f45976c96e..5cb8b3a9a780cffa5f266b7947935ac8e74841ce 100644
--- a/third_party/WebKit/Source/platform/graphics/StaticBitmapImage.cpp
+++ b/third_party/WebKit/Source/platform/graphics/StaticBitmapImage.cpp
@@ -14,6 +14,7 @@
#include "third_party/skia/include/core/SkImage.h"
#include "third_party/skia/include/core/SkPaint.h"
#include "third_party/skia/include/core/SkShader.h"
+#include "third_party/skia/include/gpu/GrContext.h"
namespace blink {
@@ -42,9 +43,16 @@ StaticBitmapImage::~StaticBitmapImage() { }
IntSize StaticBitmapImage::size() const
{
+ if (!m_image)
+ return IntSize(m_mailbox.textureSize.width, m_mailbox.textureSize.height);
return IntSize(m_image->width(), m_image->height());
}
+bool StaticBitmapImage::isTextureBacked()
+{
+ return m_image && m_image->isTextureBacked();
+}
+
bool StaticBitmapImage::currentFrameKnownToBeOpaque(MetadataMode)
{
return m_image->isOpaque();
@@ -66,28 +74,21 @@ void StaticBitmapImage::draw(SkCanvas* canvas, const SkPaint& paint, const Float
observer->didDraw(this);
}
-PassRefPtr<SkImage> StaticBitmapImage::imageForCurrentFrame()
+void StaticBitmapImage::switchStorageToSkImage(WebGraphicsContext3DProvider* provider)
{
- if (m_image)
- return m_image;
- DCHECK(isMainThread());
- // In the place when we consume an ImageBitmap that is gpu texture backed,
- // create a new SkImage from that texture.
- // TODO(xidachen): make this work on a worker thread.
- OwnPtr<WebGraphicsContext3DProvider> provider = adoptPtr(Platform::current()->createSharedOffscreenGraphicsContext3DProvider());
if (!provider)
- return nullptr;
+ return;
GrContext* grContext = provider->grContext();
if (!grContext)
- return nullptr;
+ return;
gpu::gles2::GLES2Interface* gl = provider->contextGL();
if (!gl)
- return nullptr;
+ return;
gl->WaitSyncTokenCHROMIUM(m_mailbox.syncToken);
- GLuint textureId = gl->CreateAndConsumeTextureCHROMIUM(GL_TEXTURE_2D, m_mailbox.name);
+ m_textureId = gl->CreateAndConsumeTextureCHROMIUM(GL_TEXTURE_2D, m_mailbox.name);
GrGLTextureInfo textureInfo;
textureInfo.fTarget = GL_TEXTURE_2D;
- textureInfo.fID = textureId;
+ textureInfo.fID = m_textureId;
GrBackendTextureDesc backendTexture;
backendTexture.fOrigin = kBottomLeft_GrSurfaceOrigin;
backendTexture.fWidth = m_mailbox.textureSize.width;
@@ -96,6 +97,93 @@ PassRefPtr<SkImage> StaticBitmapImage::imageForCurrentFrame()
backendTexture.fTextureHandle = skia::GrGLTextureInfoToGrBackendObject(textureInfo);
sk_sp<SkImage> skImage = SkImage::MakeFromAdoptedTexture(grContext, backendTexture);
m_image = fromSkSp(skImage);
+}
+
+void StaticBitmapImage::copyToTexture(WebGraphicsContext3DProvider* provider, GLuint destinationTexture, GLenum internalFormat, GLenum destType, bool flipY)
+{
+ gpu::gles2::GLES2Interface* gl = provider->contextGL();
+ if (!gl)
+ return;
+ gl->CopyTextureCHROMIUM(m_textureId, destinationTexture, internalFormat, destType, flipY, false, false);
+ const GLuint64 fenceSync = gl->InsertFenceSyncCHROMIUM();
+ GLbyte syncToken[24];
+ gl->GenSyncTokenCHROMIUM(fenceSync, syncToken);
+}
+
+bool StaticBitmapImage::switchStorageToMailbox(WebGraphicsContext3DProvider* provider)
+{
+ 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;
+}
+
+PassRefPtr<SkImage> StaticBitmapImage::imageForCurrentFrame(WebGraphicsContext3DProvider* contextProvider)
+{
+ if (m_image) {
+ // If the SkImage is not texture-backed
+ if (!m_image->isTextureBacked())
+ return m_image;
+ // SkImage is texture-backed, but no mailbox exists. virtual/gpu/ cases.
+ if (!hasMailbox()) {
+ // SkImage is texture-backed on the shared context
+ if (contextProvider) {
+ OwnPtr<WebGraphicsContext3DProvider> sharedProvider = adoptPtr(Platform::current()->createSharedOffscreenGraphicsContext3DProvider());
+ if (!switchStorageToMailbox(sharedProvider.get()))
+ return nullptr;
+ switchStorageToSkImage(contextProvider);
+ RefPtr<SkImage> retVal = m_image;
+ // Get a new mailbox because we cannot retain a texture in the WebGL context.
+ if (!switchStorageToMailbox(contextProvider))
+ return nullptr;
+ return retVal;
+ }
+ return m_image;
+ }
+ // Has mailbox, but contextProvider is null (2D).
+ if (!contextProvider)
+ return m_image;
+ // 3D context, consume mailbox, prepare a new mailbox.
+ switchStorageToSkImage(contextProvider);
+ RefPtr<SkImage> retVal = m_image;
+ if (!switchStorageToMailbox(contextProvider))
+ return nullptr;
+ return retVal;
+ }
+ // No mailbox, return null;
+ if (!hasMailbox())
+ return nullptr;
+ // Has mailbox, consume mailbox, prepare a new mailbox if contextProvider is not null (3D).
+ if (!contextProvider) {
+ DCHECK(isMainThread());
+ // TODO(xidachen): make this work on a worker thread.
+ OwnPtr<WebGraphicsContext3DProvider> sharedProvider = adoptPtr(Platform::current()->createSharedOffscreenGraphicsContext3DProvider());
+ switchStorageToSkImage(sharedProvider.get());
+ } else {
+ switchStorageToSkImage(contextProvider);
+ RefPtr<SkImage> retVal = m_image;
+ if (!switchStorageToMailbox(contextProvider))
+ return nullptr;
+ return retVal;
+ }
return m_image;
}

Powered by Google App Engine
This is Rietveld 408576698