| 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 12 matching lines...) Expand all Loading... |
| 23 const scoped_refptr<base::MessageLoopProxy>& compositor_message_loop, | 23 const scoped_refptr<base::MessageLoopProxy>& compositor_message_loop, |
| 24 WebGraphicsContext3DCommandBufferImpl* context) | 24 WebGraphicsContext3DCommandBufferImpl* context) |
| 25 : compositor_message_loop_(compositor_message_loop), | 25 : compositor_message_loop_(compositor_message_loop), |
| 26 main_message_loop_(base::MessageLoopProxy::current()), | 26 main_message_loop_(base::MessageLoopProxy::current()), |
| 27 gpu_channel_host_(gpu_channel_host), | 27 gpu_channel_host_(gpu_channel_host), |
| 28 aborted_waiter_(true, false), | 28 aborted_waiter_(true, false), |
| 29 compositor_loop_async_waiter_(false, false), | 29 compositor_loop_async_waiter_(false, false), |
| 30 render_thread_async_waiter_(false, false) { | 30 render_thread_async_waiter_(false, false) { |
| 31 if (compositor_message_loop_->BelongsToCurrentThread()) { | 31 if (compositor_message_loop_->BelongsToCurrentThread()) { |
| 32 AsyncGetContext(context); | 32 AsyncGetContext(context); |
| 33 compositor_loop_async_waiter_.Reset(); |
| 33 return; | 34 return; |
| 34 } | 35 } |
| 35 // Threaded compositor requires us to wait for the context to be acquired. | 36 // Threaded compositor requires us to wait for the context to be acquired. |
| 36 compositor_message_loop_->PostTask(FROM_HERE, base::Bind( | 37 compositor_message_loop_->PostTask(FROM_HERE, base::Bind( |
| 37 &RendererGpuVideoDecoderFactories::AsyncGetContext, | 38 &RendererGpuVideoDecoderFactories::AsyncGetContext, |
| 38 // Unretained to avoid ref/deref'ing |*this|, which is not yet stored in a | 39 // Unretained to avoid ref/deref'ing |*this|, which is not yet stored in a |
| 39 // scoped_refptr. Safe because the Wait() below keeps us alive until this | 40 // scoped_refptr. Safe because the Wait() below keeps us alive until this |
| 40 // task completes. | 41 // task completes. |
| 41 base::Unretained(this), | 42 base::Unretained(this), |
| 42 // OK to pass raw because the pointee is only deleted on the compositor | 43 // OK to pass raw because the pointee is only deleted on the compositor |
| (...skipping 14 matching lines...) Expand all Loading... |
| 57 context_->insertEventMarkerEXT("GpuVDAContext3D"); | 58 context_->insertEventMarkerEXT("GpuVDAContext3D"); |
| 58 } | 59 } |
| 59 } | 60 } |
| 60 compositor_loop_async_waiter_.Signal(); | 61 compositor_loop_async_waiter_.Signal(); |
| 61 } | 62 } |
| 62 | 63 |
| 63 media::VideoDecodeAccelerator* | 64 media::VideoDecodeAccelerator* |
| 64 RendererGpuVideoDecoderFactories::CreateVideoDecodeAccelerator( | 65 RendererGpuVideoDecoderFactories::CreateVideoDecodeAccelerator( |
| 65 media::VideoCodecProfile profile, | 66 media::VideoCodecProfile profile, |
| 66 media::VideoDecodeAccelerator::Client* client) { | 67 media::VideoDecodeAccelerator::Client* client) { |
| 67 DCHECK(!compositor_message_loop_->BelongsToCurrentThread()); | 68 if (compositor_message_loop_->BelongsToCurrentThread()) { |
| 69 AsyncCreateVideoDecodeAccelerator(profile, client); |
| 70 compositor_loop_async_waiter_.Reset(); |
| 71 return vda_.release(); |
| 72 } |
| 68 // The VDA is returned in the vda_ member variable by the | 73 // The VDA is returned in the vda_ member variable by the |
| 69 // AsyncCreateVideoDecodeAccelerator() function. | 74 // AsyncCreateVideoDecodeAccelerator() function. |
| 70 compositor_message_loop_->PostTask(FROM_HERE, base::Bind( | 75 compositor_message_loop_->PostTask(FROM_HERE, base::Bind( |
| 71 &RendererGpuVideoDecoderFactories::AsyncCreateVideoDecodeAccelerator, | 76 &RendererGpuVideoDecoderFactories::AsyncCreateVideoDecodeAccelerator, |
| 72 this, profile, client)); | 77 this, profile, client)); |
| 73 | 78 |
| 74 base::WaitableEvent* objects[] = {&aborted_waiter_, | 79 base::WaitableEvent* objects[] = {&aborted_waiter_, |
| 75 &compositor_loop_async_waiter_}; | 80 &compositor_loop_async_waiter_}; |
| 76 if (base::WaitableEvent::WaitMany(objects, arraysize(objects)) == 0) { | 81 if (base::WaitableEvent::WaitMany(objects, arraysize(objects)) == 0) { |
| 77 // If we are aborting and the VDA is created by the | 82 // If we are aborting and the VDA is created by the |
| (...skipping 19 matching lines...) Expand all Loading... |
| 97 compositor_loop_async_waiter_.Signal(); | 102 compositor_loop_async_waiter_.Signal(); |
| 98 } | 103 } |
| 99 | 104 |
| 100 uint32 RendererGpuVideoDecoderFactories::CreateTextures( | 105 uint32 RendererGpuVideoDecoderFactories::CreateTextures( |
| 101 int32 count, const gfx::Size& size, | 106 int32 count, const gfx::Size& size, |
| 102 std::vector<uint32>* texture_ids, | 107 std::vector<uint32>* texture_ids, |
| 103 std::vector<gpu::Mailbox>* texture_mailboxes, | 108 std::vector<gpu::Mailbox>* texture_mailboxes, |
| 104 uint32 texture_target) { | 109 uint32 texture_target) { |
| 105 uint32 sync_point = 0; | 110 uint32 sync_point = 0; |
| 106 | 111 |
| 107 DCHECK(!compositor_message_loop_->BelongsToCurrentThread()); | 112 if (compositor_message_loop_->BelongsToCurrentThread()) { |
| 113 AsyncCreateTextures(count, size, texture_target, &sync_point); |
| 114 texture_ids->swap(created_textures_); |
| 115 texture_mailboxes->swap(created_texture_mailboxes_); |
| 116 compositor_loop_async_waiter_.Reset(); |
| 117 return sync_point; |
| 118 } |
| 108 compositor_message_loop_->PostTask(FROM_HERE, base::Bind( | 119 compositor_message_loop_->PostTask(FROM_HERE, base::Bind( |
| 109 &RendererGpuVideoDecoderFactories::AsyncCreateTextures, this, | 120 &RendererGpuVideoDecoderFactories::AsyncCreateTextures, this, |
| 110 count, size, texture_target, &sync_point)); | 121 count, size, texture_target, &sync_point)); |
| 111 | 122 |
| 112 base::WaitableEvent* objects[] = {&aborted_waiter_, | 123 base::WaitableEvent* objects[] = {&aborted_waiter_, |
| 113 &compositor_loop_async_waiter_}; | 124 &compositor_loop_async_waiter_}; |
| 114 if (base::WaitableEvent::WaitMany(objects, arraysize(objects)) == 0) | 125 if (base::WaitableEvent::WaitMany(objects, arraysize(objects)) == 0) |
| 115 return 0; | 126 return 0; |
| 116 texture_ids->swap(created_textures_); | 127 texture_ids->swap(created_textures_); |
| 117 texture_mailboxes->swap(created_texture_mailboxes_); | 128 texture_mailboxes->swap(created_texture_mailboxes_); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 153 // 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 |
| 154 // reused, this should not be unacceptably expensive. | 165 // reused, this should not be unacceptably expensive. |
| 155 gles2->Flush(); | 166 gles2->Flush(); |
| 156 DCHECK_EQ(gles2->GetError(), static_cast<GLenum>(GL_NO_ERROR)); | 167 DCHECK_EQ(gles2->GetError(), static_cast<GLenum>(GL_NO_ERROR)); |
| 157 | 168 |
| 158 *sync_point = gles2->InsertSyncPointCHROMIUM(); | 169 *sync_point = gles2->InsertSyncPointCHROMIUM(); |
| 159 compositor_loop_async_waiter_.Signal(); | 170 compositor_loop_async_waiter_.Signal(); |
| 160 } | 171 } |
| 161 | 172 |
| 162 void RendererGpuVideoDecoderFactories::DeleteTexture(uint32 texture_id) { | 173 void RendererGpuVideoDecoderFactories::DeleteTexture(uint32 texture_id) { |
| 163 DCHECK(!compositor_message_loop_->BelongsToCurrentThread()); | 174 if (compositor_message_loop_->BelongsToCurrentThread()) { |
| 175 AsyncDeleteTexture(texture_id); |
| 176 return; |
| 177 } |
| 164 compositor_message_loop_->PostTask(FROM_HERE, base::Bind( | 178 compositor_message_loop_->PostTask(FROM_HERE, base::Bind( |
| 165 &RendererGpuVideoDecoderFactories::AsyncDeleteTexture, this, texture_id)); | 179 &RendererGpuVideoDecoderFactories::AsyncDeleteTexture, this, texture_id)); |
| 166 } | 180 } |
| 167 | 181 |
| 168 void RendererGpuVideoDecoderFactories::AsyncDeleteTexture(uint32 texture_id) { | 182 void RendererGpuVideoDecoderFactories::AsyncDeleteTexture(uint32 texture_id) { |
| 169 DCHECK(compositor_message_loop_->BelongsToCurrentThread()); | 183 DCHECK(compositor_message_loop_->BelongsToCurrentThread()); |
| 170 if (!context_.get()) | 184 if (!context_.get()) |
| 171 return; | 185 return; |
| 172 | 186 |
| 173 gpu::gles2::GLES2Implementation* gles2 = context_->GetImplementation(); | 187 gpu::gles2::GLES2Implementation* gles2 = context_->GetImplementation(); |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 254 gles2->ReadPixels(0, 0, size.width(), size.height(), GL_BGRA_EXT, | 268 gles2->ReadPixels(0, 0, size.width(), size.height(), GL_BGRA_EXT, |
| 255 GL_UNSIGNED_BYTE, read_pixels_bitmap_.pixelRef()->pixels()); | 269 GL_UNSIGNED_BYTE, read_pixels_bitmap_.pixelRef()->pixels()); |
| 256 gles2->DeleteFramebuffers(1, &fb); | 270 gles2->DeleteFramebuffers(1, &fb); |
| 257 gles2->DeleteTextures(1, &tmp_texture); | 271 gles2->DeleteTextures(1, &tmp_texture); |
| 258 DCHECK_EQ(gles2->GetError(), static_cast<GLenum>(GL_NO_ERROR)); | 272 DCHECK_EQ(gles2->GetError(), static_cast<GLenum>(GL_NO_ERROR)); |
| 259 compositor_loop_async_waiter_.Signal(); | 273 compositor_loop_async_waiter_.Signal(); |
| 260 } | 274 } |
| 261 | 275 |
| 262 base::SharedMemory* RendererGpuVideoDecoderFactories::CreateSharedMemory( | 276 base::SharedMemory* RendererGpuVideoDecoderFactories::CreateSharedMemory( |
| 263 size_t size) { | 277 size_t size) { |
| 264 DCHECK(!main_message_loop_->BelongsToCurrentThread()); | 278 if (main_message_loop_->BelongsToCurrentThread()) { |
| 279 return ChildThread::current()->AllocateSharedMemory(size); |
| 280 } |
| 265 main_message_loop_->PostTask(FROM_HERE, base::Bind( | 281 main_message_loop_->PostTask(FROM_HERE, base::Bind( |
| 266 &RendererGpuVideoDecoderFactories::AsyncCreateSharedMemory, this, | 282 &RendererGpuVideoDecoderFactories::AsyncCreateSharedMemory, this, |
| 267 size)); | 283 size)); |
| 268 | 284 |
| 269 base::WaitableEvent* objects[] = {&aborted_waiter_, | 285 base::WaitableEvent* objects[] = {&aborted_waiter_, |
| 270 &render_thread_async_waiter_}; | 286 &render_thread_async_waiter_}; |
| 271 if (base::WaitableEvent::WaitMany(objects, arraysize(objects)) == 0) | 287 if (base::WaitableEvent::WaitMany(objects, arraysize(objects)) == 0) |
| 272 return NULL; | 288 return NULL; |
| 273 return shared_memory_segment_.release(); | 289 return shared_memory_segment_.release(); |
| 274 } | 290 } |
| (...skipping 20 matching lines...) Expand all Loading... |
| 295 return aborted_waiter_.IsSignaled(); | 311 return aborted_waiter_.IsSignaled(); |
| 296 } | 312 } |
| 297 | 313 |
| 298 void RendererGpuVideoDecoderFactories::AsyncDestroyVideoDecodeAccelerator() { | 314 void RendererGpuVideoDecoderFactories::AsyncDestroyVideoDecodeAccelerator() { |
| 299 // OK to release because Destroy() will delete the VDA instance. | 315 // OK to release because Destroy() will delete the VDA instance. |
| 300 if (vda_) | 316 if (vda_) |
| 301 vda_.release()->Destroy(); | 317 vda_.release()->Destroy(); |
| 302 } | 318 } |
| 303 | 319 |
| 304 } // namespace content | 320 } // namespace content |
| OLD | NEW |