OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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_decoder_factories.h" | 5 #include "content/renderer/media/renderer_gpu_video_decoder_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" |
(...skipping 11 matching lines...) Expand all Loading... |
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 WebGraphicsContext3DCommandBufferImpl* context) | 24 WebGraphicsContext3DCommandBufferImpl* context) |
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 aborted_waiter_(true, false), | 27 aborted_waiter_(true, false), |
28 compositor_loop_async_waiter_(false, false), | 28 compositor_loop_async_waiter_(false, false), |
29 render_thread_async_waiter_(false, false) { | 29 render_thread_async_waiter_(false, false) { |
30 if (message_loop_->BelongsToCurrentThread()) { | 30 if (message_loop_->BelongsToCurrentThread()) { |
31 AsyncGetContext(context); | 31 AsyncGetContext(context); |
| 32 compositor_loop_async_waiter_.Reset(); |
32 return; | 33 return; |
33 } | 34 } |
34 // Threaded compositor requires us to wait for the context to be acquired. | 35 // Threaded compositor requires us to wait for the context to be acquired. |
35 message_loop_->PostTask(FROM_HERE, base::Bind( | 36 message_loop_->PostTask(FROM_HERE, base::Bind( |
36 &RendererGpuVideoDecoderFactories::AsyncGetContext, | 37 &RendererGpuVideoDecoderFactories::AsyncGetContext, |
37 // Unretained to avoid ref/deref'ing |*this|, which is not yet stored in a | 38 // Unretained to avoid ref/deref'ing |*this|, which is not yet stored in a |
38 // scoped_refptr. Safe because the Wait() below keeps us alive until this | 39 // scoped_refptr. Safe because the Wait() below keeps us alive until this |
39 // task completes. | 40 // task completes. |
40 base::Unretained(this), | 41 base::Unretained(this), |
41 // OK to pass raw because the pointee is only deleted on the compositor | 42 // OK to pass raw because the pointee is only deleted on the compositor |
42 // thread, and only as the result of a PostTask from the render thread | 43 // thread, and only as the result of a PostTask from the render thread |
43 // which can only happen after this function returns, so our PostTask will | 44 // which can only happen after this function returns, so our PostTask will |
44 // run first. | 45 // run first. |
45 context)); | 46 context)); |
46 compositor_loop_async_waiter_.Wait(); | 47 compositor_loop_async_waiter_.Wait(); |
47 } | 48 } |
48 | 49 |
| 50 RendererGpuVideoDecoderFactories::RendererGpuVideoDecoderFactories( |
| 51 scoped_refptr<base::MessageLoopProxy> message_loop, |
| 52 scoped_refptr<GpuChannelHost> gpu_channel_host, |
| 53 base::WeakPtr<WebGraphicsContext3DCommandBufferImpl> context) |
| 54 : message_loop_(message_loop), |
| 55 gpu_channel_host_(gpu_channel_host), |
| 56 context_(context), |
| 57 aborted_waiter_(true, false), |
| 58 compositor_loop_async_waiter_(false, false), |
| 59 render_thread_async_waiter_(false, false) { |
| 60 } |
| 61 |
| 62 RendererGpuVideoDecoderFactories* RendererGpuVideoDecoderFactories::Copy() { |
| 63 return new RendererGpuVideoDecoderFactories( |
| 64 message_loop_, gpu_channel_host_, context_); |
| 65 } |
| 66 |
49 void RendererGpuVideoDecoderFactories::AsyncGetContext( | 67 void RendererGpuVideoDecoderFactories::AsyncGetContext( |
50 WebGraphicsContext3DCommandBufferImpl* context) { | 68 WebGraphicsContext3DCommandBufferImpl* context) { |
51 context_ = context->AsWeakPtr(); | 69 context_ = context->AsWeakPtr(); |
52 if (context_) { | 70 if (context_) { |
53 if (context_->makeContextCurrent()) { | 71 if (context_->makeContextCurrent()) { |
54 // Called once per media player, but is a no-op after the first one in | 72 // Called once per media player, but is a no-op after the first one in |
55 // each renderer. | 73 // each renderer. |
56 context_->insertEventMarkerEXT("GpuVDAContext3D"); | 74 context_->insertEventMarkerEXT("GpuVDAContext3D"); |
57 } | 75 } |
58 } | 76 } |
59 compositor_loop_async_waiter_.Signal(); | 77 compositor_loop_async_waiter_.Signal(); |
60 } | 78 } |
61 | 79 |
62 media::VideoDecodeAccelerator* | 80 media::VideoDecodeAccelerator* |
63 RendererGpuVideoDecoderFactories::CreateVideoDecodeAccelerator( | 81 RendererGpuVideoDecoderFactories::CreateVideoDecodeAccelerator( |
64 media::VideoCodecProfile profile, | 82 media::VideoCodecProfile profile, |
65 media::VideoDecodeAccelerator::Client* client) { | 83 media::VideoDecodeAccelerator::Client* client) { |
66 DCHECK(!message_loop_->BelongsToCurrentThread()); | 84 if (message_loop_->BelongsToCurrentThread()) { |
| 85 AsyncCreateVideoDecodeAccelerator(profile, client); |
| 86 compositor_loop_async_waiter_.Reset(); |
| 87 return vda_.release(); |
| 88 } |
67 // The VDA is returned in the vda_ member variable by the | 89 // The VDA is returned in the vda_ member variable by the |
68 // AsyncCreateVideoDecodeAccelerator() function. | 90 // AsyncCreateVideoDecodeAccelerator() function. |
69 message_loop_->PostTask(FROM_HERE, base::Bind( | 91 message_loop_->PostTask(FROM_HERE, base::Bind( |
70 &RendererGpuVideoDecoderFactories::AsyncCreateVideoDecodeAccelerator, | 92 &RendererGpuVideoDecoderFactories::AsyncCreateVideoDecodeAccelerator, |
71 this, profile, client)); | 93 this, profile, client)); |
72 | 94 |
73 base::WaitableEvent* objects[] = {&aborted_waiter_, | 95 base::WaitableEvent* objects[] = {&aborted_waiter_, |
74 &compositor_loop_async_waiter_}; | 96 &compositor_loop_async_waiter_}; |
75 if (base::WaitableEvent::WaitMany(objects, arraysize(objects)) == 0) { | 97 if (base::WaitableEvent::WaitMany(objects, arraysize(objects)) == 0) { |
76 // If we are aborting and the VDA is created by the | 98 // If we are aborting and the VDA is created by the |
(...skipping 17 matching lines...) Expand all Loading... |
94 context_->GetCommandBufferProxy()->GetRouteID(), | 116 context_->GetCommandBufferProxy()->GetRouteID(), |
95 profile, client); | 117 profile, client); |
96 } | 118 } |
97 compositor_loop_async_waiter_.Signal(); | 119 compositor_loop_async_waiter_.Signal(); |
98 } | 120 } |
99 | 121 |
100 bool RendererGpuVideoDecoderFactories::CreateTextures( | 122 bool RendererGpuVideoDecoderFactories::CreateTextures( |
101 int32 count, const gfx::Size& size, | 123 int32 count, const gfx::Size& size, |
102 std::vector<uint32>* texture_ids, | 124 std::vector<uint32>* texture_ids, |
103 uint32 texture_target) { | 125 uint32 texture_target) { |
104 DCHECK(!message_loop_->BelongsToCurrentThread()); | 126 if (message_loop_->BelongsToCurrentThread()) { |
| 127 AsyncCreateTextures(count, size, texture_target); |
| 128 texture_ids->swap(created_textures_); |
| 129 compositor_loop_async_waiter_.Reset(); |
| 130 return true; |
| 131 } |
105 message_loop_->PostTask(FROM_HERE, base::Bind( | 132 message_loop_->PostTask(FROM_HERE, base::Bind( |
106 &RendererGpuVideoDecoderFactories::AsyncCreateTextures, this, | 133 &RendererGpuVideoDecoderFactories::AsyncCreateTextures, this, |
107 count, size, texture_target)); | 134 count, size, texture_target)); |
108 | 135 |
109 base::WaitableEvent* objects[] = {&aborted_waiter_, | 136 base::WaitableEvent* objects[] = {&aborted_waiter_, |
110 &compositor_loop_async_waiter_}; | 137 &compositor_loop_async_waiter_}; |
111 if (base::WaitableEvent::WaitMany(objects, arraysize(objects)) == 0) | 138 if (base::WaitableEvent::WaitMany(objects, arraysize(objects)) == 0) |
112 return false; | 139 return false; |
113 texture_ids->swap(created_textures_); | 140 texture_ids->swap(created_textures_); |
114 return true; | 141 return true; |
(...skipping 26 matching lines...) Expand all Loading... |
141 } | 168 } |
142 // We need a glFlush here to guarantee the decoder (in the GPU process) can | 169 // We need a glFlush here to guarantee the decoder (in the GPU process) can |
143 // use the texture ids we return here. Since textures are expected to be | 170 // use the texture ids we return here. Since textures are expected to be |
144 // reused, this should not be unacceptably expensive. | 171 // reused, this should not be unacceptably expensive. |
145 gles2->Flush(); | 172 gles2->Flush(); |
146 DCHECK_EQ(gles2->GetError(), static_cast<GLenum>(GL_NO_ERROR)); | 173 DCHECK_EQ(gles2->GetError(), static_cast<GLenum>(GL_NO_ERROR)); |
147 compositor_loop_async_waiter_.Signal(); | 174 compositor_loop_async_waiter_.Signal(); |
148 } | 175 } |
149 | 176 |
150 void RendererGpuVideoDecoderFactories::DeleteTexture(uint32 texture_id) { | 177 void RendererGpuVideoDecoderFactories::DeleteTexture(uint32 texture_id) { |
151 DCHECK(!message_loop_->BelongsToCurrentThread()); | 178 if (message_loop_->BelongsToCurrentThread()) { |
| 179 AsyncDeleteTexture(texture_id); |
| 180 return; |
| 181 } |
152 message_loop_->PostTask(FROM_HERE, base::Bind( | 182 message_loop_->PostTask(FROM_HERE, base::Bind( |
153 &RendererGpuVideoDecoderFactories::AsyncDeleteTexture, this, texture_id)); | 183 &RendererGpuVideoDecoderFactories::AsyncDeleteTexture, this, texture_id)); |
154 } | 184 } |
155 | 185 |
156 void RendererGpuVideoDecoderFactories::AsyncDeleteTexture(uint32 texture_id) { | 186 void RendererGpuVideoDecoderFactories::AsyncDeleteTexture(uint32 texture_id) { |
157 DCHECK(message_loop_->BelongsToCurrentThread()); | 187 DCHECK(message_loop_->BelongsToCurrentThread()); |
158 if (!context_) | 188 if (!context_) |
159 return; | 189 return; |
160 | 190 |
161 gpu::gles2::GLES2Implementation* gles2 = context_->GetImplementation(); | 191 gpu::gles2::GLES2Implementation* gles2 = context_->GetImplementation(); |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
257 return aborted_waiter_.IsSignaled(); | 287 return aborted_waiter_.IsSignaled(); |
258 } | 288 } |
259 | 289 |
260 void RendererGpuVideoDecoderFactories::AsyncDestroyVideoDecodeAccelerator() { | 290 void RendererGpuVideoDecoderFactories::AsyncDestroyVideoDecodeAccelerator() { |
261 // OK to release because Destroy() will delete the VDA instance. | 291 // OK to release because Destroy() will delete the VDA instance. |
262 if (vda_) | 292 if (vda_) |
263 vda_.release()->Destroy(); | 293 vda_.release()->Destroy(); |
264 } | 294 } |
265 | 295 |
266 } // namespace content | 296 } // namespace content |
OLD | NEW |