| 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 |
| (...skipping 14 matching lines...) Expand all Loading... |
| 56 context_->insertEventMarkerEXT("GpuVDAContext3D"); | 57 context_->insertEventMarkerEXT("GpuVDAContext3D"); |
| 57 } | 58 } |
| 58 } | 59 } |
| 59 compositor_loop_async_waiter_.Signal(); | 60 compositor_loop_async_waiter_.Signal(); |
| 60 } | 61 } |
| 61 | 62 |
| 62 media::VideoDecodeAccelerator* | 63 media::VideoDecodeAccelerator* |
| 63 RendererGpuVideoDecoderFactories::CreateVideoDecodeAccelerator( | 64 RendererGpuVideoDecoderFactories::CreateVideoDecodeAccelerator( |
| 64 media::VideoCodecProfile profile, | 65 media::VideoCodecProfile profile, |
| 65 media::VideoDecodeAccelerator::Client* client) { | 66 media::VideoDecodeAccelerator::Client* client) { |
| 66 DCHECK(!message_loop_->BelongsToCurrentThread()); | 67 if (message_loop_->BelongsToCurrentThread()) { |
| 68 AsyncCreateVideoDecodeAccelerator(profile, client); |
| 69 compositor_loop_async_waiter_.Reset(); |
| 70 return vda_.release(); |
| 71 } |
| 67 // The VDA is returned in the vda_ member variable by the | 72 // The VDA is returned in the vda_ member variable by the |
| 68 // AsyncCreateVideoDecodeAccelerator() function. | 73 // AsyncCreateVideoDecodeAccelerator() function. |
| 69 message_loop_->PostTask(FROM_HERE, base::Bind( | 74 message_loop_->PostTask(FROM_HERE, base::Bind( |
| 70 &RendererGpuVideoDecoderFactories::AsyncCreateVideoDecodeAccelerator, | 75 &RendererGpuVideoDecoderFactories::AsyncCreateVideoDecodeAccelerator, |
| 71 this, profile, client)); | 76 this, profile, client)); |
| 72 | 77 |
| 73 base::WaitableEvent* objects[] = {&aborted_waiter_, | 78 base::WaitableEvent* objects[] = {&aborted_waiter_, |
| 74 &compositor_loop_async_waiter_}; | 79 &compositor_loop_async_waiter_}; |
| 75 if (base::WaitableEvent::WaitMany(objects, arraysize(objects)) == 0) { | 80 if (base::WaitableEvent::WaitMany(objects, arraysize(objects)) == 0) { |
| 76 // If we are aborting and the VDA is created by the | 81 // If we are aborting and the VDA is created by the |
| (...skipping 16 matching lines...) Expand all Loading... |
| 93 vda_ = gpu_channel_host_->CreateVideoDecoder( | 98 vda_ = gpu_channel_host_->CreateVideoDecoder( |
| 94 context_->GetCommandBufferProxy()->GetRouteID(), profile, client); | 99 context_->GetCommandBufferProxy()->GetRouteID(), profile, client); |
| 95 } | 100 } |
| 96 compositor_loop_async_waiter_.Signal(); | 101 compositor_loop_async_waiter_.Signal(); |
| 97 } | 102 } |
| 98 | 103 |
| 99 bool RendererGpuVideoDecoderFactories::CreateTextures( | 104 bool RendererGpuVideoDecoderFactories::CreateTextures( |
| 100 int32 count, const gfx::Size& size, | 105 int32 count, const gfx::Size& size, |
| 101 std::vector<uint32>* texture_ids, | 106 std::vector<uint32>* texture_ids, |
| 102 uint32 texture_target) { | 107 uint32 texture_target) { |
| 103 DCHECK(!message_loop_->BelongsToCurrentThread()); | 108 if (message_loop_->BelongsToCurrentThread()) { |
| 109 AsyncCreateTextures(count, size, texture_target); |
| 110 texture_ids->swap(created_textures_); |
| 111 compositor_loop_async_waiter_.Reset(); |
| 112 return true; |
| 113 } |
| 104 message_loop_->PostTask(FROM_HERE, base::Bind( | 114 message_loop_->PostTask(FROM_HERE, base::Bind( |
| 105 &RendererGpuVideoDecoderFactories::AsyncCreateTextures, this, | 115 &RendererGpuVideoDecoderFactories::AsyncCreateTextures, this, |
| 106 count, size, texture_target)); | 116 count, size, texture_target)); |
| 107 | 117 |
| 108 base::WaitableEvent* objects[] = {&aborted_waiter_, | 118 base::WaitableEvent* objects[] = {&aborted_waiter_, |
| 109 &compositor_loop_async_waiter_}; | 119 &compositor_loop_async_waiter_}; |
| 110 if (base::WaitableEvent::WaitMany(objects, arraysize(objects)) == 0) | 120 if (base::WaitableEvent::WaitMany(objects, arraysize(objects)) == 0) |
| 111 return false; | 121 return false; |
| 112 texture_ids->swap(created_textures_); | 122 texture_ids->swap(created_textures_); |
| 113 return true; | 123 return true; |
| (...skipping 26 matching lines...) Expand all Loading... |
| 140 } | 150 } |
| 141 // We need a glFlush here to guarantee the decoder (in the GPU process) can | 151 // We need a glFlush here to guarantee the decoder (in the GPU process) can |
| 142 // use the texture ids we return here. Since textures are expected to be | 152 // use the texture ids we return here. Since textures are expected to be |
| 143 // reused, this should not be unacceptably expensive. | 153 // reused, this should not be unacceptably expensive. |
| 144 gles2->Flush(); | 154 gles2->Flush(); |
| 145 DCHECK_EQ(gles2->GetError(), static_cast<GLenum>(GL_NO_ERROR)); | 155 DCHECK_EQ(gles2->GetError(), static_cast<GLenum>(GL_NO_ERROR)); |
| 146 compositor_loop_async_waiter_.Signal(); | 156 compositor_loop_async_waiter_.Signal(); |
| 147 } | 157 } |
| 148 | 158 |
| 149 void RendererGpuVideoDecoderFactories::DeleteTexture(uint32 texture_id) { | 159 void RendererGpuVideoDecoderFactories::DeleteTexture(uint32 texture_id) { |
| 150 DCHECK(!message_loop_->BelongsToCurrentThread()); | 160 if (message_loop_->BelongsToCurrentThread()) { |
| 161 AsyncDeleteTexture(texture_id); |
| 162 return; |
| 163 } |
| 151 message_loop_->PostTask(FROM_HERE, base::Bind( | 164 message_loop_->PostTask(FROM_HERE, base::Bind( |
| 152 &RendererGpuVideoDecoderFactories::AsyncDeleteTexture, this, texture_id)); | 165 &RendererGpuVideoDecoderFactories::AsyncDeleteTexture, this, texture_id)); |
| 153 } | 166 } |
| 154 | 167 |
| 155 void RendererGpuVideoDecoderFactories::AsyncDeleteTexture(uint32 texture_id) { | 168 void RendererGpuVideoDecoderFactories::AsyncDeleteTexture(uint32 texture_id) { |
| 156 DCHECK(message_loop_->BelongsToCurrentThread()); | 169 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 157 if (!context_.get()) | 170 if (!context_.get()) |
| 158 return; | 171 return; |
| 159 | 172 |
| 160 gpu::gles2::GLES2Implementation* gles2 = context_->GetImplementation(); | 173 gpu::gles2::GLES2Implementation* gles2 = context_->GetImplementation(); |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 214 gles2->ReadPixels(0, 0, size.width(), size.height(), GL_BGRA_EXT, | 227 gles2->ReadPixels(0, 0, size.width(), size.height(), GL_BGRA_EXT, |
| 215 GL_UNSIGNED_BYTE, read_pixels_bitmap_.pixelRef()->pixels()); | 228 GL_UNSIGNED_BYTE, read_pixels_bitmap_.pixelRef()->pixels()); |
| 216 gles2->DeleteFramebuffers(1, &fb); | 229 gles2->DeleteFramebuffers(1, &fb); |
| 217 gles2->DeleteTextures(1, &tmp_texture); | 230 gles2->DeleteTextures(1, &tmp_texture); |
| 218 DCHECK_EQ(gles2->GetError(), static_cast<GLenum>(GL_NO_ERROR)); | 231 DCHECK_EQ(gles2->GetError(), static_cast<GLenum>(GL_NO_ERROR)); |
| 219 compositor_loop_async_waiter_.Signal(); | 232 compositor_loop_async_waiter_.Signal(); |
| 220 } | 233 } |
| 221 | 234 |
| 222 base::SharedMemory* RendererGpuVideoDecoderFactories::CreateSharedMemory( | 235 base::SharedMemory* RendererGpuVideoDecoderFactories::CreateSharedMemory( |
| 223 size_t size) { | 236 size_t size) { |
| 224 DCHECK_NE(base::MessageLoop::current(), | 237 if (base::MessageLoop::current() == ChildThread::current()->message_loop()) { |
| 225 ChildThread::current()->message_loop()); | 238 return ChildThread::current()->AllocateSharedMemory(size); |
| 239 } |
| 226 ChildThread::current()->message_loop()->PostTask(FROM_HERE, base::Bind( | 240 ChildThread::current()->message_loop()->PostTask(FROM_HERE, base::Bind( |
| 227 &RendererGpuVideoDecoderFactories::AsyncCreateSharedMemory, this, | 241 &RendererGpuVideoDecoderFactories::AsyncCreateSharedMemory, this, |
| 228 size)); | 242 size)); |
| 229 | 243 |
| 230 base::WaitableEvent* objects[] = {&aborted_waiter_, | 244 base::WaitableEvent* objects[] = {&aborted_waiter_, |
| 231 &render_thread_async_waiter_}; | 245 &render_thread_async_waiter_}; |
| 232 if (base::WaitableEvent::WaitMany(objects, arraysize(objects)) == 0) | 246 if (base::WaitableEvent::WaitMany(objects, arraysize(objects)) == 0) |
| 233 return NULL; | 247 return NULL; |
| 234 return shared_memory_segment_.release(); | 248 return shared_memory_segment_.release(); |
| 235 } | 249 } |
| (...skipping 20 matching lines...) Expand all Loading... |
| 256 return aborted_waiter_.IsSignaled(); | 270 return aborted_waiter_.IsSignaled(); |
| 257 } | 271 } |
| 258 | 272 |
| 259 void RendererGpuVideoDecoderFactories::AsyncDestroyVideoDecodeAccelerator() { | 273 void RendererGpuVideoDecoderFactories::AsyncDestroyVideoDecodeAccelerator() { |
| 260 // OK to release because Destroy() will delete the VDA instance. | 274 // OK to release because Destroy() will delete the VDA instance. |
| 261 if (vda_) | 275 if (vda_) |
| 262 vda_.release()->Destroy(); | 276 vda_.release()->Destroy(); |
| 263 } | 277 } |
| 264 | 278 |
| 265 } // namespace content | 279 } // namespace content |
| OLD | NEW |