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

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: 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(Pa ssRefPtr<SkImage> image) 26 PassRefPtr<AcceleratedStaticBitmapImage> AcceleratedStaticBitmapImage::create(Pa ssRefPtr<SkImage> image)
24 { 27 {
25 return adoptRef(new AcceleratedStaticBitmapImage(image)); 28 return adoptRef(new AcceleratedStaticBitmapImage(image));
26 } 29 }
27 30
28 PassRefPtr<AcceleratedStaticBitmapImage> AcceleratedStaticBitmapImage::create(Pa ssRefPtr<SkImage> image, sk_sp<GrContext> grContext, const gpu::Mailbox& mailbox , const gpu::SyncToken& syncToken) 31 PassRefPtr<AcceleratedStaticBitmapImage> AcceleratedStaticBitmapImage::create(Pa ssRefPtr<SkImage> image, GrContext* grContext, const gpu::Mailbox& mailbox, cons t gpu::SyncToken& syncToken)
29 { 32 {
30 return adoptRef(new AcceleratedStaticBitmapImage(image, std::move(grContext) , mailbox, syncToken)); 33 return adoptRef(new AcceleratedStaticBitmapImage(image, std::move(grContext) , mailbox, syncToken));
Stephen White 2016/09/01 15:43:53 Note: now calling std::move() on a bare ptr.
31 } 34 }
32 35
33 AcceleratedStaticBitmapImage::AcceleratedStaticBitmapImage(PassRefPtr<SkImage> i mage) 36 AcceleratedStaticBitmapImage::AcceleratedStaticBitmapImage(PassRefPtr<SkImage> i mage)
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(PassRefPtr<SkImage> i mage, sk_sp<GrContext> grContext, const gpu::Mailbox& mailbox, const gpu::SyncTo ken& syncToken) 43 AcceleratedStaticBitmapImage::AcceleratedStaticBitmapImage(PassRefPtr<SkImage> i mage, GrContext* grContext, const gpu::Mailbox& mailbox, const gpu::SyncToken& s yncToken)
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 DCHECK(grContext);
51 m_threadChecker.DetachFromThread();
52 GrContext* sharedGr = SharedGpuContext::gr();
53 if (!grContext || grContext == sharedGr) {
Stephen White 2016/09/01 15:43:53 As discussed, use this create() method only for ou
54 m_sharedContextId = SharedGpuContext::contextId();
55 }
48 } 56 }
49 57
50 AcceleratedStaticBitmapImage::~AcceleratedStaticBitmapImage() = default; 58 AcceleratedStaticBitmapImage::~AcceleratedStaticBitmapImage()
59 {
60 // Avoid leaking mailboxes in cases where the texture gets recycled by skia.
61 if (m_hasMailbox && SharedGpuContext::isValid())
62 SharedGpuContext::gl()->ProduceTextureDirectCHROMIUM(0, GL_TEXTURE_2D, m _mailbox.name);
63 releaseImageThreadSafe();
64 }
51 65
52 void AcceleratedStaticBitmapImage::copyToTexture(WebGraphicsContext3DProvider* d estProvider, GLuint destTextureId, GLenum internalFormat, GLenum destType, bool flipY) 66 void AcceleratedStaticBitmapImage::copyToTexture(WebGraphicsContext3DProvider* d estProvider, GLuint destTextureId, GLenum internalFormat, GLenum destType, bool flipY)
53 { 67 {
68 checkThread();
69 if (!isValid())
70 return;
54 // |destProvider| may not be the same context as the one used for |m_image| so we use a mailbox to 71 // |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. 72 // generate a texture id for |destProvider| to access.
56 ensureMailbox(); 73 ensureMailbox();
57 74
58 // Get a texture id that |destProvider| knows about and copy from it. 75 // Get a texture id that |destProvider| knows about and copy from it.
59 gpu::gles2::GLES2Interface* destGL = destProvider->contextGL(); 76 gpu::gles2::GLES2Interface* destGL = destProvider->contextGL();
60 destGL->WaitSyncTokenCHROMIUM(m_syncToken.GetData()); 77 destGL->WaitSyncTokenCHROMIUM(m_syncToken.GetData());
61 GLuint sourceTextureId = destGL->CreateAndConsumeTextureCHROMIUM(GL_TEXTURE_ 2D, m_mailbox.name); 78 GLuint sourceTextureId = destGL->CreateAndConsumeTextureCHROMIUM(GL_TEXTURE_ 2D, m_mailbox.name);
62 destGL->CopyTextureCHROMIUM(sourceTextureId, destTextureId, internalFormat, destType, flipY, false, false); 79 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. 80 // 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); 81 destGL->DeleteTextures(1, &sourceTextureId);
65 } 82 }
66 83
67 PassRefPtr<SkImage> AcceleratedStaticBitmapImage::imageForCurrentFrame() 84 PassRefPtr<SkImage> AcceleratedStaticBitmapImage::imageForCurrentFrame()
68 { 85 {
69 // This must return an SkImage that can be used with the shared main thread context. If |m_image| satisfies that, we are done. 86 checkThread();
70 if (m_imageIsForSharedMainThreadContext) 87 if (!isValid())
71 return m_image; 88 return nullptr;
89 createImageFromMailboxIfNeeded();
90 return m_image;
91 }
72 92
73 // TODO(xidachen): make this work on a worker thread. 93 void AcceleratedStaticBitmapImage::draw(SkCanvas* canvas, const SkPaint& paint, const FloatRect& dstRect, const FloatRect& srcRect, RespectImageOrientationEnum respectImageOrientation, ImageClampingMode imageClampingMode)
74 DCHECK(isMainThread()); 94 {
95 checkThread();
96 if (!isValid())
97 return;
98 createImageFromMailboxIfNeeded();
99 StaticBitmapImage::draw(canvas, paint, dstRect, srcRect, respectImageOrienta tion, imageClampingMode);
100 }
75 101
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 102 bool AcceleratedStaticBitmapImage::isValid()
77 // use the mailbox to generate a texture id for the shared main thread conte xt to use. 103 {
104 if (!m_image)
105 return false;
106 if (!SharedGpuContext::isValid())
107 return false; // Gpu context was lost
108 if (imageBelongsToSharedContext() && m_sharedContextId != SharedGpuContext:: contextId())
109 return false; // Gpu context was lost an restored since resource was cre ated
110 return true;
111 }
112
113 bool AcceleratedStaticBitmapImage::imageBelongsToSharedContext()
114 {
115 return m_sharedContextId != SharedGpuContext::kNoSharedContext;
116 }
117
118 void AcceleratedStaticBitmapImage::createImageFromMailboxIfNeeded()
119 {
120 if (imageBelongsToSharedContext())
121 return;
78 DCHECK(m_hasMailbox); 122 DCHECK(m_hasMailbox);
79 123 gpu::gles2::GLES2Interface* sharedGL = SharedGpuContext::gl();
80 auto sharedMainThreadContextProvider = wrapUnique(Platform::current()->creat eSharedOffscreenGraphicsContext3DProvider()); 124 GrContext* sharedGrContext = SharedGpuContext::gr();
81 gpu::gles2::GLES2Interface* sharedGL = sharedMainThreadContextProvider->cont extGL(); 125 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 126
86 sharedGL->WaitSyncTokenCHROMIUM(m_syncToken.GetData()); 127 sharedGL->WaitSyncTokenCHROMIUM(m_syncToken.GetData());
87 GLuint sharedContextTextureId = sharedGL->CreateAndConsumeTextureCHROMIUM(GL _TEXTURE_2D, m_mailbox.name); 128 GLuint sharedContextTextureId = sharedGL->CreateAndConsumeTextureCHROMIUM(GL _TEXTURE_2D, m_mailbox.name);
88
89 GrGLTextureInfo textureInfo; 129 GrGLTextureInfo textureInfo;
90 textureInfo.fTarget = GL_TEXTURE_2D; 130 textureInfo.fTarget = GL_TEXTURE_2D;
91 textureInfo.fID = sharedContextTextureId; 131 textureInfo.fID = sharedContextTextureId;
92 GrBackendTextureDesc backendTexture; 132 GrBackendTextureDesc backendTexture;
93 backendTexture.fOrigin = kBottomLeft_GrSurfaceOrigin; 133 backendTexture.fOrigin = kBottomLeft_GrSurfaceOrigin;
94 backendTexture.fWidth = size().width(); 134 backendTexture.fWidth = size().width();
95 backendTexture.fHeight = size().height(); 135 backendTexture.fHeight = size().height();
96 backendTexture.fConfig = kSkia8888_GrPixelConfig; 136 backendTexture.fConfig = kSkia8888_GrPixelConfig;
97 backendTexture.fTextureHandle = skia::GrGLTextureInfoToGrBackendObject(textu reInfo); 137 backendTexture.fTextureHandle = skia::GrGLTextureInfoToGrBackendObject(textu reInfo);
98 138
99 m_image = fromSkSp(SkImage::MakeFromAdoptedTexture(sharedGrContext, backendT exture)); 139 RefPtr<SkImage> newImage = fromSkSp(SkImage::MakeFromAdoptedTexture(sharedGr Context, backendTexture));
Stephen White 2016/09/01 15:43:53 Nit: could also use an sk_sp<> for newImage, then
100 m_imageIsForSharedMainThreadContext = true; 140 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. 141 m_image = newImage;
102 m_grContext = nullptr; 142
103 return m_image; 143 m_sharedContextId = SharedGpuContext::contextId();
104 } 144 }
105 145
106 void AcceleratedStaticBitmapImage::ensureMailbox() 146 void AcceleratedStaticBitmapImage::ensureMailbox()
107 { 147 {
108 if (m_hasMailbox) 148 if (m_hasMailbox)
109 return; 149 return;
110 150
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. 151 DCHECK(m_image);
112 DCHECK(m_imageIsForSharedMainThreadContext);
113 auto sharedMainThreadContextProvider = wrapUnique(Platform::current()->creat eSharedOffscreenGraphicsContext3DProvider());
114 152
115 gpu::gles2::GLES2Interface* sharedGL = sharedMainThreadContextProvider->cont extGL(); 153 gpu::gles2::GLES2Interface* sharedGL = SharedGpuContext::gl();
116 GrContext* sharedGrContext = sharedMainThreadContextProvider->grContext(); 154 GrContext* sharedGrContext = SharedGpuContext::gr();
117 if (!sharedGrContext) 155 if (!sharedGrContext)
118 return; // Can happen if the context is lost, the SkImage won't be any g ood now anyway. 156 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; 157 GLuint imageTextureId = skia::GrBackendObjectToGrGLTextureInfo(m_image->getT extureHandle(true))->fID;
121 sharedGL->BindTexture(GL_TEXTURE_2D, imageTextureId); 158 sharedGL->BindTexture(GL_TEXTURE_2D, imageTextureId);
122 159
123 sharedGL->GenMailboxCHROMIUM(m_mailbox.name); 160 sharedGL->GenMailboxCHROMIUM(m_mailbox.name);
124 sharedGL->ProduceTextureCHROMIUM(GL_TEXTURE_2D, m_mailbox.name); 161 sharedGL->ProduceTextureCHROMIUM(GL_TEXTURE_2D, m_mailbox.name);
125 const GLuint64 fenceSync = sharedGL->InsertFenceSyncCHROMIUM(); 162 const GLuint64 fenceSync = sharedGL->InsertFenceSyncCHROMIUM();
126 sharedGL->Flush(); 163 sharedGL->Flush();
127 sharedGL->GenSyncTokenCHROMIUM(fenceSync, m_syncToken.GetData()); 164 sharedGL->GenSyncTokenCHROMIUM(fenceSync, m_syncToken.GetData());
128 165
129 sharedGL->BindTexture(GL_TEXTURE_2D, 0); 166 sharedGL->BindTexture(GL_TEXTURE_2D, 0);
130 // We changed bound textures in this function, so reset the GrContext. 167 // We changed bound textures in this function, so reset the GrContext.
131 sharedGrContext->resetContext(kTextureBinding_GrGLBackendState); 168 sharedGrContext->resetContext(kTextureBinding_GrGLBackendState);
132 169
133 m_hasMailbox = true; 170 m_hasMailbox = true;
134 } 171 }
135 172
173 void AcceleratedStaticBitmapImage::transfer()
174 {
175 checkThread();
176 ensureMailbox();
177 m_sharedContextId = SharedGpuContext::kNoSharedContext;
178 // If image thread is set, it means that the image has been consumed on the current thread,
179 // which may happen when we have chained transfers. When that is the case, w e must not
180 // reset m_imageThread to ensure that releaseImage is called on the right th read.
181 if (!m_imageThread)
182 m_imageThread = Platform::current()->currentThread();
183 m_detachThreadAtNextCheck = true;
184 }
185
186 void AcceleratedStaticBitmapImage::checkThread()
187 {
188 if (m_detachThreadAtNextCheck) {
189 m_threadChecker.DetachFromThread();
190 m_detachThreadAtNextCheck = false;
191 }
192 CHECK(m_threadChecker.CalledOnValidThread());
193 }
194
195 void releaseImage(SkImage* image, std::unique_ptr<gpu::SyncToken>&& syncToken)
196 {
197 if (SharedGpuContext::isValid())
198 SharedGpuContext::gl()->WaitSyncTokenCHROMIUM(syncToken->GetData());
199 image->unref();
Stephen White 2016/09/01 15:43:53 It's unfortunate to have explit unref() here. Coul
200 }
201
202 void AcceleratedStaticBitmapImage::releaseImageThreadSafe()
203 {
204 // If m_image belongs to a GrContext that is on another thread, it
205 // must be released on that thread.
206 if (m_imageThread && m_image && m_imageThread != Platform::current()->curren tThread() && SharedGpuContext::isValid()) {
207 gpu::gles2::GLES2Interface* sharedGL = SharedGpuContext::gl();
208 std::unique_ptr<gpu::SyncToken> releaseSyncToken(new gpu::SyncToken);
209 const GLuint64 fenceSync = sharedGL->InsertFenceSyncCHROMIUM();
210 sharedGL->Flush();
211 sharedGL->GenSyncTokenCHROMIUM(fenceSync, releaseSyncToken->GetData());
212 m_imageThread->getWebTaskRunner()->postTask(BLINK_FROM_HERE, crossThread Bind(&releaseImage, crossThreadUnretained(m_image.release().leakRef()), passed(s td::move(releaseSyncToken))));
213 }
214 m_image = nullptr;
215 m_imageThread = nullptr;
216 }
217
136 } // namespace blink 218 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698