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

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

Issue 1755163003: CL for perf tryjob on mac Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 10 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/Canvas2DLayerBridge.cpp
diff --git a/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp b/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp
index dca9edb51fab5a44b422ded286e701d4d3603848..dcb5be2650bce56d837532cde216f55fb60087bc 100644
--- a/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp
+++ b/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp
@@ -139,6 +139,10 @@ Canvas2DLayerBridge::Canvas2DLayerBridge(PassOwnPtr<WebGraphicsContext3DProvider
Canvas2DLayerBridge::~Canvas2DLayerBridge()
{
ASSERT(m_destructionInProgress);
+ for (const auto& it : m_imageInfoCache) {
+ deleteCHROMIUMImage(it);
+ }
+
m_layer.clear();
ASSERT(m_mailboxes.size() == 0);
#ifndef NDEBUG
@@ -196,6 +200,170 @@ 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)
+{
+ ImageInfo imageInfo = createIOSurfaceBackedTexture();
+ if (imageInfo.empty())
+ return false;
+
+ GLuint imageTexture = skia::GrBackendObjectToGrGLTextureInfo(image->getTextureHandle(true))->fID;
+ context()->copyTextureCHROMIUM(imageTexture, imageInfo.m_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(imageInfo.m_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_imageInfo = imageInfo;
+ *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;
+}
+
+Canvas2DLayerBridge::ImageInfo Canvas2DLayerBridge::createIOSurfaceBackedTexture()
+{
+ if (!m_imageInfoCache.isEmpty()) {
+ Canvas2DLayerBridge::ImageInfo info = m_imageInfoCache.last();
+ m_imageInfoCache.removeLast();
+ return info;
+ }
+
+ WebGraphicsContext3D* webContext = context();
+ GLuint imageId = webContext->createGpuMemoryBufferImageCHROMIUM(m_size.width(), m_size.height(), GL_BGRA_EXT, GC3D_SCANOUT_CHROMIUM);
+ if (!imageId)
+ return Canvas2DLayerBridge::ImageInfo();
+
+ GLuint textureId= webContext->createTexture();
+ if (!textureId) {
+ webContext->destroyImageCHROMIUM(imageId);
+ return Canvas2DLayerBridge::ImageInfo();
+ }
+
+ 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);
+
+ return Canvas2DLayerBridge::ImageInfo(imageId, textureId);
+}
+
+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;
+}
+
+void Canvas2DLayerBridge::resetSkiaTextureBinding()
+{
+ GrContext* grContext = m_contextProvider->grContext();
+ if (grContext)
+ grContext->resetContext(kTextureBinding_GrGLBackendState);
+}
+
+void Canvas2DLayerBridge::deleteCHROMIUMImage(ImageInfo info)
+{
+ WebGraphicsContext3D* webContext = context();
+ if (webContext->isContextLost())
+ return;
+
+ GLenum target = GC3D_TEXTURE_RECTANGLE_ARB;
+ webContext->bindTexture(target, info.m_textureId);
+ webContext->releaseTexImage2DCHROMIUM(target, info.m_imageId);
+ webContext->destroyImageCHROMIUM(info.m_imageId);
+ webContext->deleteTexture(info.m_textureId);
+ webContext->bindTexture(target, 0);
+
+ resetSkiaTextureBinding();
+}
+
static void hibernateWrapper(WeakPtr<Canvas2DLayerBridge> bridge, double /*idleDeadline*/)
{
if (bridge) {
@@ -616,75 +784,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 +828,10 @@ void Canvas2DLayerBridge::mailboxReleased(const WebExternalTextureMailbox& mailb
}
}
}
+
+ if (!releasedMailboxInfo->m_imageInfo.empty() && !lostResource) {
+ m_imageInfoCache.append(releasedMailboxInfo->m_imageInfo);
+ }
}
RefPtr<Canvas2DLayerBridge> selfRef;
@@ -828,11 +939,23 @@ void Canvas2DLayerBridge::willOverwriteCanvas()
skipQueuedDrawCommands();
}
+Canvas2DLayerBridge::ImageInfo::ImageInfo(GLuint imageId, GLuint textureId) : m_imageId(imageId), m_textureId(textureId)
+{
+ ASSERT(imageId);
+ ASSERT(textureId);
+}
+
+bool Canvas2DLayerBridge::ImageInfo::empty()
+{
+ return m_imageId == 0;
+}
+
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_imageInfo = other.m_imageInfo;
}
void Canvas2DLayerBridge::Logger::reportHibernationEvent(HibernationEvent event)

Powered by Google App Engine
This is Rietveld 408576698