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

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

Issue 2738573002: Streamline the presentation of ImageBitmapRenderingContext (Closed)
Patch Set: Fix crash in gpu test Created 3 years, 9 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 unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "platform/graphics/gpu/ImageLayerBridge.h"
6
7 #include "cc/resources/shared_bitmap.h"
8 #include "cc/resources/texture_mailbox.h"
9 #include "gpu/command_buffer/client/gles2_interface.h"
10 #include "platform/graphics/ColorBehavior.h"
11 #include "platform/graphics/GraphicsLayer.h"
12 #include "platform/graphics/gpu/SharedGpuContext.h"
13 #include "public/platform/Platform.h"
14 #include "public/platform/WebCompositorSupport.h"
15 #include "public/platform/WebExternalTextureLayer.h"
16
17 namespace blink {
18
19 ImageLayerBridge::ImageLayerBridge(OpacityMode opacityMode)
20 : m_weakPtrFactory(this), m_opacityMode(opacityMode) {}
21
22 ImageLayerBridge::~ImageLayerBridge() {
23 if (!m_disposed)
24 dispose();
25 }
26
27 void ImageLayerBridge::setImage(PassRefPtr<StaticBitmapImage> image) {
28 if (!m_layer) {
29 m_layer =
30 Platform::current()->compositorSupport()->createExternalTextureLayer(
31 this);
32 GraphicsLayer::registerContentsLayer(m_layer->layer());
33 m_layer->setNearestNeighbor(m_filterQuality == kNone_SkFilterQuality);
34 if (m_opacityMode == Opaque) {
35 m_layer->setOpaque(true);
36 m_layer->setBlendBackgroundColor(false);
37 }
38 }
39 m_image = std::move(image);
40 if (m_image) {
41 if (m_opacityMode == NonOpaque) {
42 m_layer->setOpaque(m_image->currentFrameKnownToBeOpaque());
43 m_layer->setBlendBackgroundColor(!m_image->currentFrameKnownToBeOpaque());
44 }
45 }
46 m_layer->layer()->invalidate();
47 if (!m_hasPresentedSinceLastSetImage && m_image &&
48 m_image->isTextureBacked()) {
49 // If the layer bridge is not presenting, the GrContext may not be getting
50 // flushed regularly. The flush is normally triggered inside the
51 // m_image->ensureMailbox() call of
52 // ImageLayerBridge::PrepareTextureMailbox. To prevent a potential memory
53 // leak we must flush the GrContext here.
54 m_image->imageForCurrentFrame()->getTextureHandle(
55 true); // GrContext flush.
56 }
57 m_hasPresentedSinceLastSetImage = false;
58 }
59
60 void ImageLayerBridge::dispose() {
61 if (m_layer) {
62 GraphicsLayer::unregisterContentsLayer(m_layer->layer());
63 m_layer->clearTexture();
64 m_layer.reset();
65 }
66 m_image = nullptr;
67 m_disposed = true;
68 }
69
70 bool ImageLayerBridge::PrepareTextureMailbox(
71 cc::TextureMailbox* outMailbox,
72 std::unique_ptr<cc::SingleReleaseCallback>* outReleaseCallback) {
73 if (m_disposed)
74 return false;
75
76 if (!m_image)
77 return false;
78
79 if (m_hasPresentedSinceLastSetImage)
80 return false;
81
82 m_hasPresentedSinceLastSetImage = true;
83
84 if (m_image->isAccelerated()) {
85 m_image->ensureMailbox();
86 *outMailbox = cc::TextureMailbox(m_image->mailbox(), m_image->syncToken(),
87 GL_TEXTURE_2D);
88 auto func = WTF::bind(&ImageLayerBridge::mailboxReleasedGpu,
89 m_weakPtrFactory.createWeakPtr(), m_image);
90 *outReleaseCallback = cc::SingleReleaseCallback::Create(
91 convertToBaseCallback(std::move(func)));
92 } else {
93 std::unique_ptr<cc::SharedBitmap> bitmap = createOrRecycleBitmap();
94 if (!bitmap)
95 return false;
96
97 sk_sp<SkImage> skImage = m_image->imageForCurrentFrame();
98 if (!skImage)
99 return false;
100
101 SkImageInfo dstInfo = SkImageInfo::MakeN32Premul(m_image->width(), 1);
102 size_t rowBytes = m_image->width() * 4;
103
104 // loop to flip Y
105 for (int row = 0; row < m_image->height(); row++) {
106 if (!skImage->readPixels(
107 dstInfo,
108 bitmap->pixels() + rowBytes * (m_image->height() - 1 - row),
109 rowBytes, 0, row))
110 return false;
111 }
112
113 *outMailbox = cc::TextureMailbox(
114 bitmap.get(), gfx::Size(m_image->width(), m_image->height()));
115 auto func = WTF::bind(&ImageLayerBridge::mailboxReleasedSoftware,
116 m_weakPtrFactory.createWeakPtr(),
117 base::Passed(&bitmap), m_image->size());
118 *outReleaseCallback = cc::SingleReleaseCallback::Create(
119 convertToBaseCallback(std::move(func)));
120 }
121
122 outMailbox->set_nearest_neighbor(m_filterQuality == kNone_SkFilterQuality);
123 // TODO(junov): Figure out how to get the color space info.
124 // outMailbox->set_color_space();
125
126 return true;
127 }
128
129 std::unique_ptr<cc::SharedBitmap> ImageLayerBridge::createOrRecycleBitmap() {
130 auto it = std::remove_if(m_recycledBitmaps.begin(), m_recycledBitmaps.end(),
131 [this](const RecycledBitmap& bitmap) {
132 return bitmap.size != m_image->size();
133 });
134 m_recycledBitmaps.shrink(it - m_recycledBitmaps.begin());
135
136 if (!m_recycledBitmaps.isEmpty()) {
137 RecycledBitmap recycled = std::move(m_recycledBitmaps.back());
138 m_recycledBitmaps.pop_back();
139 DCHECK(recycled.size == m_image->size());
140 return std::move(recycled.bitmap);
141 }
142 return Platform::current()->allocateSharedBitmap(m_image->size());
143 }
144
145 void ImageLayerBridge::mailboxReleasedGpu(RefPtr<StaticBitmapImage> image,
146 const gpu::SyncToken& token,
147 bool lostResource) {
148 if (image) {
149 DCHECK(image->isAccelerated());
150 if (token.HasData()) {
151 if (image->hasMailbox()) {
152 image->updateSyncToken(token);
153 } else {
154 // Wait on sync token now because SkiaTextureHolder does not know
155 // about sync tokens.
156 gpu::gles2::GLES2Interface* sharedGL = SharedGpuContext::gl();
157 if (sharedGL)
158 sharedGL->WaitSyncTokenCHROMIUM(token.GetConstData());
159 }
160 }
161 }
162 // let 'image' go out of scope to finalize the release. The
163 // destructor will wait on sync token before deleting resource.
164 }
165
166 void ImageLayerBridge::mailboxReleasedSoftware(
167 std::unique_ptr<cc::SharedBitmap> bitmap,
168 const IntSize& size,
169 const gpu::SyncToken& syncToken,
170 bool lostResource) {
171 DCHECK(!syncToken.HasData()); // No sync tokens for software resources.
172 if (!m_disposed && !lostResource) {
173 RecycledBitmap recycled = {std::move(bitmap), size};
174 m_recycledBitmaps.push_back(std::move(recycled));
175 }
176 }
177
178 WebLayer* ImageLayerBridge::platformLayer() const {
179 return m_layer->layer();
180 }
181
182 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698