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

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

Issue 2300633004: Allow canvases to be GPU-accelerated in Workers (Closed)
Patch Set: test expectation Created 4 years, 3 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
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "platform/graphics/AcceleratedStaticBitmapImage.h" 5 #include "platform/graphics/AcceleratedStaticBitmapImage.h"
6 6
7 #include "gpu/command_buffer/client/gles2_interface.h" 7 #include "gpu/command_buffer/client/gles2_interface.h"
8 #include "gpu/command_buffer/common/sync_token.h" 8 #include "gpu/command_buffer/common/sync_token.h"
9 #include "platform/CrossThreadFunctional.h"
9 #include "platform/graphics/StaticBitmapImage.h" 10 #include "platform/graphics/StaticBitmapImage.h"
11 #include "platform/graphics/gpu/SharedGpuContext.h"
10 #include "platform/graphics/skia/SkiaUtils.h" 12 #include "platform/graphics/skia/SkiaUtils.h"
11 #include "public/platform/Platform.h" 13 #include "public/platform/Platform.h"
12 #include "public/platform/WebGraphicsContext3DProvider.h" 14 #include "public/platform/WebGraphicsContext3DProvider.h"
15 #include "public/platform/WebTaskRunner.h"
13 #include "skia/ext/texture_handle.h" 16 #include "skia/ext/texture_handle.h"
14 #include "third_party/skia/include/core/SkImage.h" 17 #include "third_party/skia/include/core/SkImage.h"
15 #include "third_party/skia/include/gpu/GrContext.h" 18 #include "third_party/skia/include/gpu/GrContext.h"
16 #include "wtf/PtrUtil.h" 19 #include "wtf/PtrUtil.h"
17 20
18 #include <memory> 21 #include <memory>
19 #include <utility> 22 #include <utility>
20 23
21 namespace blink { 24 namespace blink {
22 25
23 PassRefPtr<AcceleratedStaticBitmapImage> AcceleratedStaticBitmapImage::create(sk _sp<SkImage> image) 26 PassRefPtr<AcceleratedStaticBitmapImage> AcceleratedStaticBitmapImage::createFro mSharedContextImage(sk_sp<SkImage> image)
24 { 27 {
25 return adoptRef(new AcceleratedStaticBitmapImage(std::move(image))); 28 return adoptRef(new AcceleratedStaticBitmapImage(std::move(image)));
26 } 29 }
27 30
28 PassRefPtr<AcceleratedStaticBitmapImage> AcceleratedStaticBitmapImage::create(sk _sp<SkImage> image, sk_sp<GrContext> grContext, const gpu::Mailbox& mailbox, con st gpu::SyncToken& syncToken) 31 PassRefPtr<AcceleratedStaticBitmapImage> AcceleratedStaticBitmapImage::createFro mWebGLContextImage(sk_sp<SkImage> image, const gpu::Mailbox& mailbox, const gpu: :SyncToken& syncToken)
29 { 32 {
30 return adoptRef(new AcceleratedStaticBitmapImage(std::move(image), std::move (grContext), mailbox, syncToken)); 33 return adoptRef(new AcceleratedStaticBitmapImage(std::move(image), mailbox, syncToken));
31 } 34 }
32 35
33 AcceleratedStaticBitmapImage::AcceleratedStaticBitmapImage(sk_sp<SkImage> image) 36 AcceleratedStaticBitmapImage::AcceleratedStaticBitmapImage(sk_sp<SkImage> image)
34 : StaticBitmapImage(std::move(image)) 37 : StaticBitmapImage(std::move(image))
35 , m_imageIsForSharedMainThreadContext(true) 38 , m_sharedContextId(SharedGpuContext::contextId())
36 { 39 {
40 m_threadChecker.DetachFromThread();
37 } 41 }
38 42
39 AcceleratedStaticBitmapImage::AcceleratedStaticBitmapImage(sk_sp<SkImage> image, sk_sp<GrContext> grContext, const gpu::Mailbox& mailbox, const gpu::SyncToken& syncToken) 43 AcceleratedStaticBitmapImage::AcceleratedStaticBitmapImage(sk_sp<SkImage> image, const gpu::Mailbox& mailbox, const gpu::SyncToken& syncToken)
40 : StaticBitmapImage(std::move(image)) 44 : StaticBitmapImage(std::move(image))
41 , m_imageIsForSharedMainThreadContext(false) // TODO(danakj): Could be true though, caller would know. 45 , m_sharedContextId(SharedGpuContext::kNoSharedContext)
42 , m_grContext(std::move(grContext))
43 , m_hasMailbox(true) 46 , m_hasMailbox(true)
44 , m_mailbox(mailbox) 47 , m_mailbox(mailbox)
45 , m_syncToken(syncToken) 48 , m_syncToken(syncToken)
46 { 49 {
47 DCHECK(m_grContext); 50 m_threadChecker.DetachFromThread();
51
52 // Note: In this case, m_image is not usable directly because it is not in t he shared context.
53 // It is just used to hold a reference to the texture object in the origin c ontext until the
54 // mailbox can be consumed.
48 } 55 }
49 56
50 AcceleratedStaticBitmapImage::~AcceleratedStaticBitmapImage() = default; 57 AcceleratedStaticBitmapImage::~AcceleratedStaticBitmapImage()
58 {
59 // Avoid leaking mailboxes in cases where the texture gets recycled by skia.
60 if (m_hasMailbox && SharedGpuContext::isValid())
61 SharedGpuContext::gl()->ProduceTextureDirectCHROMIUM(0, GL_TEXTURE_2D, m _mailbox.name);
62 releaseImageThreadSafe();
63 }
51 64
52 void AcceleratedStaticBitmapImage::copyToTexture(WebGraphicsContext3DProvider* d estProvider, GLuint destTextureId, GLenum internalFormat, GLenum destType, bool flipY) 65 void AcceleratedStaticBitmapImage::copyToTexture(WebGraphicsContext3DProvider* d estProvider, GLuint destTextureId, GLenum internalFormat, GLenum destType, bool flipY)
53 { 66 {
67 checkThread();
68 if (!isValid())
69 return;
54 // |destProvider| may not be the same context as the one used for |m_image| so we use a mailbox to 70 // |destProvider| may not be the same context as the one used for |m_image| so we use a mailbox to
55 // generate a texture id for |destProvider| to access. 71 // generate a texture id for |destProvider| to access.
56 ensureMailbox(); 72 ensureMailbox();
57 73
58 // Get a texture id that |destProvider| knows about and copy from it. 74 // Get a texture id that |destProvider| knows about and copy from it.
59 gpu::gles2::GLES2Interface* destGL = destProvider->contextGL(); 75 gpu::gles2::GLES2Interface* destGL = destProvider->contextGL();
60 destGL->WaitSyncTokenCHROMIUM(m_syncToken.GetData()); 76 destGL->WaitSyncTokenCHROMIUM(m_syncToken.GetData());
61 GLuint sourceTextureId = destGL->CreateAndConsumeTextureCHROMIUM(GL_TEXTURE_ 2D, m_mailbox.name); 77 GLuint sourceTextureId = destGL->CreateAndConsumeTextureCHROMIUM(GL_TEXTURE_ 2D, m_mailbox.name);
62 destGL->CopyTextureCHROMIUM(sourceTextureId, destTextureId, internalFormat, destType, flipY, false, false); 78 destGL->CopyTextureCHROMIUM(sourceTextureId, destTextureId, internalFormat, destType, flipY, false, false);
63 // This drops the |destGL| context's reference on our |m_mailbox|, but it's still held alive by our SkImage. 79 // This drops the |destGL| context's reference on our |m_mailbox|, but it's still held alive by our SkImage.
64 destGL->DeleteTextures(1, &sourceTextureId); 80 destGL->DeleteTextures(1, &sourceTextureId);
65 } 81 }
66 82
67 sk_sp<SkImage> AcceleratedStaticBitmapImage::imageForCurrentFrame() 83 sk_sp<SkImage> AcceleratedStaticBitmapImage::imageForCurrentFrame()
68 { 84 {
69 // This must return an SkImage that can be used with the shared main thread context. If |m_image| satisfies that, we are done. 85 checkThread();
70 if (m_imageIsForSharedMainThreadContext) 86 if (!isValid())
71 return m_image; 87 return nullptr;
88 createImageFromMailboxIfNeeded();
89 return m_image;
90 }
72 91
73 // TODO(xidachen): make this work on a worker thread. 92 void AcceleratedStaticBitmapImage::draw(SkCanvas* canvas, const SkPaint& paint, const FloatRect& dstRect, const FloatRect& srcRect, RespectImageOrientationEnum respectImageOrientation, ImageClampingMode imageClampingMode)
74 DCHECK(isMainThread()); 93 {
94 checkThread();
95 if (!isValid())
96 return;
97 createImageFromMailboxIfNeeded();
98 StaticBitmapImage::draw(canvas, paint, dstRect, srcRect, respectImageOrienta tion, imageClampingMode);
99 }
75 100
76 // If the SkImage came from any other context than the shared main thread on e, we expect to be given a mailbox at construction. We 101 bool AcceleratedStaticBitmapImage::isValid()
77 // use the mailbox to generate a texture id for the shared main thread conte xt to use. 102 {
103 if (!m_image)
104 return false;
105 if (!SharedGpuContext::isValid())
106 return false; // Gpu context was lost
107 if (imageBelongsToSharedContext() && m_sharedContextId != SharedGpuContext:: contextId())
108 return false; // Gpu context was lost an restored since resource was cre ated
109 return true;
110 }
111
112 bool AcceleratedStaticBitmapImage::imageBelongsToSharedContext()
113 {
114 return m_sharedContextId != SharedGpuContext::kNoSharedContext;
115 }
116
117 void AcceleratedStaticBitmapImage::createImageFromMailboxIfNeeded()
118 {
119 if (imageBelongsToSharedContext())
120 return;
78 DCHECK(m_hasMailbox); 121 DCHECK(m_hasMailbox);
79 122 gpu::gles2::GLES2Interface* sharedGL = SharedGpuContext::gl();
80 auto sharedMainThreadContextProvider = wrapUnique(Platform::current()->creat eSharedOffscreenGraphicsContext3DProvider()); 123 GrContext* sharedGrContext = SharedGpuContext::gr();
81 gpu::gles2::GLES2Interface* sharedGL = sharedMainThreadContextProvider->cont extGL(); 124 DCHECK(sharedGL && sharedGrContext); // context isValid already checked in c allers
82 GrContext* sharedGrContext = sharedMainThreadContextProvider->grContext();
83 if (!sharedGrContext)
84 return nullptr; // Can happen if the context is lost, the SkImage won't be any good now anyway.
85 125
86 sharedGL->WaitSyncTokenCHROMIUM(m_syncToken.GetData()); 126 sharedGL->WaitSyncTokenCHROMIUM(m_syncToken.GetData());
87 GLuint sharedContextTextureId = sharedGL->CreateAndConsumeTextureCHROMIUM(GL _TEXTURE_2D, m_mailbox.name); 127 GLuint sharedContextTextureId = sharedGL->CreateAndConsumeTextureCHROMIUM(GL _TEXTURE_2D, m_mailbox.name);
88
89 GrGLTextureInfo textureInfo; 128 GrGLTextureInfo textureInfo;
90 textureInfo.fTarget = GL_TEXTURE_2D; 129 textureInfo.fTarget = GL_TEXTURE_2D;
91 textureInfo.fID = sharedContextTextureId; 130 textureInfo.fID = sharedContextTextureId;
92 GrBackendTextureDesc backendTexture; 131 GrBackendTextureDesc backendTexture;
93 backendTexture.fOrigin = kBottomLeft_GrSurfaceOrigin; 132 backendTexture.fOrigin = kBottomLeft_GrSurfaceOrigin;
94 backendTexture.fWidth = size().width(); 133 backendTexture.fWidth = size().width();
95 backendTexture.fHeight = size().height(); 134 backendTexture.fHeight = size().height();
96 backendTexture.fConfig = kSkia8888_GrPixelConfig; 135 backendTexture.fConfig = kSkia8888_GrPixelConfig;
97 backendTexture.fTextureHandle = skia::GrGLTextureInfoToGrBackendObject(textu reInfo); 136 backendTexture.fTextureHandle = skia::GrGLTextureInfoToGrBackendObject(textu reInfo);
98 137
99 m_image = SkImage::MakeFromAdoptedTexture(sharedGrContext, backendTexture); 138 sk_sp<SkImage> newImage = SkImage::MakeFromAdoptedTexture(sharedGrContext, b ackendTexture);
100 m_imageIsForSharedMainThreadContext = true; 139 releaseImageThreadSafe();
101 // Can drop the ref on the GrContext since m_image is now backed by a textur e from the shared main thread context. 140 m_image = newImage;
102 m_grContext = nullptr; 141
103 return m_image; 142 m_sharedContextId = SharedGpuContext::contextId();
104 } 143 }
105 144
106 void AcceleratedStaticBitmapImage::ensureMailbox() 145 void AcceleratedStaticBitmapImage::ensureMailbox()
107 { 146 {
108 if (m_hasMailbox) 147 if (m_hasMailbox)
109 return; 148 return;
110 149
111 // If we weren't given a mailbox at creation, then we were given a SkImage t hat is assumed to be from the shared main thread context. 150 DCHECK(m_image);
112 DCHECK(m_imageIsForSharedMainThreadContext);
113 auto sharedMainThreadContextProvider = wrapUnique(Platform::current()->creat eSharedOffscreenGraphicsContext3DProvider());
114 151
115 gpu::gles2::GLES2Interface* sharedGL = sharedMainThreadContextProvider->cont extGL(); 152 gpu::gles2::GLES2Interface* sharedGL = SharedGpuContext::gl();
116 GrContext* sharedGrContext = sharedMainThreadContextProvider->grContext(); 153 GrContext* sharedGrContext = SharedGpuContext::gr();
117 if (!sharedGrContext) 154 if (!sharedGrContext)
118 return; // Can happen if the context is lost, the SkImage won't be any g ood now anyway. 155 return; // Can happen if the context is lost, the SkImage won't be any g ood now anyway.
119
120 GLuint imageTextureId = skia::GrBackendObjectToGrGLTextureInfo(m_image->getT extureHandle(true))->fID; 156 GLuint imageTextureId = skia::GrBackendObjectToGrGLTextureInfo(m_image->getT extureHandle(true))->fID;
121 sharedGL->BindTexture(GL_TEXTURE_2D, imageTextureId); 157 sharedGL->BindTexture(GL_TEXTURE_2D, imageTextureId);
122 158
123 sharedGL->GenMailboxCHROMIUM(m_mailbox.name); 159 sharedGL->GenMailboxCHROMIUM(m_mailbox.name);
124 sharedGL->ProduceTextureCHROMIUM(GL_TEXTURE_2D, m_mailbox.name); 160 sharedGL->ProduceTextureCHROMIUM(GL_TEXTURE_2D, m_mailbox.name);
125 const GLuint64 fenceSync = sharedGL->InsertFenceSyncCHROMIUM(); 161 const GLuint64 fenceSync = sharedGL->InsertFenceSyncCHROMIUM();
126 sharedGL->Flush(); 162 sharedGL->Flush();
127 sharedGL->GenSyncTokenCHROMIUM(fenceSync, m_syncToken.GetData()); 163 sharedGL->GenSyncTokenCHROMIUM(fenceSync, m_syncToken.GetData());
128 164
129 sharedGL->BindTexture(GL_TEXTURE_2D, 0); 165 sharedGL->BindTexture(GL_TEXTURE_2D, 0);
130 // We changed bound textures in this function, so reset the GrContext. 166 // We changed bound textures in this function, so reset the GrContext.
131 sharedGrContext->resetContext(kTextureBinding_GrGLBackendState); 167 sharedGrContext->resetContext(kTextureBinding_GrGLBackendState);
132 168
133 m_hasMailbox = true; 169 m_hasMailbox = true;
134 } 170 }
135 171
172 void AcceleratedStaticBitmapImage::transfer()
173 {
174 checkThread();
175 ensureMailbox();
176 m_sharedContextId = SharedGpuContext::kNoSharedContext;
177 // If image thread is set, it means that the image has been consumed on the current thread,
178 // which may happen when we have chained transfers. When that is the case, w e must not
179 // reset m_imageThread to ensure that releaseImage is called on the right th read.
180 if (!m_imageThread)
181 m_imageThread = Platform::current()->currentThread();
182 m_detachThreadAtNextCheck = true;
183 }
184
185 void AcceleratedStaticBitmapImage::checkThread()
186 {
187 if (m_detachThreadAtNextCheck) {
188 m_threadChecker.DetachFromThread();
189 m_detachThreadAtNextCheck = false;
190 }
191 CHECK(m_threadChecker.CalledOnValidThread());
192 }
193
194 void releaseImage(sk_sp<SkImage>&& image, std::unique_ptr<gpu::SyncToken>&& sync Token)
195 {
196 if (SharedGpuContext::isValid() && syncToken->HasData())
197 SharedGpuContext::gl()->WaitSyncTokenCHROMIUM(syncToken->GetData());
198 image.reset();
199 }
200
201 void AcceleratedStaticBitmapImage::releaseImageThreadSafe()
202 {
203 // If m_image belongs to a GrContext that is on another thread, it
204 // must be released on that thread.
205 if (m_imageThread && m_image && m_imageThread != Platform::current()->curren tThread() && SharedGpuContext::isValid()) {
206 gpu::gles2::GLES2Interface* sharedGL = SharedGpuContext::gl();
207 std::unique_ptr<gpu::SyncToken> releaseSyncToken(new gpu::SyncToken);
208 const GLuint64 fenceSync = sharedGL->InsertFenceSyncCHROMIUM();
209 sharedGL->Flush();
210 sharedGL->GenSyncTokenCHROMIUM(fenceSync, releaseSyncToken->GetData());
211 m_imageThread->getWebTaskRunner()->postTask(BLINK_FROM_HERE, crossThread Bind(&releaseImage, passed(std::move(m_image)), passed(std::move(releaseSyncToke n))));
212 }
213 m_image = nullptr;
214 m_imageThread = nullptr;
215 }
216
136 } // namespace blink 217 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698