| 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" |
| 11 #include "base/synchronization/waitable_event.h" | 11 #include "base/synchronization/waitable_event.h" |
| 12 #include "content/common/child_thread.h" | 12 #include "content/common/child_thread.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 "gpu/command_buffer/client/gles2_implementation.h" | 15 #include "gpu/command_buffer/client/gles2_implementation.h" |
| 16 #include "gpu/ipc/command_buffer_proxy.h" | 16 #include "gpu/ipc/command_buffer_proxy.h" |
| 17 | 17 |
| 18 RendererGpuVideoDecoderFactories::~RendererGpuVideoDecoderFactories() {} | 18 RendererGpuVideoDecoderFactories::~RendererGpuVideoDecoderFactories() {} |
| 19 RendererGpuVideoDecoderFactories::RendererGpuVideoDecoderFactories( | 19 RendererGpuVideoDecoderFactories::RendererGpuVideoDecoderFactories( |
| 20 GpuChannelHost* gpu_channel_host, MessageLoop* message_loop, | 20 GpuChannelHost* gpu_channel_host, |
| 21 const scoped_refptr<base::MessageLoopProxy>& message_loop, |
| 21 const base::WeakPtr<WebGraphicsContext3DCommandBufferImpl>& context) | 22 const base::WeakPtr<WebGraphicsContext3DCommandBufferImpl>& context) |
| 22 : message_loop_(message_loop), | 23 : message_loop_(message_loop), |
| 23 gpu_channel_host_(gpu_channel_host), | 24 gpu_channel_host_(gpu_channel_host), |
| 24 context_(context) { | 25 context_(context) { |
| 25 DCHECK(context_); | 26 DCHECK(context_); |
| 26 context_->DetachFromThread(); | 27 context_->DetachFromThread(); |
| 27 if (MessageLoop::current() == message_loop_) { | 28 if (message_loop_->BelongsToCurrentThread()) { |
| 28 AsyncGetContext(NULL); | 29 AsyncGetContext(NULL); |
| 29 return; | 30 return; |
| 30 } | 31 } |
| 31 // Threaded compositor requires us to wait for the context to be acquired. | 32 // Threaded compositor requires us to wait for the context to be acquired. |
| 32 base::WaitableEvent waiter(false, false); | 33 base::WaitableEvent waiter(false, false); |
| 33 message_loop_->PostTask(FROM_HERE, base::Bind( | 34 message_loop_->PostTask(FROM_HERE, base::Bind( |
| 34 &RendererGpuVideoDecoderFactories::AsyncGetContext, | 35 &RendererGpuVideoDecoderFactories::AsyncGetContext, |
| 35 // Unretained to avoid ref/deref'ing |*this|, which is not yet stored in a | 36 // Unretained to avoid ref/deref'ing |*this|, which is not yet stored in a |
| 36 // scoped_refptr. Safe because the Wait() below keeps us alive until this | 37 // scoped_refptr. Safe because the Wait() below keeps us alive until this |
| 37 // task completes. | 38 // task completes. |
| 38 base::Unretained(this), &waiter)); | 39 base::Unretained(this), &waiter)); |
| 39 waiter.Wait(); | 40 waiter.Wait(); |
| 40 } | 41 } |
| 41 | 42 |
| 42 void RendererGpuVideoDecoderFactories::AsyncGetContext( | 43 void RendererGpuVideoDecoderFactories::AsyncGetContext( |
| 43 base::WaitableEvent* waiter) { | 44 base::WaitableEvent* waiter) { |
| 44 if (context_) | 45 if (context_) |
| 45 context_->makeContextCurrent(); | 46 context_->makeContextCurrent(); |
| 46 if (waiter) | 47 if (waiter) |
| 47 waiter->Signal(); | 48 waiter->Signal(); |
| 48 } | 49 } |
| 49 | 50 |
| 50 media::VideoDecodeAccelerator* | 51 media::VideoDecodeAccelerator* |
| 51 RendererGpuVideoDecoderFactories::CreateVideoDecodeAccelerator( | 52 RendererGpuVideoDecoderFactories::CreateVideoDecodeAccelerator( |
| 52 media::VideoCodecProfile profile, | 53 media::VideoCodecProfile profile, |
| 53 media::VideoDecodeAccelerator::Client* client) { | 54 media::VideoDecodeAccelerator::Client* client) { |
| 54 DCHECK_NE(MessageLoop::current(), message_loop_); | 55 DCHECK(!message_loop_->BelongsToCurrentThread()); |
| 55 media::VideoDecodeAccelerator* vda = NULL; | 56 media::VideoDecodeAccelerator* vda = NULL; |
| 56 base::WaitableEvent waiter(false, false); | 57 base::WaitableEvent waiter(false, false); |
| 57 message_loop_->PostTask(FROM_HERE, base::Bind( | 58 message_loop_->PostTask(FROM_HERE, base::Bind( |
| 58 &RendererGpuVideoDecoderFactories::AsyncCreateVideoDecodeAccelerator, | 59 &RendererGpuVideoDecoderFactories::AsyncCreateVideoDecodeAccelerator, |
| 59 this, profile, client, &vda, &waiter)); | 60 this, profile, client, &vda, &waiter)); |
| 60 waiter.Wait(); | 61 waiter.Wait(); |
| 61 return vda; | 62 return vda; |
| 62 } | 63 } |
| 63 | 64 |
| 64 void RendererGpuVideoDecoderFactories::AsyncCreateVideoDecodeAccelerator( | 65 void RendererGpuVideoDecoderFactories::AsyncCreateVideoDecodeAccelerator( |
| 65 media::VideoCodecProfile profile, | 66 media::VideoCodecProfile profile, |
| 66 media::VideoDecodeAccelerator::Client* client, | 67 media::VideoDecodeAccelerator::Client* client, |
| 67 media::VideoDecodeAccelerator** vda, | 68 media::VideoDecodeAccelerator** vda, |
| 68 base::WaitableEvent* waiter) { | 69 base::WaitableEvent* waiter) { |
| 69 DCHECK_EQ(MessageLoop::current(), message_loop_); | 70 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 70 if (context_) { | 71 if (context_) { |
| 71 *vda = gpu_channel_host_->CreateVideoDecoder( | 72 *vda = gpu_channel_host_->CreateVideoDecoder( |
| 72 context_->GetCommandBufferProxy()->GetRouteID(), | 73 context_->GetCommandBufferProxy()->GetRouteID(), |
| 73 profile, client); | 74 profile, client); |
| 74 } else { | 75 } else { |
| 75 *vda = NULL; | 76 *vda = NULL; |
| 76 } | 77 } |
| 77 waiter->Signal(); | 78 waiter->Signal(); |
| 78 } | 79 } |
| 79 | 80 |
| 80 bool RendererGpuVideoDecoderFactories::CreateTextures( | 81 bool RendererGpuVideoDecoderFactories::CreateTextures( |
| 81 int32 count, const gfx::Size& size, | 82 int32 count, const gfx::Size& size, |
| 82 std::vector<uint32>* texture_ids, | 83 std::vector<uint32>* texture_ids, |
| 83 uint32 texture_target) { | 84 uint32 texture_target) { |
| 84 DCHECK_NE(MessageLoop::current(), message_loop_); | 85 DCHECK(!message_loop_->BelongsToCurrentThread()); |
| 85 bool success = false; | 86 bool success = false; |
| 86 base::WaitableEvent waiter(false, false); | 87 base::WaitableEvent waiter(false, false); |
| 87 message_loop_->PostTask(FROM_HERE, base::Bind( | 88 message_loop_->PostTask(FROM_HERE, base::Bind( |
| 88 &RendererGpuVideoDecoderFactories::AsyncCreateTextures, this, | 89 &RendererGpuVideoDecoderFactories::AsyncCreateTextures, this, |
| 89 count, size, texture_ids, texture_target, &success, &waiter)); | 90 count, size, texture_ids, texture_target, &success, &waiter)); |
| 90 waiter.Wait(); | 91 waiter.Wait(); |
| 91 return success; | 92 return success; |
| 92 } | 93 } |
| 93 | 94 |
| 94 void RendererGpuVideoDecoderFactories::AsyncCreateTextures( | 95 void RendererGpuVideoDecoderFactories::AsyncCreateTextures( |
| 95 int32 count, const gfx::Size& size, std::vector<uint32>* texture_ids, | 96 int32 count, const gfx::Size& size, std::vector<uint32>* texture_ids, |
| 96 uint32 texture_target, bool* success, base::WaitableEvent* waiter) { | 97 uint32 texture_target, bool* success, base::WaitableEvent* waiter) { |
| 97 DCHECK_EQ(MessageLoop::current(), message_loop_); | 98 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 98 DCHECK(texture_target); | 99 DCHECK(texture_target); |
| 99 if (!context_) { | 100 if (!context_) { |
| 100 *success = false; | 101 *success = false; |
| 101 waiter->Signal(); | 102 waiter->Signal(); |
| 102 return; | 103 return; |
| 103 } | 104 } |
| 104 gpu::gles2::GLES2Implementation* gles2 = context_->GetImplementation(); | 105 gpu::gles2::GLES2Implementation* gles2 = context_->GetImplementation(); |
| 105 texture_ids->resize(count); | 106 texture_ids->resize(count); |
| 106 gles2->GenTextures(count, &texture_ids->at(0)); | 107 gles2->GenTextures(count, &texture_ids->at(0)); |
| 107 for (int i = 0; i < count; ++i) { | 108 for (int i = 0; i < count; ++i) { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 120 // We need a glFlush here to guarantee the decoder (in the GPU process) can | 121 // We need a glFlush here to guarantee the decoder (in the GPU process) can |
| 121 // use the texture ids we return here. Since textures are expected to be | 122 // use the texture ids we return here. Since textures are expected to be |
| 122 // reused, this should not be unacceptably expensive. | 123 // reused, this should not be unacceptably expensive. |
| 123 gles2->Flush(); | 124 gles2->Flush(); |
| 124 DCHECK_EQ(gles2->GetError(), static_cast<GLenum>(GL_NO_ERROR)); | 125 DCHECK_EQ(gles2->GetError(), static_cast<GLenum>(GL_NO_ERROR)); |
| 125 *success = true; | 126 *success = true; |
| 126 waiter->Signal(); | 127 waiter->Signal(); |
| 127 } | 128 } |
| 128 | 129 |
| 129 void RendererGpuVideoDecoderFactories::DeleteTexture(uint32 texture_id) { | 130 void RendererGpuVideoDecoderFactories::DeleteTexture(uint32 texture_id) { |
| 130 DCHECK_NE(MessageLoop::current(), message_loop_); | 131 DCHECK(!message_loop_->BelongsToCurrentThread()); |
| 131 message_loop_->PostTask(FROM_HERE, base::Bind( | 132 message_loop_->PostTask(FROM_HERE, base::Bind( |
| 132 &RendererGpuVideoDecoderFactories::AsyncDeleteTexture, this, texture_id)); | 133 &RendererGpuVideoDecoderFactories::AsyncDeleteTexture, this, texture_id)); |
| 133 } | 134 } |
| 134 | 135 |
| 135 void RendererGpuVideoDecoderFactories::AsyncDeleteTexture(uint32 texture_id) { | 136 void RendererGpuVideoDecoderFactories::AsyncDeleteTexture(uint32 texture_id) { |
| 136 DCHECK_EQ(MessageLoop::current(), message_loop_); | 137 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 137 if (!context_) | 138 if (!context_) |
| 138 return; | 139 return; |
| 139 gpu::gles2::GLES2Implementation* gles2 = context_->GetImplementation(); | 140 gpu::gles2::GLES2Implementation* gles2 = context_->GetImplementation(); |
| 140 gles2->DeleteTextures(1, &texture_id); | 141 gles2->DeleteTextures(1, &texture_id); |
| 141 DCHECK_EQ(gles2->GetError(), static_cast<GLenum>(GL_NO_ERROR)); | 142 DCHECK_EQ(gles2->GetError(), static_cast<GLenum>(GL_NO_ERROR)); |
| 142 } | 143 } |
| 143 | 144 |
| 144 base::SharedMemory* RendererGpuVideoDecoderFactories::CreateSharedMemory( | 145 base::SharedMemory* RendererGpuVideoDecoderFactories::CreateSharedMemory( |
| 145 size_t size) { | 146 size_t size) { |
| 146 DCHECK_NE(MessageLoop::current(), ChildThread::current()->message_loop()); | 147 DCHECK_NE(MessageLoop::current(), ChildThread::current()->message_loop()); |
| 147 base::SharedMemory* shm = NULL; | 148 base::SharedMemory* shm = NULL; |
| 148 base::WaitableEvent waiter(false, false); | 149 base::WaitableEvent waiter(false, false); |
| 149 ChildThread::current()->message_loop()->PostTask(FROM_HERE, base::Bind( | 150 ChildThread::current()->message_loop()->PostTask(FROM_HERE, base::Bind( |
| 150 &RendererGpuVideoDecoderFactories::AsyncCreateSharedMemory, this, | 151 &RendererGpuVideoDecoderFactories::AsyncCreateSharedMemory, this, |
| 151 size, &shm, &waiter)); | 152 size, &shm, &waiter)); |
| 152 waiter.Wait(); | 153 waiter.Wait(); |
| 153 return shm; | 154 return shm; |
| 154 } | 155 } |
| 155 | 156 |
| 156 void RendererGpuVideoDecoderFactories::AsyncCreateSharedMemory( | 157 void RendererGpuVideoDecoderFactories::AsyncCreateSharedMemory( |
| 157 size_t size, base::SharedMemory** shm, base::WaitableEvent* waiter) { | 158 size_t size, base::SharedMemory** shm, base::WaitableEvent* waiter) { |
| 158 DCHECK_EQ(MessageLoop::current(), ChildThread::current()->message_loop()); | 159 DCHECK_EQ(MessageLoop::current(), ChildThread::current()->message_loop()); |
| 159 *shm = ChildThread::current()->AllocateSharedMemory(size); | 160 *shm = ChildThread::current()->AllocateSharedMemory(size); |
| 160 waiter->Signal(); | 161 waiter->Signal(); |
| 161 } | 162 } |
| OLD | NEW |