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

Unified Diff: third_party/WebKit/Source/platform/graphics/gpu/ImageLayerBridge.cpp

Issue 2738573002: Streamline the presentation of ImageBitmapRenderingContext (Closed)
Patch Set: Fixed expectations Created 3 years, 8 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
« no previous file with comments | « third_party/WebKit/Source/platform/graphics/gpu/ImageLayerBridge.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: third_party/WebKit/Source/platform/graphics/gpu/ImageLayerBridge.cpp
diff --git a/third_party/WebKit/Source/platform/graphics/gpu/ImageLayerBridge.cpp b/third_party/WebKit/Source/platform/graphics/gpu/ImageLayerBridge.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e31bc9bc3e5aacebf5337479754acf07e35b8c5f
--- /dev/null
+++ b/third_party/WebKit/Source/platform/graphics/gpu/ImageLayerBridge.cpp
@@ -0,0 +1,181 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "platform/graphics/gpu/ImageLayerBridge.h"
+
+#include "cc/resources/shared_bitmap.h"
+#include "cc/resources/texture_mailbox.h"
+#include "gpu/command_buffer/client/gles2_interface.h"
+#include "platform/graphics/ColorBehavior.h"
+#include "platform/graphics/GraphicsLayer.h"
+#include "platform/graphics/gpu/SharedGpuContext.h"
+#include "public/platform/Platform.h"
+#include "public/platform/WebCompositorSupport.h"
+#include "public/platform/WebExternalTextureLayer.h"
+#include "public/platform/WebGraphicsContext3DProvider.h"
+
+namespace blink {
+
+ImageLayerBridge::ImageLayerBridge(OpacityMode opacityMode)
+ : m_weakPtrFactory(this), m_opacityMode(opacityMode) {
+ m_layer =
+ Platform::current()->compositorSupport()->createExternalTextureLayer(
+ this);
+ GraphicsLayer::registerContentsLayer(m_layer->layer());
+ m_layer->setNearestNeighbor(m_filterQuality == kNone_SkFilterQuality);
+ if (m_opacityMode == Opaque) {
+ m_layer->setOpaque(true);
+ m_layer->setBlendBackgroundColor(false);
+ }
+}
+
+ImageLayerBridge::~ImageLayerBridge() {
+ if (!m_disposed)
+ dispose();
+}
+
+void ImageLayerBridge::setImage(PassRefPtr<StaticBitmapImage> image) {
+ m_image = std::move(image);
+ if (m_image) {
+ if (m_opacityMode == NonOpaque) {
+ m_layer->setOpaque(m_image->currentFrameKnownToBeOpaque());
+ m_layer->setBlendBackgroundColor(!m_image->currentFrameKnownToBeOpaque());
+ }
+ }
+ if (!m_hasPresentedSinceLastSetImage && m_image &&
+ m_image->isTextureBacked()) {
+ // If the layer bridge is not presenting, the GrContext may not be getting
+ // flushed regularly. The flush is normally triggered inside the
+ // m_image->ensureMailbox() call of
+ // ImageLayerBridge::PrepareTextureMailbox. To prevent a potential memory
+ // leak we must flush the GrContext here.
+ m_image->imageForCurrentFrame()->getTextureHandle(
+ true); // GrContext flush.
+ }
+ m_hasPresentedSinceLastSetImage = false;
+}
+
+void ImageLayerBridge::dispose() {
+ if (m_layer) {
+ GraphicsLayer::unregisterContentsLayer(m_layer->layer());
+ m_layer->clearTexture();
+ m_layer.reset();
+ }
+ m_image = nullptr;
+ m_disposed = true;
+}
+
+bool ImageLayerBridge::PrepareTextureMailbox(
+ cc::TextureMailbox* outMailbox,
+ std::unique_ptr<cc::SingleReleaseCallback>* outReleaseCallback) {
+ if (m_disposed)
+ return false;
+
+ if (!m_image)
+ return false;
+
+ if (m_hasPresentedSinceLastSetImage)
+ return false;
+
+ m_hasPresentedSinceLastSetImage = true;
+
+ if (m_image->isTextureBacked()) {
+ m_image->ensureMailbox();
+ *outMailbox = cc::TextureMailbox(m_image->mailbox(), m_image->syncToken(),
+ GL_TEXTURE_2D);
+ auto func = WTF::bind(&ImageLayerBridge::mailboxReleasedGpu,
+ m_weakPtrFactory.createWeakPtr(), m_image);
+ *outReleaseCallback = cc::SingleReleaseCallback::Create(
+ convertToBaseCallback(std::move(func)));
+ } else {
+ std::unique_ptr<cc::SharedBitmap> bitmap = createOrRecycleBitmap();
+ if (!bitmap)
+ return false;
+
+ sk_sp<SkImage> skImage = m_image->imageForCurrentFrame();
+ if (!skImage)
+ return false;
+
+ SkImageInfo dstInfo = SkImageInfo::MakeN32Premul(m_image->width(), 1);
+ size_t rowBytes = m_image->width() * 4;
+
+ // loop to flip Y
+ for (int row = 0; row < m_image->height(); row++) {
+ if (!skImage->readPixels(
+ dstInfo,
+ bitmap->pixels() + rowBytes * (m_image->height() - 1 - row),
+ rowBytes, 0, row))
+ return false;
+ }
+
+ *outMailbox = cc::TextureMailbox(
+ bitmap.get(), gfx::Size(m_image->width(), m_image->height()));
+ auto func = WTF::bind(&ImageLayerBridge::mailboxReleasedSoftware,
+ m_weakPtrFactory.createWeakPtr(),
+ base::Passed(&bitmap), m_image->size());
+ *outReleaseCallback = cc::SingleReleaseCallback::Create(
+ convertToBaseCallback(std::move(func)));
+ }
+
+ outMailbox->set_nearest_neighbor(m_filterQuality == kNone_SkFilterQuality);
+ // TODO(junov): Figure out how to get the color space info.
+ // outMailbox->set_color_space();
+
+ return true;
+}
+
+std::unique_ptr<cc::SharedBitmap> ImageLayerBridge::createOrRecycleBitmap() {
+ auto it = std::remove_if(m_recycledBitmaps.begin(), m_recycledBitmaps.end(),
+ [this](const RecycledBitmap& bitmap) {
+ return bitmap.size != m_image->size();
+ });
+ m_recycledBitmaps.shrink(it - m_recycledBitmaps.begin());
+
+ if (!m_recycledBitmaps.isEmpty()) {
+ RecycledBitmap recycled = std::move(m_recycledBitmaps.back());
+ m_recycledBitmaps.pop_back();
+ DCHECK(recycled.size == m_image->size());
+ return std::move(recycled.bitmap);
+ }
+ return Platform::current()->allocateSharedBitmap(m_image->size());
+}
+
+void ImageLayerBridge::mailboxReleasedGpu(RefPtr<StaticBitmapImage> image,
+ const gpu::SyncToken& token,
+ bool lostResource) {
+ if (image) {
+ DCHECK(image->isTextureBacked());
+ if (token.HasData()) {
+ if (image->hasMailbox()) {
+ image->updateSyncToken(token);
+ } else {
+ // Wait on sync token now because SkiaTextureHolder does not know
+ // about sync tokens.
+ gpu::gles2::GLES2Interface* sharedGL = SharedGpuContext::gl();
+ if (sharedGL)
+ sharedGL->WaitSyncTokenCHROMIUM(token.GetConstData());
+ }
+ }
+ }
+ // let 'image' go out of scope to finalize the release. The
+ // destructor will wait on sync token before deleting resource.
+}
+
+void ImageLayerBridge::mailboxReleasedSoftware(
+ std::unique_ptr<cc::SharedBitmap> bitmap,
+ const IntSize& size,
+ const gpu::SyncToken& syncToken,
+ bool lostResource) {
+ DCHECK(!syncToken.HasData()); // No sync tokens for software resources.
+ if (!m_disposed && !lostResource) {
+ RecycledBitmap recycled = {std::move(bitmap), size};
+ m_recycledBitmaps.push_back(std::move(recycled));
+ }
+}
+
+WebLayer* ImageLayerBridge::platformLayer() const {
+ return m_layer->layer();
+}
+
+} // namespace blink
« no previous file with comments | « third_party/WebKit/Source/platform/graphics/gpu/ImageLayerBridge.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698