| Index: content/renderer/media/renderer_gpu_video_accelerator_factories.cc
|
| ===================================================================
|
| --- content/renderer/media/renderer_gpu_video_accelerator_factories.cc (revision 218293)
|
| +++ content/renderer/media/renderer_gpu_video_accelerator_factories.cc (working copy)
|
| @@ -1,428 +0,0 @@
|
| -// Copyright 2013 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -#include "content/renderer/media/renderer_gpu_video_accelerator_factories.h"
|
| -
|
| -#include <GLES2/gl2.h>
|
| -#include <GLES2/gl2ext.h>
|
| -
|
| -#include "base/bind.h"
|
| -#include "content/child/child_thread.h"
|
| -#include "content/common/gpu/client/gpu_channel_host.h"
|
| -#include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h"
|
| -#include "gpu/command_buffer/client/gles2_implementation.h"
|
| -#include "gpu/ipc/command_buffer_proxy.h"
|
| -#include "third_party/skia/include/core/SkPixelRef.h"
|
| -
|
| -namespace content {
|
| -
|
| -RendererGpuVideoAcceleratorFactories::~RendererGpuVideoAcceleratorFactories() {}
|
| -RendererGpuVideoAcceleratorFactories::RendererGpuVideoAcceleratorFactories(
|
| - GpuChannelHost* gpu_channel_host,
|
| - const scoped_refptr<base::MessageLoopProxy>& message_loop,
|
| - WebGraphicsContext3DCommandBufferImpl* context)
|
| - : message_loop_(message_loop),
|
| - main_message_loop_(base::MessageLoopProxy::current()),
|
| - gpu_channel_host_(gpu_channel_host),
|
| - aborted_waiter_(true, false),
|
| - message_loop_async_waiter_(false, false),
|
| - render_thread_async_waiter_(false, false) {
|
| - // |context| is only required to support HW-accelerated decode.
|
| - if (!context)
|
| - return;
|
| -
|
| - if (message_loop_->BelongsToCurrentThread()) {
|
| - AsyncGetContext(context);
|
| - message_loop_async_waiter_.Reset();
|
| - return;
|
| - }
|
| - // Wait for the context to be acquired.
|
| - message_loop_->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&RendererGpuVideoAcceleratorFactories::AsyncGetContext,
|
| - // Unretained to avoid ref/deref'ing |*this|, which is not yet
|
| - // stored in a scoped_refptr. Safe because the Wait() below
|
| - // keeps us alive until this task completes.
|
| - base::Unretained(this),
|
| - // OK to pass raw because the pointee is only deleted on the
|
| - // compositor thread, and only as the result of a PostTask from
|
| - // the render thread which can only happen after this function
|
| - // returns, so our PostTask will run first.
|
| - context));
|
| - message_loop_async_waiter_.Wait();
|
| -}
|
| -
|
| -RendererGpuVideoAcceleratorFactories::RendererGpuVideoAcceleratorFactories()
|
| - : aborted_waiter_(true, false),
|
| - message_loop_async_waiter_(false, false),
|
| - render_thread_async_waiter_(false, false) {}
|
| -
|
| -void RendererGpuVideoAcceleratorFactories::AsyncGetContext(
|
| - WebGraphicsContext3DCommandBufferImpl* context) {
|
| - context_ = context->AsWeakPtr();
|
| - if (context_.get()) {
|
| - if (context_->makeContextCurrent()) {
|
| - // Called once per media player, but is a no-op after the first one in
|
| - // each renderer.
|
| - context_->insertEventMarkerEXT("GpuVDAContext3D");
|
| - }
|
| - }
|
| - message_loop_async_waiter_.Signal();
|
| -}
|
| -
|
| -scoped_ptr<media::VideoDecodeAccelerator>
|
| -RendererGpuVideoAcceleratorFactories::CreateVideoDecodeAccelerator(
|
| - media::VideoCodecProfile profile,
|
| - media::VideoDecodeAccelerator::Client* client) {
|
| - if (message_loop_->BelongsToCurrentThread()) {
|
| - AsyncCreateVideoDecodeAccelerator(profile, client);
|
| - message_loop_async_waiter_.Reset();
|
| - return vda_.Pass();
|
| - }
|
| - // The VDA is returned in the vda_ member variable by the
|
| - // AsyncCreateVideoDecodeAccelerator() function.
|
| - message_loop_->PostTask(FROM_HERE,
|
| - base::Bind(&RendererGpuVideoAcceleratorFactories::
|
| - AsyncCreateVideoDecodeAccelerator,
|
| - this,
|
| - profile,
|
| - client));
|
| -
|
| - base::WaitableEvent* objects[] = {&aborted_waiter_,
|
| - &message_loop_async_waiter_};
|
| - if (base::WaitableEvent::WaitMany(objects, arraysize(objects)) == 0) {
|
| - // If we are aborting and the VDA is created by the
|
| - // AsyncCreateVideoDecodeAccelerator() function later we need to ensure
|
| - // that it is destroyed on the same thread.
|
| - message_loop_->PostTask(FROM_HERE,
|
| - base::Bind(&RendererGpuVideoAcceleratorFactories::
|
| - AsyncDestroyVideoDecodeAccelerator,
|
| - this));
|
| - return scoped_ptr<media::VideoDecodeAccelerator>();
|
| - }
|
| - return vda_.Pass();
|
| -}
|
| -
|
| -scoped_ptr<media::VideoEncodeAccelerator>
|
| -RendererGpuVideoAcceleratorFactories::CreateVideoEncodeAccelerator(
|
| - media::VideoEncodeAccelerator::Client* client) {
|
| - if (message_loop_->BelongsToCurrentThread()) {
|
| - AsyncCreateVideoEncodeAccelerator(client);
|
| - message_loop_async_waiter_.Reset();
|
| - return vea_.Pass();
|
| - }
|
| - // The VEA is returned in the vea_ member variable by the
|
| - // AsyncCreateVideoEncodeAccelerator() function.
|
| - message_loop_->PostTask(FROM_HERE,
|
| - base::Bind(&RendererGpuVideoAcceleratorFactories::
|
| - AsyncCreateVideoEncodeAccelerator,
|
| - this,
|
| - client));
|
| -
|
| - base::WaitableEvent* objects[] = {&aborted_waiter_,
|
| - &message_loop_async_waiter_};
|
| - if (base::WaitableEvent::WaitMany(objects, arraysize(objects)) == 0) {
|
| - // If we are aborting and the VDA is created by the
|
| - // AsyncCreateVideoEncodeAccelerator() function later we need to ensure
|
| - // that it is destroyed on the same thread.
|
| - message_loop_->PostTask(FROM_HERE,
|
| - base::Bind(&RendererGpuVideoAcceleratorFactories::
|
| - AsyncDestroyVideoEncodeAccelerator,
|
| - this));
|
| - return scoped_ptr<media::VideoEncodeAccelerator>();
|
| - }
|
| - return vea_.Pass();
|
| -}
|
| -
|
| -void RendererGpuVideoAcceleratorFactories::AsyncCreateVideoDecodeAccelerator(
|
| - media::VideoCodecProfile profile,
|
| - media::VideoDecodeAccelerator::Client* client) {
|
| - DCHECK(message_loop_->BelongsToCurrentThread());
|
| -
|
| - if (context_.get() && context_->GetCommandBufferProxy()) {
|
| - vda_ = gpu_channel_host_->CreateVideoDecoder(
|
| - context_->GetCommandBufferProxy()->GetRouteID(), profile, client);
|
| - }
|
| - message_loop_async_waiter_.Signal();
|
| -}
|
| -
|
| -void RendererGpuVideoAcceleratorFactories::AsyncCreateVideoEncodeAccelerator(
|
| - media::VideoEncodeAccelerator::Client* client) {
|
| - DCHECK(message_loop_->BelongsToCurrentThread());
|
| -
|
| - vea_ = gpu_channel_host_->CreateVideoEncoder(client).Pass();
|
| - message_loop_async_waiter_.Signal();
|
| -}
|
| -
|
| -uint32 RendererGpuVideoAcceleratorFactories::CreateTextures(
|
| - int32 count,
|
| - const gfx::Size& size,
|
| - std::vector<uint32>* texture_ids,
|
| - std::vector<gpu::Mailbox>* texture_mailboxes,
|
| - uint32 texture_target) {
|
| - uint32 sync_point = 0;
|
| -
|
| - if (message_loop_->BelongsToCurrentThread()) {
|
| - AsyncCreateTextures(count, size, texture_target, &sync_point);
|
| - texture_ids->swap(created_textures_);
|
| - texture_mailboxes->swap(created_texture_mailboxes_);
|
| - message_loop_async_waiter_.Reset();
|
| - return sync_point;
|
| - }
|
| - message_loop_->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&RendererGpuVideoAcceleratorFactories::AsyncCreateTextures,
|
| - this,
|
| - count,
|
| - size,
|
| - texture_target,
|
| - &sync_point));
|
| -
|
| - base::WaitableEvent* objects[] = {&aborted_waiter_,
|
| - &message_loop_async_waiter_};
|
| - if (base::WaitableEvent::WaitMany(objects, arraysize(objects)) == 0)
|
| - return 0;
|
| - texture_ids->swap(created_textures_);
|
| - texture_mailboxes->swap(created_texture_mailboxes_);
|
| - return sync_point;
|
| -}
|
| -
|
| -void RendererGpuVideoAcceleratorFactories::AsyncCreateTextures(
|
| - int32 count,
|
| - const gfx::Size& size,
|
| - uint32 texture_target,
|
| - uint32* sync_point) {
|
| - DCHECK(message_loop_->BelongsToCurrentThread());
|
| - DCHECK(texture_target);
|
| -
|
| - if (!context_.get()) {
|
| - message_loop_async_waiter_.Signal();
|
| - return;
|
| - }
|
| - gpu::gles2::GLES2Implementation* gles2 = context_->GetImplementation();
|
| - created_textures_.resize(count);
|
| - created_texture_mailboxes_.resize(count);
|
| - gles2->GenTextures(count, &created_textures_[0]);
|
| - for (int i = 0; i < count; ++i) {
|
| - gles2->ActiveTexture(GL_TEXTURE0);
|
| - uint32 texture_id = created_textures_[i];
|
| - gles2->BindTexture(texture_target, texture_id);
|
| - gles2->TexParameteri(texture_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
| - gles2->TexParameteri(texture_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
| - gles2->TexParameteri(texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
| - gles2->TexParameteri(texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
| - if (texture_target == GL_TEXTURE_2D) {
|
| - gles2->TexImage2D(texture_target,
|
| - 0,
|
| - GL_RGBA,
|
| - size.width(),
|
| - size.height(),
|
| - 0,
|
| - GL_RGBA,
|
| - GL_UNSIGNED_BYTE,
|
| - NULL);
|
| - }
|
| - gles2->GenMailboxCHROMIUM(created_texture_mailboxes_[i].name);
|
| - gles2->ProduceTextureCHROMIUM(texture_target,
|
| - created_texture_mailboxes_[i].name);
|
| - }
|
| -
|
| - // We need a glFlush here to guarantee the decoder (in the GPU process) can
|
| - // use the texture ids we return here. Since textures are expected to be
|
| - // reused, this should not be unacceptably expensive.
|
| - gles2->Flush();
|
| - DCHECK_EQ(gles2->GetError(), static_cast<GLenum>(GL_NO_ERROR));
|
| -
|
| - *sync_point = gles2->InsertSyncPointCHROMIUM();
|
| - message_loop_async_waiter_.Signal();
|
| -}
|
| -
|
| -void RendererGpuVideoAcceleratorFactories::DeleteTexture(uint32 texture_id) {
|
| - if (message_loop_->BelongsToCurrentThread()) {
|
| - AsyncDeleteTexture(texture_id);
|
| - return;
|
| - }
|
| - message_loop_->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&RendererGpuVideoAcceleratorFactories::AsyncDeleteTexture,
|
| - this,
|
| - texture_id));
|
| -}
|
| -
|
| -void RendererGpuVideoAcceleratorFactories::AsyncDeleteTexture(
|
| - uint32 texture_id) {
|
| - DCHECK(message_loop_->BelongsToCurrentThread());
|
| - if (!context_.get())
|
| - return;
|
| -
|
| - gpu::gles2::GLES2Implementation* gles2 = context_->GetImplementation();
|
| - gles2->DeleteTextures(1, &texture_id);
|
| - DCHECK_EQ(gles2->GetError(), static_cast<GLenum>(GL_NO_ERROR));
|
| -}
|
| -
|
| -void RendererGpuVideoAcceleratorFactories::WaitSyncPoint(uint32 sync_point) {
|
| - if (message_loop_->BelongsToCurrentThread()) {
|
| - AsyncWaitSyncPoint(sync_point);
|
| - message_loop_async_waiter_.Reset();
|
| - return;
|
| - }
|
| -
|
| - message_loop_->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&RendererGpuVideoAcceleratorFactories::AsyncWaitSyncPoint,
|
| - this,
|
| - sync_point));
|
| - base::WaitableEvent* objects[] = {&aborted_waiter_,
|
| - &message_loop_async_waiter_};
|
| - base::WaitableEvent::WaitMany(objects, arraysize(objects));
|
| -}
|
| -
|
| -void RendererGpuVideoAcceleratorFactories::AsyncWaitSyncPoint(
|
| - uint32 sync_point) {
|
| - DCHECK(message_loop_->BelongsToCurrentThread());
|
| - if (!context_) {
|
| - message_loop_async_waiter_.Signal();
|
| - return;
|
| - }
|
| -
|
| - gpu::gles2::GLES2Implementation* gles2 = context_->GetImplementation();
|
| - gles2->WaitSyncPointCHROMIUM(sync_point);
|
| - message_loop_async_waiter_.Signal();
|
| -}
|
| -
|
| -void RendererGpuVideoAcceleratorFactories::ReadPixels(uint32 texture_id,
|
| - uint32 texture_target,
|
| - const gfx::Size& size,
|
| - const SkBitmap& pixels) {
|
| - // SkBitmaps use the SkPixelRef object to refcount the underlying pixels.
|
| - // Multiple SkBitmaps can share a SkPixelRef instance. We use this to
|
| - // ensure that the underlying pixels in the SkBitmap passed in remain valid
|
| - // until the AsyncReadPixels() call completes.
|
| - read_pixels_bitmap_.setPixelRef(pixels.pixelRef());
|
| -
|
| - if (!message_loop_->BelongsToCurrentThread()) {
|
| - message_loop_->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&RendererGpuVideoAcceleratorFactories::AsyncReadPixels,
|
| - this,
|
| - texture_id,
|
| - texture_target,
|
| - size));
|
| - base::WaitableEvent* objects[] = {&aborted_waiter_,
|
| - &message_loop_async_waiter_};
|
| - if (base::WaitableEvent::WaitMany(objects, arraysize(objects)) == 0)
|
| - return;
|
| - } else {
|
| - AsyncReadPixels(texture_id, texture_target, size);
|
| - message_loop_async_waiter_.Reset();
|
| - }
|
| - read_pixels_bitmap_.setPixelRef(NULL);
|
| -}
|
| -
|
| -void RendererGpuVideoAcceleratorFactories::AsyncReadPixels(
|
| - uint32 texture_id,
|
| - uint32 texture_target,
|
| - const gfx::Size& size) {
|
| - DCHECK(message_loop_->BelongsToCurrentThread());
|
| - if (!context_.get()) {
|
| - message_loop_async_waiter_.Signal();
|
| - return;
|
| - }
|
| -
|
| - gpu::gles2::GLES2Implementation* gles2 = context_->GetImplementation();
|
| -
|
| - GLuint tmp_texture;
|
| - gles2->GenTextures(1, &tmp_texture);
|
| - gles2->BindTexture(texture_target, tmp_texture);
|
| - gles2->TexParameteri(texture_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
| - gles2->TexParameteri(texture_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
| - gles2->TexParameteri(texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
| - gles2->TexParameteri(texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
| - context_->copyTextureCHROMIUM(
|
| - texture_target, texture_id, tmp_texture, 0, GL_RGBA, GL_UNSIGNED_BYTE);
|
| -
|
| - GLuint fb;
|
| - gles2->GenFramebuffers(1, &fb);
|
| - gles2->BindFramebuffer(GL_FRAMEBUFFER, fb);
|
| - gles2->FramebufferTexture2D(
|
| - GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture_target, tmp_texture, 0);
|
| - gles2->PixelStorei(GL_PACK_ALIGNMENT, 4);
|
| - gles2->ReadPixels(0,
|
| - 0,
|
| - size.width(),
|
| - size.height(),
|
| - GL_BGRA_EXT,
|
| - GL_UNSIGNED_BYTE,
|
| - read_pixels_bitmap_.pixelRef()->pixels());
|
| - gles2->DeleteFramebuffers(1, &fb);
|
| - gles2->DeleteTextures(1, &tmp_texture);
|
| - DCHECK_EQ(gles2->GetError(), static_cast<GLenum>(GL_NO_ERROR));
|
| - message_loop_async_waiter_.Signal();
|
| -}
|
| -
|
| -base::SharedMemory* RendererGpuVideoAcceleratorFactories::CreateSharedMemory(
|
| - size_t size) {
|
| - if (main_message_loop_->BelongsToCurrentThread()) {
|
| - return ChildThread::current()->AllocateSharedMemory(size);
|
| - }
|
| - main_message_loop_->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&RendererGpuVideoAcceleratorFactories::AsyncCreateSharedMemory,
|
| - this,
|
| - size));
|
| -
|
| - base::WaitableEvent* objects[] = {&aborted_waiter_,
|
| - &render_thread_async_waiter_};
|
| - if (base::WaitableEvent::WaitMany(objects, arraysize(objects)) == 0)
|
| - return NULL;
|
| - return shared_memory_segment_.release();
|
| -}
|
| -
|
| -void RendererGpuVideoAcceleratorFactories::AsyncCreateSharedMemory(
|
| - size_t size) {
|
| - DCHECK_EQ(base::MessageLoop::current(),
|
| - ChildThread::current()->message_loop());
|
| -
|
| - shared_memory_segment_.reset(
|
| - ChildThread::current()->AllocateSharedMemory(size));
|
| - render_thread_async_waiter_.Signal();
|
| -}
|
| -
|
| -scoped_refptr<base::MessageLoopProxy>
|
| -RendererGpuVideoAcceleratorFactories::GetMessageLoop() {
|
| - return message_loop_;
|
| -}
|
| -
|
| -void RendererGpuVideoAcceleratorFactories::Abort() { aborted_waiter_.Signal(); }
|
| -
|
| -bool RendererGpuVideoAcceleratorFactories::IsAborted() {
|
| - return aborted_waiter_.IsSignaled();
|
| -}
|
| -
|
| -scoped_refptr<RendererGpuVideoAcceleratorFactories>
|
| -RendererGpuVideoAcceleratorFactories::Clone() {
|
| - scoped_refptr<RendererGpuVideoAcceleratorFactories> factories =
|
| - new RendererGpuVideoAcceleratorFactories();
|
| - factories->message_loop_ = message_loop_;
|
| - factories->main_message_loop_ = main_message_loop_;
|
| - factories->gpu_channel_host_ = gpu_channel_host_;
|
| - factories->context_ = context_;
|
| - return factories;
|
| -}
|
| -
|
| -void
|
| -RendererGpuVideoAcceleratorFactories::AsyncDestroyVideoDecodeAccelerator() {
|
| - // OK to release because Destroy() will delete the VDA instance.
|
| - if (vda_)
|
| - vda_.release()->Destroy();
|
| -}
|
| -
|
| -void
|
| -RendererGpuVideoAcceleratorFactories::AsyncDestroyVideoEncodeAccelerator() {
|
| - // OK to release because Destroy() will delete the VDA instance.
|
| - if (vea_)
|
| - vea_.release()->Destroy();
|
| -}
|
| -
|
| -} // namespace content
|
|
|