Chromium Code Reviews| 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 : aborted_waiter_(true, false), | |
| 52 compositor_loop_async_waiter_(false, false), | |
| 53 render_thread_async_waiter_(false, false) {} | |
| 54 | |
| 55 scoped_refptr<RendererGpuVideoDecoderFactories> | |
| 56 RendererGpuVideoDecoderFactories::Clone() { | |
| 57 scoped_refptr<RendererGpuVideoDecoderFactories> factories = | |
| 58 new RendererGpuVideoDecoderFactories(); | |
| 59 factories->message_loop_ = message_loop_; | |
| 60 factories->gpu_channel_host_ = gpu_channel_host_; | |
| 61 factories->context_ = context_; | |
| 62 return factories; | |
| 63 } | |
| 64 | |
| 49 void RendererGpuVideoDecoderFactories::AsyncGetContext( | 65 void RendererGpuVideoDecoderFactories::AsyncGetContext( |
| 50 WebGraphicsContext3DCommandBufferImpl* context) { | 66 WebGraphicsContext3DCommandBufferImpl* context) { |
| 51 context_ = context->AsWeakPtr(); | 67 context_ = context->AsWeakPtr(); |
| 52 if (context_) { | 68 if (context_) { |
| 53 if (context_->makeContextCurrent()) { | 69 if (context_->makeContextCurrent()) { |
| 54 // Called once per media player, but is a no-op after the first one in | 70 // Called once per media player, but is a no-op after the first one in |
| 55 // each renderer. | 71 // each renderer. |
| 56 context_->insertEventMarkerEXT("GpuVDAContext3D"); | 72 context_->insertEventMarkerEXT("GpuVDAContext3D"); |
| 57 } | 73 } |
| 58 } | 74 } |
| 59 compositor_loop_async_waiter_.Signal(); | 75 compositor_loop_async_waiter_.Signal(); |
| 60 } | 76 } |
| 61 | 77 |
| 62 media::VideoDecodeAccelerator* | 78 media::VideoDecodeAccelerator* |
| 63 RendererGpuVideoDecoderFactories::CreateVideoDecodeAccelerator( | 79 RendererGpuVideoDecoderFactories::CreateVideoDecodeAccelerator( |
| 64 media::VideoCodecProfile profile, | 80 media::VideoCodecProfile profile, |
| 65 media::VideoDecodeAccelerator::Client* client) { | 81 media::VideoDecodeAccelerator::Client* client) { |
| 66 DCHECK(!message_loop_->BelongsToCurrentThread()); | 82 DCHECK(!message_loop_->BelongsToCurrentThread()); |
|
Ami GONE FROM CHROMIUM
2013/06/13 20:10:03
Why remove the sync path?
wuchengli
2013/06/18 16:11:23
This patchset uses a new thread as |message_loop_|
| |
| 67 // The VDA is returned in the vda_ member variable by the | 83 // The VDA is returned in the vda_ member variable by the |
| 68 // AsyncCreateVideoDecodeAccelerator() function. | 84 // AsyncCreateVideoDecodeAccelerator() function. |
| 69 message_loop_->PostTask(FROM_HERE, base::Bind( | 85 message_loop_->PostTask(FROM_HERE, base::Bind( |
| 70 &RendererGpuVideoDecoderFactories::AsyncCreateVideoDecodeAccelerator, | 86 &RendererGpuVideoDecoderFactories::AsyncCreateVideoDecodeAccelerator, |
| 71 this, profile, client)); | 87 this, profile, client)); |
| 72 | 88 |
| 73 base::WaitableEvent* objects[] = {&aborted_waiter_, | 89 base::WaitableEvent* objects[] = {&aborted_waiter_, |
| 74 &compositor_loop_async_waiter_}; | 90 &compositor_loop_async_waiter_}; |
| 75 if (base::WaitableEvent::WaitMany(objects, arraysize(objects)) == 0) { | 91 if (base::WaitableEvent::WaitMany(objects, arraysize(objects)) == 0) { |
| 76 // If we are aborting and the VDA is created by the | 92 // If we are aborting and the VDA is created by the |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 94 context_->GetCommandBufferProxy()->GetRouteID(), | 110 context_->GetCommandBufferProxy()->GetRouteID(), |
| 95 profile, client); | 111 profile, client); |
| 96 } | 112 } |
| 97 compositor_loop_async_waiter_.Signal(); | 113 compositor_loop_async_waiter_.Signal(); |
| 98 } | 114 } |
| 99 | 115 |
| 100 bool RendererGpuVideoDecoderFactories::CreateTextures( | 116 bool RendererGpuVideoDecoderFactories::CreateTextures( |
| 101 int32 count, const gfx::Size& size, | 117 int32 count, const gfx::Size& size, |
| 102 std::vector<uint32>* texture_ids, | 118 std::vector<uint32>* texture_ids, |
| 103 uint32 texture_target) { | 119 uint32 texture_target) { |
| 104 DCHECK(!message_loop_->BelongsToCurrentThread()); | 120 if (message_loop_->BelongsToCurrentThread()) { |
| 121 AsyncCreateTextures(count, size, texture_target); | |
| 122 texture_ids->swap(created_textures_); | |
| 123 compositor_loop_async_waiter_.Reset(); | |
| 124 return true; | |
| 125 } | |
| 105 message_loop_->PostTask(FROM_HERE, base::Bind( | 126 message_loop_->PostTask(FROM_HERE, base::Bind( |
| 106 &RendererGpuVideoDecoderFactories::AsyncCreateTextures, this, | 127 &RendererGpuVideoDecoderFactories::AsyncCreateTextures, this, |
| 107 count, size, texture_target)); | 128 count, size, texture_target)); |
| 108 | 129 |
| 109 base::WaitableEvent* objects[] = {&aborted_waiter_, | 130 base::WaitableEvent* objects[] = {&aborted_waiter_, |
| 110 &compositor_loop_async_waiter_}; | 131 &compositor_loop_async_waiter_}; |
| 111 if (base::WaitableEvent::WaitMany(objects, arraysize(objects)) == 0) | 132 if (base::WaitableEvent::WaitMany(objects, arraysize(objects)) == 0) |
| 112 return false; | 133 return false; |
| 113 texture_ids->swap(created_textures_); | 134 texture_ids->swap(created_textures_); |
| 114 return true; | 135 return true; |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 141 } | 162 } |
| 142 // We need a glFlush here to guarantee the decoder (in the GPU process) can | 163 // 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 | 164 // use the texture ids we return here. Since textures are expected to be |
| 144 // reused, this should not be unacceptably expensive. | 165 // reused, this should not be unacceptably expensive. |
| 145 gles2->Flush(); | 166 gles2->Flush(); |
| 146 DCHECK_EQ(gles2->GetError(), static_cast<GLenum>(GL_NO_ERROR)); | 167 DCHECK_EQ(gles2->GetError(), static_cast<GLenum>(GL_NO_ERROR)); |
| 147 compositor_loop_async_waiter_.Signal(); | 168 compositor_loop_async_waiter_.Signal(); |
| 148 } | 169 } |
| 149 | 170 |
| 150 void RendererGpuVideoDecoderFactories::DeleteTexture(uint32 texture_id) { | 171 void RendererGpuVideoDecoderFactories::DeleteTexture(uint32 texture_id) { |
| 151 DCHECK(!message_loop_->BelongsToCurrentThread()); | 172 if (message_loop_->BelongsToCurrentThread()) { |
| 173 AsyncDeleteTexture(texture_id); | |
| 174 return; | |
| 175 } | |
| 152 message_loop_->PostTask(FROM_HERE, base::Bind( | 176 message_loop_->PostTask(FROM_HERE, base::Bind( |
| 153 &RendererGpuVideoDecoderFactories::AsyncDeleteTexture, this, texture_id)); | 177 &RendererGpuVideoDecoderFactories::AsyncDeleteTexture, this, texture_id)); |
| 154 } | 178 } |
| 155 | 179 |
| 156 void RendererGpuVideoDecoderFactories::AsyncDeleteTexture(uint32 texture_id) { | 180 void RendererGpuVideoDecoderFactories::AsyncDeleteTexture(uint32 texture_id) { |
| 157 DCHECK(message_loop_->BelongsToCurrentThread()); | 181 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 158 if (!context_) | 182 if (!context_) |
| 159 return; | 183 return; |
| 160 | 184 |
| 161 gpu::gles2::GLES2Implementation* gles2 = context_->GetImplementation(); | 185 gpu::gles2::GLES2Implementation* gles2 = context_->GetImplementation(); |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 257 return aborted_waiter_.IsSignaled(); | 281 return aborted_waiter_.IsSignaled(); |
| 258 } | 282 } |
| 259 | 283 |
| 260 void RendererGpuVideoDecoderFactories::AsyncDestroyVideoDecodeAccelerator() { | 284 void RendererGpuVideoDecoderFactories::AsyncDestroyVideoDecodeAccelerator() { |
| 261 // OK to release because Destroy() will delete the VDA instance. | 285 // OK to release because Destroy() will delete the VDA instance. |
| 262 if (vda_) | 286 if (vda_) |
| 263 vda_.release()->Destroy(); | 287 vda_.release()->Destroy(); |
| 264 } | 288 } |
| 265 | 289 |
| 266 } // namespace content | 290 } // namespace content |
| OLD | NEW |