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

Side by Side Diff: content/renderer/media/renderer_gpu_video_accelerator_factories.cc

Issue 27420004: Remove threading from RendererGpuVideoAcceleratorFactories (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@dthread
Patch Set: 51676bf4 Initial. Created 7 years, 2 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 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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 "content/renderer/media/renderer_gpu_video_accelerator_factories.h" 5 #include "content/renderer/media/renderer_gpu_video_accelerator_factories.h"
6 6
7 #include <GLES2/gl2.h> 7 #include <GLES2/gl2.h>
8 #include <GLES2/gl2ext.h> 8 #include <GLES2/gl2ext.h>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
11 #include "content/child/child_thread.h" 11 #include "content/child/child_thread.h"
12 #include "content/common/gpu/client/context_provider_command_buffer.h" 12 #include "content/common/gpu/client/context_provider_command_buffer.h"
13 #include "content/common/gpu/client/gpu_channel_host.h" 13 #include "content/common/gpu/client/gpu_channel_host.h"
14 #include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h" 14 #include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h"
15 #include "gpu/command_buffer/client/gles2_implementation.h" 15 #include "gpu/command_buffer/client/gles2_implementation.h"
16 #include "third_party/skia/include/core/SkPixelRef.h" 16 #include "third_party/skia/include/core/SkPixelRef.h"
17 17
18 namespace content { 18 namespace content {
19 19
20 RendererGpuVideoAcceleratorFactories::~RendererGpuVideoAcceleratorFactories() {} 20 RendererGpuVideoAcceleratorFactories::~RendererGpuVideoAcceleratorFactories() {}
21 RendererGpuVideoAcceleratorFactories::RendererGpuVideoAcceleratorFactories( 21 RendererGpuVideoAcceleratorFactories::RendererGpuVideoAcceleratorFactories(
22 GpuChannelHost* gpu_channel_host, 22 GpuChannelHost* gpu_channel_host,
23 const scoped_refptr<base::MessageLoopProxy>& message_loop, 23 const scoped_refptr<base::MessageLoopProxy>& message_loop,
24 const scoped_refptr<ContextProviderCommandBuffer>& context_provider) 24 const scoped_refptr<ContextProviderCommandBuffer>& context_provider)
25 : message_loop_(message_loop), 25 : message_loop_(message_loop),
26 gpu_channel_host_(gpu_channel_host), 26 gpu_channel_host_(gpu_channel_host),
27 context_provider_(context_provider), 27 context_provider_(context_provider),
28 thread_safe_sender_(ChildThread::current()->thread_safe_sender()), 28 thread_safe_sender_(ChildThread::current()->thread_safe_sender()) {
29 aborted_waiter_(true, false),
30 message_loop_async_waiter_(false, false) {
31 // |context_provider_| is only required to support HW-accelerated decode. 29 // |context_provider_| is only required to support HW-accelerated decode.
32 if (!context_provider_) 30 if (!context_provider_)
33 return; 31 return;
34 32
35 if (message_loop_->BelongsToCurrentThread()) { 33 if (message_loop_->BelongsToCurrentThread()) {
36 AsyncBindContext(); 34 AsyncBindContext();
37 message_loop_async_waiter_.Reset();
38 return; 35 return;
39 } 36 }
40 // Wait for the context to be acquired. 37 // Wait for the context to be acquired.
41 message_loop_->PostTask( 38 message_loop_->PostTask(
42 FROM_HERE, 39 FROM_HERE,
43 base::Bind(&RendererGpuVideoAcceleratorFactories::AsyncBindContext, 40 base::Bind(&RendererGpuVideoAcceleratorFactories::AsyncBindContext,
44 // Unretained to avoid ref/deref'ing |*this|, which is not yet 41 // Unretained to avoid ref/deref'ing |*this|, which is not yet
45 // stored in a scoped_refptr. Safe because the Wait() below 42 // stored in a scoped_refptr. Safe because the Wait() below
46 // keeps us alive until this task completes. 43 // keeps us alive until this task completes.
Ami GONE FROM CHROMIUM 2013/10/17 22:22:17 That the comment is a lie is a problem. The Unreta
sheu 2013/10/21 05:17:35 Done.
47 base::Unretained(this))); 44 base::Unretained(this)));
48 message_loop_async_waiter_.Wait();
49 } 45 }
50 46
51 RendererGpuVideoAcceleratorFactories::RendererGpuVideoAcceleratorFactories()
52 : aborted_waiter_(true, false),
53 message_loop_async_waiter_(false, false) {}
54
55 WebGraphicsContext3DCommandBufferImpl* 47 WebGraphicsContext3DCommandBufferImpl*
56 RendererGpuVideoAcceleratorFactories::GetContext3d() { 48 RendererGpuVideoAcceleratorFactories::GetContext3d() {
57 DCHECK(message_loop_->BelongsToCurrentThread()); 49 DCHECK(message_loop_->BelongsToCurrentThread());
58 if (!context_provider_) 50 if (!context_provider_)
59 return NULL; 51 return NULL;
60 WebGraphicsContext3DCommandBufferImpl* context = 52 WebGraphicsContext3DCommandBufferImpl* context =
61 context_provider_->Context3d(); 53 context_provider_->Context3d();
62 if (context->isContextLost()) { 54 if (context->isContextLost()) {
63 context_provider_->VerifyContexts(); 55 context_provider_->VerifyContexts();
64 context_provider_ = NULL; 56 context_provider_ = NULL;
65 return NULL; 57 return NULL;
66 } 58 }
67 return context; 59 return context;
68 } 60 }
69 61
70 void RendererGpuVideoAcceleratorFactories::AsyncBindContext() { 62 void RendererGpuVideoAcceleratorFactories::AsyncBindContext() {
71 DCHECK(message_loop_->BelongsToCurrentThread()); 63 DCHECK(message_loop_->BelongsToCurrentThread());
72 if (!context_provider_->BindToCurrentThread()) 64 if (!context_provider_->BindToCurrentThread())
73 context_provider_ = NULL; 65 context_provider_ = NULL;
74 message_loop_async_waiter_.Signal();
75 } 66 }
76 67
77 scoped_ptr<media::VideoDecodeAccelerator> 68 scoped_ptr<media::VideoDecodeAccelerator>
78 RendererGpuVideoAcceleratorFactories::CreateVideoDecodeAccelerator( 69 RendererGpuVideoAcceleratorFactories::CreateVideoDecodeAccelerator(
79 media::VideoCodecProfile profile, 70 media::VideoCodecProfile profile,
80 media::VideoDecodeAccelerator::Client* client) { 71 media::VideoDecodeAccelerator::Client* client) {
81 if (message_loop_->BelongsToCurrentThread()) { 72 DCHECK(message_loop_->BelongsToCurrentThread());
82 AsyncCreateVideoDecodeAccelerator(profile, client); 73
83 message_loop_async_waiter_.Reset(); 74 WebGraphicsContext3DCommandBufferImpl* context = GetContext3d();
84 return vda_.Pass(); 75 if (context && context->GetCommandBufferProxy()) {
76 return gpu_channel_host_->CreateVideoDecoder(
77 context->GetCommandBufferProxy()->GetRouteID(), profile, client);
85 } 78 }
86 // The VDA is returned in the vda_ member variable by the
87 // AsyncCreateVideoDecodeAccelerator() function.
88 message_loop_->PostTask(FROM_HERE,
89 base::Bind(&RendererGpuVideoAcceleratorFactories::
90 AsyncCreateVideoDecodeAccelerator,
91 this,
92 profile,
93 client));
94 79
95 base::WaitableEvent* objects[] = {&aborted_waiter_, 80 return scoped_ptr<media::VideoDecodeAccelerator>();
96 &message_loop_async_waiter_};
97 if (base::WaitableEvent::WaitMany(objects, arraysize(objects)) == 0) {
98 // If we are aborting and the VDA is created by the
99 // AsyncCreateVideoDecodeAccelerator() function later we need to ensure
100 // that it is destroyed on the same thread.
101 message_loop_->PostTask(FROM_HERE,
102 base::Bind(&RendererGpuVideoAcceleratorFactories::
103 AsyncDestroyVideoDecodeAccelerator,
104 this));
105 return scoped_ptr<media::VideoDecodeAccelerator>();
106 }
107 return vda_.Pass();
108 } 81 }
109 82
110 scoped_ptr<media::VideoEncodeAccelerator> 83 scoped_ptr<media::VideoEncodeAccelerator>
111 RendererGpuVideoAcceleratorFactories::CreateVideoEncodeAccelerator( 84 RendererGpuVideoAcceleratorFactories::CreateVideoEncodeAccelerator(
112 media::VideoEncodeAccelerator::Client* client) { 85 media::VideoEncodeAccelerator::Client* client) {
113 DCHECK(message_loop_->BelongsToCurrentThread()); 86 DCHECK(message_loop_->BelongsToCurrentThread());
114 87
115 return gpu_channel_host_->CreateVideoEncoder(client); 88 return gpu_channel_host_->CreateVideoEncoder(client);
116 } 89 }
117 90
118 void RendererGpuVideoAcceleratorFactories::AsyncCreateVideoDecodeAccelerator(
119 media::VideoCodecProfile profile,
120 media::VideoDecodeAccelerator::Client* client) {
121 DCHECK(message_loop_->BelongsToCurrentThread());
122
123 WebGraphicsContext3DCommandBufferImpl* context = GetContext3d();
124 if (context && context->GetCommandBufferProxy()) {
125 vda_ = gpu_channel_host_->CreateVideoDecoder(
126 context->GetCommandBufferProxy()->GetRouteID(), profile, client);
127 }
128 message_loop_async_waiter_.Signal();
129 }
130
131 uint32 RendererGpuVideoAcceleratorFactories::CreateTextures( 91 uint32 RendererGpuVideoAcceleratorFactories::CreateTextures(
132 int32 count, 92 int32 count,
133 const gfx::Size& size, 93 const gfx::Size& size,
134 std::vector<uint32>* texture_ids, 94 std::vector<uint32>* texture_ids,
135 std::vector<gpu::Mailbox>* texture_mailboxes, 95 std::vector<gpu::Mailbox>* texture_mailboxes,
136 uint32 texture_target) { 96 uint32 texture_target) {
137 DCHECK(message_loop_->BelongsToCurrentThread()); 97 DCHECK(message_loop_->BelongsToCurrentThread());
138 DCHECK(texture_target); 98 DCHECK(texture_target);
139 99
140 WebGraphicsContext3DCommandBufferImpl* context = GetContext3d(); 100 WebGraphicsContext3DCommandBufferImpl* context = GetContext3d();
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
194 DCHECK(message_loop_->BelongsToCurrentThread()); 154 DCHECK(message_loop_->BelongsToCurrentThread());
195 155
196 WebGraphicsContext3DCommandBufferImpl* context = GetContext3d(); 156 WebGraphicsContext3DCommandBufferImpl* context = GetContext3d();
197 if (!context) 157 if (!context)
198 return; 158 return;
199 159
200 gpu::gles2::GLES2Implementation* gles2 = context->GetImplementation(); 160 gpu::gles2::GLES2Implementation* gles2 = context->GetImplementation();
201 gles2->WaitSyncPointCHROMIUM(sync_point); 161 gles2->WaitSyncPointCHROMIUM(sync_point);
202 } 162 }
203 163
204 void RendererGpuVideoAcceleratorFactories::ReadPixels(uint32 texture_id, 164 void RendererGpuVideoAcceleratorFactories::ReadPixels(uint32 texture_id,
Ami GONE FROM CHROMIUM 2013/10/17 22:22:17 I believe this is called from the compositing thre
sheu 2013/10/21 05:17:35 Gonna refactor the trampolines out of this class.
205 const gfx::Size& size, 165 const gfx::Size& size,
206 const SkBitmap& pixels) { 166 const SkBitmap& pixels) {
207 // SkBitmaps use the SkPixelRef object to refcount the underlying pixels. 167 base::WaitableEvent waiter(true, false);
208 // Multiple SkBitmaps can share a SkPixelRef instance. We use this to
209 // ensure that the underlying pixels in the SkBitmap passed in remain valid
210 // until the AsyncReadPixels() call completes.
211 read_pixels_bitmap_.setPixelRef(pixels.pixelRef());
212
213 if (!message_loop_->BelongsToCurrentThread()) { 168 if (!message_loop_->BelongsToCurrentThread()) {
214 message_loop_->PostTask( 169 message_loop_->PostTask(
215 FROM_HERE, 170 FROM_HERE,
216 base::Bind(&RendererGpuVideoAcceleratorFactories::AsyncReadPixels, 171 base::Bind(&RendererGpuVideoAcceleratorFactories::AsyncReadPixels,
217 this, 172 this,
218 texture_id, 173 texture_id,
219 size)); 174 size,
220 base::WaitableEvent* objects[] = {&aborted_waiter_, 175 pixels,
221 &message_loop_async_waiter_}; 176 &waiter));
222 if (base::WaitableEvent::WaitMany(objects, arraysize(objects)) == 0) 177 waiter.Wait();
Ami GONE FROM CHROMIUM 2013/10/17 22:22:17 This is only deadlock-safe if the media thread is
223 return; 178 return;
224 } else { 179 } else {
225 AsyncReadPixels(texture_id, size); 180 AsyncReadPixels(texture_id, size, pixels, &waiter);
226 message_loop_async_waiter_.Reset();
227 } 181 }
228 read_pixels_bitmap_.setPixelRef(NULL);
229 } 182 }
230 183
231 void RendererGpuVideoAcceleratorFactories::AsyncReadPixels( 184 void RendererGpuVideoAcceleratorFactories::AsyncReadPixels(
232 uint32 texture_id, 185 uint32 texture_id,
233 const gfx::Size& size) { 186 const gfx::Size& size,
187 const SkBitmap& pixels,
188 base::WaitableEvent* waiter) {
234 DCHECK(message_loop_->BelongsToCurrentThread()); 189 DCHECK(message_loop_->BelongsToCurrentThread());
235 WebGraphicsContext3DCommandBufferImpl* context = GetContext3d(); 190 WebGraphicsContext3DCommandBufferImpl* context = GetContext3d();
236 if (!context) { 191 if (!context) {
237 message_loop_async_waiter_.Signal(); 192 waiter->Signal();
238 return; 193 return;
239 } 194 }
240 195
241 gpu::gles2::GLES2Implementation* gles2 = context->GetImplementation(); 196 gpu::gles2::GLES2Implementation* gles2 = context->GetImplementation();
242 197
243 GLuint tmp_texture; 198 GLuint tmp_texture;
244 gles2->GenTextures(1, &tmp_texture); 199 gles2->GenTextures(1, &tmp_texture);
245 gles2->BindTexture(GL_TEXTURE_2D, tmp_texture); 200 gles2->BindTexture(GL_TEXTURE_2D, tmp_texture);
246 gles2->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 201 gles2->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
247 gles2->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 202 gles2->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
248 gles2->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 203 gles2->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
249 gles2->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 204 gles2->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
250 context->copyTextureCHROMIUM( 205 context->copyTextureCHROMIUM(
251 GL_TEXTURE_2D, texture_id, tmp_texture, 0, GL_RGBA, GL_UNSIGNED_BYTE); 206 GL_TEXTURE_2D, texture_id, tmp_texture, 0, GL_RGBA, GL_UNSIGNED_BYTE);
252 207
253 GLuint fb; 208 GLuint fb;
254 gles2->GenFramebuffers(1, &fb); 209 gles2->GenFramebuffers(1, &fb);
255 gles2->BindFramebuffer(GL_FRAMEBUFFER, fb); 210 gles2->BindFramebuffer(GL_FRAMEBUFFER, fb);
256 gles2->FramebufferTexture2D( 211 gles2->FramebufferTexture2D(
257 GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tmp_texture, 0); 212 GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tmp_texture, 0);
258 gles2->PixelStorei(GL_PACK_ALIGNMENT, 4); 213 gles2->PixelStorei(GL_PACK_ALIGNMENT, 4);
259 gles2->ReadPixels(0, 214 gles2->ReadPixels(0,
260 0, 215 0,
261 size.width(), 216 size.width(),
262 size.height(), 217 size.height(),
263 GL_BGRA_EXT, 218 GL_BGRA_EXT,
264 GL_UNSIGNED_BYTE, 219 GL_UNSIGNED_BYTE,
265 read_pixels_bitmap_.pixelRef()->pixels()); 220 pixels.pixelRef()->pixels());
266 gles2->DeleteFramebuffers(1, &fb); 221 gles2->DeleteFramebuffers(1, &fb);
267 gles2->DeleteTextures(1, &tmp_texture); 222 gles2->DeleteTextures(1, &tmp_texture);
268 DCHECK_EQ(gles2->GetError(), static_cast<GLenum>(GL_NO_ERROR)); 223 DCHECK_EQ(gles2->GetError(), static_cast<GLenum>(GL_NO_ERROR));
269 message_loop_async_waiter_.Signal(); 224 waiter->Signal();
270 } 225 }
271 226
272 base::SharedMemory* RendererGpuVideoAcceleratorFactories::CreateSharedMemory( 227 base::SharedMemory* RendererGpuVideoAcceleratorFactories::CreateSharedMemory(
273 size_t size) { 228 size_t size) {
274 DCHECK(message_loop_->BelongsToCurrentThread()); 229 DCHECK(message_loop_->BelongsToCurrentThread());
275 return ChildThread::AllocateSharedMemory(size, thread_safe_sender_.get()); 230 return ChildThread::AllocateSharedMemory(size, thread_safe_sender_.get());
276 } 231 }
277 232
278 scoped_refptr<base::MessageLoopProxy> 233 scoped_refptr<base::MessageLoopProxy>
279 RendererGpuVideoAcceleratorFactories::GetMessageLoop() { 234 RendererGpuVideoAcceleratorFactories::GetMessageLoop() {
280 return message_loop_; 235 return message_loop_;
281 } 236 }
282 237
283 void RendererGpuVideoAcceleratorFactories::Abort() { aborted_waiter_.Signal(); }
284
285 bool RendererGpuVideoAcceleratorFactories::IsAborted() {
286 return aborted_waiter_.IsSignaled();
287 }
288
289 scoped_refptr<RendererGpuVideoAcceleratorFactories>
290 RendererGpuVideoAcceleratorFactories::Clone() {
291 scoped_refptr<RendererGpuVideoAcceleratorFactories> factories =
292 new RendererGpuVideoAcceleratorFactories();
293 factories->message_loop_ = message_loop_;
294 factories->gpu_channel_host_ = gpu_channel_host_;
295 factories->context_provider_ = context_provider_;
296 factories->thread_safe_sender_ = thread_safe_sender_;
297 return factories;
298 }
299
300 void
301 RendererGpuVideoAcceleratorFactories::AsyncDestroyVideoDecodeAccelerator() {
302 // OK to release because Destroy() will delete the VDA instance.
303 if (vda_)
304 vda_.release()->Destroy();
305 }
306
307 } // namespace content 238 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698