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

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: 2d3efbfa Rebase. 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,
25 const scoped_refptr<base::MessageLoopProxy>& message_loop_proxy,
24 const scoped_refptr<ContextProviderCommandBuffer>& context_provider) 26 const scoped_refptr<ContextProviderCommandBuffer>& context_provider)
25 : message_loop_( 27 : message_loop_proxy_(message_loop_proxy),
26 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.
33 if (!context_provider_)
34 return;
35
36 if (message_loop_->BelongsToCurrentThread()) {
37 AsyncBindContext();
38 message_loop_async_waiter_.Reset();
39 return;
40 }
41 // Wait for the context to be acquired.
42 message_loop_->PostTask(
43 FROM_HERE,
44 base::Bind(&RendererGpuVideoAcceleratorFactories::AsyncBindContext,
45 // Unretained to avoid ref/deref'ing |*this|, which is not yet
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 }
51
52 RendererGpuVideoAcceleratorFactories::RendererGpuVideoAcceleratorFactories()
53 : aborted_waiter_(true, false),
54 message_loop_async_waiter_(false, false) {}
55 31
56 WebGraphicsContext3DCommandBufferImpl* 32 WebGraphicsContext3DCommandBufferImpl*
57 RendererGpuVideoAcceleratorFactories::GetContext3d() { 33 RendererGpuVideoAcceleratorFactories::GetContext3d() {
58 DCHECK(message_loop_->BelongsToCurrentThread()); 34 DCHECK(message_loop_proxy_->BelongsToCurrentThread());
59 if (!context_provider_) 35 if (!context_provider_)
60 return NULL; 36 return NULL;
61 WebGraphicsContext3DCommandBufferImpl* context = 37 WebGraphicsContext3DCommandBufferImpl* context =
62 context_provider_->Context3d(); 38 context_provider_->Context3d();
63 if (context->isContextLost()) { 39 if (context->isContextLost()) {
64 context_provider_->VerifyContexts(); 40 context_provider_->VerifyContexts();
65 context_provider_ = NULL; 41 context_provider_ = NULL;
66 return NULL; 42 return NULL;
67 } 43 }
68 return context; 44 return context;
69 } 45 }
70 46
71 void RendererGpuVideoAcceleratorFactories::AsyncBindContext() {
72 DCHECK(message_loop_->BelongsToCurrentThread());
73 if (!context_provider_->BindToCurrentThread())
74 context_provider_ = NULL;
75 message_loop_async_waiter_.Signal();
76 }
77
78 scoped_ptr<media::VideoDecodeAccelerator> 47 scoped_ptr<media::VideoDecodeAccelerator>
79 RendererGpuVideoAcceleratorFactories::CreateVideoDecodeAccelerator( 48 RendererGpuVideoAcceleratorFactories::CreateVideoDecodeAccelerator(
80 media::VideoCodecProfile profile, 49 media::VideoCodecProfile profile,
81 media::VideoDecodeAccelerator::Client* client) { 50 media::VideoDecodeAccelerator::Client* client) {
82 if (message_loop_->BelongsToCurrentThread()) { 51 DCHECK(message_loop_proxy_->BelongsToCurrentThread());
83 AsyncCreateVideoDecodeAccelerator(profile, client); 52
84 message_loop_async_waiter_.Reset(); 53 WebGraphicsContext3DCommandBufferImpl* context = GetContext3d();
85 return vda_.Pass(); 54 if (context && context->GetCommandBufferProxy()) {
55 return gpu_channel_host_->CreateVideoDecoder(
56 context->GetCommandBufferProxy()->GetRouteID(), profile, client);
86 } 57 }
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 58
96 base::WaitableEvent* objects[] = {&aborted_waiter_, 59 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 } 60 }
110 61
111 scoped_ptr<media::VideoEncodeAccelerator> 62 scoped_ptr<media::VideoEncodeAccelerator>
112 RendererGpuVideoAcceleratorFactories::CreateVideoEncodeAccelerator( 63 RendererGpuVideoAcceleratorFactories::CreateVideoEncodeAccelerator(
113 media::VideoEncodeAccelerator::Client* client) { 64 media::VideoEncodeAccelerator::Client* client) {
114 DCHECK(message_loop_->BelongsToCurrentThread()); 65 DCHECK(message_loop_proxy_->BelongsToCurrentThread());
115 66
116 return gpu_channel_host_->CreateVideoEncoder(client); 67 return gpu_channel_host_->CreateVideoEncoder(client);
117 } 68 }
118 69
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( 70 uint32 RendererGpuVideoAcceleratorFactories::CreateTextures(
133 int32 count, 71 int32 count,
134 const gfx::Size& size, 72 const gfx::Size& size,
135 std::vector<uint32>* texture_ids, 73 std::vector<uint32>* texture_ids,
136 std::vector<gpu::Mailbox>* texture_mailboxes, 74 std::vector<gpu::Mailbox>* texture_mailboxes,
137 uint32 texture_target) { 75 uint32 texture_target) {
138 DCHECK(message_loop_->BelongsToCurrentThread()); 76 DCHECK(message_loop_proxy_->BelongsToCurrentThread());
139 DCHECK(texture_target); 77 DCHECK(texture_target);
140 78
141 WebGraphicsContext3DCommandBufferImpl* context = GetContext3d(); 79 WebGraphicsContext3DCommandBufferImpl* context = GetContext3d();
142 if (!context) 80 if (!context)
143 return 0; 81 return 0;
144 82
145 gpu::gles2::GLES2Implementation* gles2 = context->GetImplementation(); 83 gpu::gles2::GLES2Implementation* gles2 = context->GetImplementation();
146 texture_ids->resize(count); 84 texture_ids->resize(count);
147 texture_mailboxes->resize(count); 85 texture_mailboxes->resize(count);
148 gles2->GenTextures(count, &texture_ids->at(0)); 86 gles2->GenTextures(count, &texture_ids->at(0));
(...skipping 24 matching lines...) Expand all
173 // We need a glFlush here to guarantee the decoder (in the GPU process) can 111 // We need a glFlush here to guarantee the decoder (in the GPU process) can
174 // use the texture ids we return here. Since textures are expected to be 112 // use the texture ids we return here. Since textures are expected to be
175 // reused, this should not be unacceptably expensive. 113 // reused, this should not be unacceptably expensive.
176 gles2->Flush(); 114 gles2->Flush();
177 DCHECK_EQ(gles2->GetError(), static_cast<GLenum>(GL_NO_ERROR)); 115 DCHECK_EQ(gles2->GetError(), static_cast<GLenum>(GL_NO_ERROR));
178 116
179 return gles2->InsertSyncPointCHROMIUM(); 117 return gles2->InsertSyncPointCHROMIUM();
180 } 118 }
181 119
182 void RendererGpuVideoAcceleratorFactories::DeleteTexture(uint32 texture_id) { 120 void RendererGpuVideoAcceleratorFactories::DeleteTexture(uint32 texture_id) {
183 DCHECK(message_loop_->BelongsToCurrentThread()); 121 DCHECK(message_loop_proxy_->BelongsToCurrentThread());
184 122
185 WebGraphicsContext3DCommandBufferImpl* context = GetContext3d(); 123 WebGraphicsContext3DCommandBufferImpl* context = GetContext3d();
186 if (!context) 124 if (!context)
187 return; 125 return;
188 126
189 gpu::gles2::GLES2Implementation* gles2 = context->GetImplementation(); 127 gpu::gles2::GLES2Implementation* gles2 = context->GetImplementation();
190 gles2->DeleteTextures(1, &texture_id); 128 gles2->DeleteTextures(1, &texture_id);
191 DCHECK_EQ(gles2->GetError(), static_cast<GLenum>(GL_NO_ERROR)); 129 DCHECK_EQ(gles2->GetError(), static_cast<GLenum>(GL_NO_ERROR));
192 } 130 }
193 131
194 void RendererGpuVideoAcceleratorFactories::WaitSyncPoint(uint32 sync_point) { 132 void RendererGpuVideoAcceleratorFactories::WaitSyncPoint(uint32 sync_point) {
195 DCHECK(message_loop_->BelongsToCurrentThread()); 133 DCHECK(message_loop_proxy_->BelongsToCurrentThread());
196 134
197 WebGraphicsContext3DCommandBufferImpl* context = GetContext3d(); 135 WebGraphicsContext3DCommandBufferImpl* context = GetContext3d();
198 if (!context) 136 if (!context)
199 return; 137 return;
200 138
201 gpu::gles2::GLES2Implementation* gles2 = context->GetImplementation(); 139 gpu::gles2::GLES2Implementation* gles2 = context->GetImplementation();
202 gles2->WaitSyncPointCHROMIUM(sync_point); 140 gles2->WaitSyncPointCHROMIUM(sync_point);
203 } 141 }
204 142
205 void RendererGpuVideoAcceleratorFactories::ReadPixels(uint32 texture_id, 143 void RendererGpuVideoAcceleratorFactories::ReadPixels(uint32 texture_id,
206 const gfx::Size& size, 144 const gfx::Size& size,
207 const SkBitmap& pixels) { 145 const SkBitmap& pixels) {
208 // SkBitmaps use the SkPixelRef object to refcount the underlying pixels. 146 DCHECK(message_loop_proxy_->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 147
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(); 148 WebGraphicsContext3DCommandBufferImpl* context = GetContext3d();
237 if (!context) { 149 if (!context)
238 message_loop_async_waiter_.Signal();
239 return; 150 return;
240 }
241 151
242 gpu::gles2::GLES2Implementation* gles2 = context->GetImplementation(); 152 gpu::gles2::GLES2Implementation* gles2 = context->GetImplementation();
243 153
244 GLuint tmp_texture; 154 GLuint tmp_texture;
245 gles2->GenTextures(1, &tmp_texture); 155 gles2->GenTextures(1, &tmp_texture);
246 gles2->BindTexture(GL_TEXTURE_2D, tmp_texture); 156 gles2->BindTexture(GL_TEXTURE_2D, tmp_texture);
247 gles2->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 157 gles2->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
248 gles2->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 158 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); 159 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); 160 gles2->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
(...skipping 14 matching lines...) Expand all
265 GLenum skia_format = GL_RGBA; 175 GLenum skia_format = GL_RGBA;
266 #else 176 #else
267 #error Unexpected Skia ARGB_8888 layout! 177 #error Unexpected Skia ARGB_8888 layout!
268 #endif 178 #endif
269 gles2->ReadPixels(0, 179 gles2->ReadPixels(0,
270 0, 180 0,
271 size.width(), 181 size.width(),
272 size.height(), 182 size.height(),
273 skia_format, 183 skia_format,
274 GL_UNSIGNED_BYTE, 184 GL_UNSIGNED_BYTE,
275 read_pixels_bitmap_.pixelRef()->pixels()); 185 pixels.pixelRef()->pixels());
276 gles2->DeleteFramebuffers(1, &fb); 186 gles2->DeleteFramebuffers(1, &fb);
277 gles2->DeleteTextures(1, &tmp_texture); 187 gles2->DeleteTextures(1, &tmp_texture);
278 DCHECK_EQ(gles2->GetError(), static_cast<GLenum>(GL_NO_ERROR)); 188 DCHECK_EQ(gles2->GetError(), static_cast<GLenum>(GL_NO_ERROR));
279 message_loop_async_waiter_.Signal();
280 } 189 }
281 190
282 base::SharedMemory* RendererGpuVideoAcceleratorFactories::CreateSharedMemory( 191 base::SharedMemory* RendererGpuVideoAcceleratorFactories::CreateSharedMemory(
283 size_t size) { 192 size_t size) {
284 DCHECK(message_loop_->BelongsToCurrentThread()); 193 DCHECK(message_loop_proxy_->BelongsToCurrentThread());
285 return ChildThread::AllocateSharedMemory(size, thread_safe_sender_.get()); 194 return ChildThread::AllocateSharedMemory(size, thread_safe_sender_.get());
286 } 195 }
287 196
288 scoped_refptr<base::MessageLoopProxy> 197 scoped_refptr<base::MessageLoopProxy>
289 RendererGpuVideoAcceleratorFactories::GetMessageLoop() { 198 RendererGpuVideoAcceleratorFactories::GetMessageLoop() {
290 return message_loop_; 199 return message_loop_proxy_;
291 }
292
293 void RendererGpuVideoAcceleratorFactories::Abort() { aborted_waiter_.Signal(); }
294
295 bool RendererGpuVideoAcceleratorFactories::IsAborted() {
296 return aborted_waiter_.IsSignaled();
297 }
298
299 scoped_refptr<RendererGpuVideoAcceleratorFactories>
300 RendererGpuVideoAcceleratorFactories::Clone() {
301 scoped_refptr<RendererGpuVideoAcceleratorFactories> factories =
302 new RendererGpuVideoAcceleratorFactories();
303 factories->message_loop_ = message_loop_;
304 factories->gpu_channel_host_ = gpu_channel_host_;
305 factories->context_provider_ = context_provider_;
306 factories->thread_safe_sender_ = thread_safe_sender_;
307 return factories;
308 }
309
310 void
311 RendererGpuVideoAcceleratorFactories::AsyncDestroyVideoDecodeAccelerator() {
312 // OK to release because Destroy() will delete the VDA instance.
313 if (vda_)
314 vda_.release()->Destroy();
315 } 200 }
316 201
317 } // namespace content 202 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698