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

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

Powered by Google App Engine
This is Rietveld 408576698