15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/renderer/media/renderer_gpu_video_decoder_factories.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <GLES2/gl2.h>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <GLES2/gl2ext.h>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/child/child_thread.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/common/gpu/client/gpu_channel_host.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "gpu/command_buffer/client/gles2_implementation.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "gpu/ipc/command_buffer_proxy.h"
16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "third_party/skia/include/core/SkPixelRef.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace content {
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)RendererGpuVideoDecoderFactories::~RendererGpuVideoDecoderFactories() {}
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)RendererGpuVideoDecoderFactories::RendererGpuVideoDecoderFactories(
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GpuChannelHost* gpu_channel_host,
23bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    const scoped_refptr<base::MessageLoopProxy>& message_loop,
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WebGraphicsContext3DCommandBufferImpl* context)
25bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    : message_loop_(message_loop),
26eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      main_message_loop_(base::MessageLoopProxy::current()),
27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      gpu_channel_host_(gpu_channel_host),
28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      aborted_waiter_(true, false),
29bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      message_loop_async_waiter_(false, false),
30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      render_thread_async_waiter_(false, false) {
31bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  if (message_loop_->BelongsToCurrentThread()) {
32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    AsyncGetContext(context);
33bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    message_loop_async_waiter_.Reset();
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
36bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  // Wait for the context to be acquired.
37bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  message_loop_->PostTask(FROM_HERE, base::Bind(
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &RendererGpuVideoDecoderFactories::AsyncGetContext,
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Unretained to avoid ref/deref'ing |*this|, which is not yet stored in a
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // scoped_refptr.  Safe because the Wait() below keeps us alive until this
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // task completes.
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Unretained(this),
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // OK to pass raw because the pointee is only deleted on the compositor
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // thread, and only as the result of a PostTask from the render thread
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // which can only happen after this function returns, so our PostTask will
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // run first.
47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      context));
48bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  message_loop_async_waiter_.Wait();
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
51bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben MurdochRendererGpuVideoDecoderFactories::RendererGpuVideoDecoderFactories()
52bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    : aborted_waiter_(true, false),
53bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      message_loop_async_waiter_(false, false),
54bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      render_thread_async_waiter_(false, false) {}
55bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void RendererGpuVideoDecoderFactories::AsyncGetContext(
57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    WebGraphicsContext3DCommandBufferImpl* context) {
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  context_ = context->AsWeakPtr();
59868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (context_.get()) {
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (context_->makeContextCurrent()) {
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Called once per media player, but is a no-op after the first one in
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // each renderer.
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      context_->insertEventMarkerEXT("GpuVDAContext3D");
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
66bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  message_loop_async_waiter_.Signal();
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)media::VideoDecodeAccelerator*
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)RendererGpuVideoDecoderFactories::CreateVideoDecodeAccelerator(
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    media::VideoCodecProfile profile,
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    media::VideoDecodeAccelerator::Client* client) {
73bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  if (message_loop_->BelongsToCurrentThread()) {
747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    AsyncCreateVideoDecodeAccelerator(profile, client);
75bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    message_loop_async_waiter_.Reset();
767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return vda_.release();
777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // The VDA is returned in the vda_ member variable by the
79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // AsyncCreateVideoDecodeAccelerator() function.
80bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  message_loop_->PostTask(FROM_HERE, base::Bind(
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &RendererGpuVideoDecoderFactories::AsyncCreateVideoDecodeAccelerator,
82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      this, profile, client));
83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::WaitableEvent* objects[] = {&aborted_waiter_,
85bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch                                    &message_loop_async_waiter_};
86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (base::WaitableEvent::WaitMany(objects, arraysize(objects)) == 0) {
87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // If we are aborting and the VDA is created by the
88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // AsyncCreateVideoDecodeAccelerator() function later we need to ensure
89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // that it is destroyed on the same thread.
90bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    message_loop_->PostTask(FROM_HERE, base::Bind(
91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        &RendererGpuVideoDecoderFactories::AsyncDestroyVideoDecodeAccelerator,
92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        this));
93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return NULL;
94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return vda_.release();
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void RendererGpuVideoDecoderFactories::AsyncCreateVideoDecodeAccelerator(
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      media::VideoCodecProfile profile,
100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      media::VideoDecodeAccelerator::Client* client) {
101bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  DCHECK(message_loop_->BelongsToCurrentThread());
102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
103868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (context_.get() && context_->GetCommandBufferProxy()) {
104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    vda_ = gpu_channel_host_->CreateVideoDecoder(
105868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        context_->GetCommandBufferProxy()->GetRouteID(), profile, client);
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
107bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  message_loop_async_waiter_.Signal();
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
110eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochuint32 RendererGpuVideoDecoderFactories::CreateTextures(
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int32 count, const gfx::Size& size,
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<uint32>* texture_ids,
113eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    std::vector<gpu::Mailbox>* texture_mailboxes,
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint32 texture_target) {
115eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  uint32 sync_point = 0;
116eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
117bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  if (message_loop_->BelongsToCurrentThread()) {
1187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    AsyncCreateTextures(count, size, texture_target, &sync_point);
1197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    texture_ids->swap(created_textures_);
1207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    texture_mailboxes->swap(created_texture_mailboxes_);
121bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    message_loop_async_waiter_.Reset();
1227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return sync_point;
1237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
124bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  message_loop_->PostTask(FROM_HERE, base::Bind(
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &RendererGpuVideoDecoderFactories::AsyncCreateTextures, this,
126eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      count, size, texture_target, &sync_point));
127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::WaitableEvent* objects[] = {&aborted_waiter_,
129bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch                                    &message_loop_async_waiter_};
130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (base::WaitableEvent::WaitMany(objects, arraysize(objects)) == 0)
131eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return 0;
132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  texture_ids->swap(created_textures_);
133eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  texture_mailboxes->swap(created_texture_mailboxes_);
134eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return sync_point;
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void RendererGpuVideoDecoderFactories::AsyncCreateTextures(
138eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    int32 count, const gfx::Size& size, uint32 texture_target,
139eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    uint32* sync_point) {
140bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  DCHECK(message_loop_->BelongsToCurrentThread());
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(texture_target);
142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
143868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!context_.get()) {
144bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    message_loop_async_waiter_.Signal();
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gpu::gles2::GLES2Implementation* gles2 = context_->GetImplementation();
148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  created_textures_.resize(count);
149eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  created_texture_mailboxes_.resize(count);
150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  gles2->GenTextures(count, &created_textures_[0]);
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < count; ++i) {
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gles2->ActiveTexture(GL_TEXTURE0);
153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    uint32 texture_id = created_textures_[i];
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gles2->BindTexture(texture_target, texture_id);
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gles2->TexParameteri(texture_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gles2->TexParameteri(texture_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gles2->TexParameteri(texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gles2->TexParameteri(texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (texture_target == GL_TEXTURE_2D) {
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      gles2->TexImage2D(texture_target, 0, GL_RGBA, size.width(), size.height(),
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
163eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    gles2->GenMailboxCHROMIUM(created_texture_mailboxes_[i].name);
164eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    gles2->ProduceTextureCHROMIUM(texture_target,
165eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                  created_texture_mailboxes_[i].name);
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
167eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We need a glFlush here to guarantee the decoder (in the GPU process) can
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // use the texture ids we return here.  Since textures are expected to be
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // reused, this should not be unacceptably expensive.
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gles2->Flush();
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(gles2->GetError(), static_cast<GLenum>(GL_NO_ERROR));
173eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
174eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  *sync_point = gles2->InsertSyncPointCHROMIUM();
175bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  message_loop_async_waiter_.Signal();
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void RendererGpuVideoDecoderFactories::DeleteTexture(uint32 texture_id) {
179bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  if (message_loop_->BelongsToCurrentThread()) {
1807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    AsyncDeleteTexture(texture_id);
1817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return;
1827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
183bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  message_loop_->PostTask(FROM_HERE, base::Bind(
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &RendererGpuVideoDecoderFactories::AsyncDeleteTexture, this, texture_id));
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void RendererGpuVideoDecoderFactories::AsyncDeleteTexture(uint32 texture_id) {
188bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  DCHECK(message_loop_->BelongsToCurrentThread());
189868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!context_.get())
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
191c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gpu::gles2::GLES2Implementation* gles2 = context_->GetImplementation();
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gles2->DeleteTextures(1, &texture_id);
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(gles2->GetError(), static_cast<GLenum>(GL_NO_ERROR));
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
197eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid RendererGpuVideoDecoderFactories::WaitSyncPoint(uint32 sync_point) {
198bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  if (message_loop_->BelongsToCurrentThread()) {
199eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    AsyncWaitSyncPoint(sync_point);
200bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    message_loop_async_waiter_.Reset();
201eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return;
202eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
203eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
204bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  message_loop_->PostTask(FROM_HERE, base::Bind(
205eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      &RendererGpuVideoDecoderFactories::AsyncWaitSyncPoint,
206eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      this,
207eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      sync_point));
208eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::WaitableEvent* objects[] = {&aborted_waiter_,
209bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch                                    &message_loop_async_waiter_};
210eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::WaitableEvent::WaitMany(objects, arraysize(objects));
211eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
212eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
213eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid RendererGpuVideoDecoderFactories::AsyncWaitSyncPoint(uint32 sync_point) {
214bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  DCHECK(message_loop_->BelongsToCurrentThread());
215eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (!context_) {
216bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    message_loop_async_waiter_.Signal();
217eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return;
218eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
219eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
220eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  gpu::gles2::GLES2Implementation* gles2 = context_->GetImplementation();
221eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  gles2->WaitSyncPointCHROMIUM(sync_point);
222bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  message_loop_async_waiter_.Signal();
223eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
224eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void RendererGpuVideoDecoderFactories::ReadPixels(
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint32 texture_id, uint32 texture_target, const gfx::Size& size,
227c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const SkBitmap& pixels) {
228c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // SkBitmaps use the SkPixelRef object to refcount the underlying pixels.
229c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Multiple SkBitmaps can share a SkPixelRef instance. We use this to
230c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // ensure that the underlying pixels in the SkBitmap passed in remain valid
231c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // until the AsyncReadPixels() call completes.
232c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  read_pixels_bitmap_.setPixelRef(pixels.pixelRef());
233c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
234bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  if (!message_loop_->BelongsToCurrentThread()) {
235bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    message_loop_->PostTask(FROM_HERE, base::Bind(
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        &RendererGpuVideoDecoderFactories::AsyncReadPixels, this,
237c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        texture_id, texture_target, size));
238c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::WaitableEvent* objects[] = {&aborted_waiter_,
239bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch                                      &message_loop_async_waiter_};
240c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (base::WaitableEvent::WaitMany(objects, arraysize(objects)) == 0)
241c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return;
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
243c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    AsyncReadPixels(texture_id, texture_target, size);
244bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    message_loop_async_waiter_.Reset();
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
246c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  read_pixels_bitmap_.setPixelRef(NULL);
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void RendererGpuVideoDecoderFactories::AsyncReadPixels(
250c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    uint32 texture_id, uint32 texture_target, const gfx::Size& size) {
251bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  DCHECK(message_loop_->BelongsToCurrentThread());
252868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!context_.get()) {
253bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    message_loop_async_waiter_.Signal();
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
255c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gpu::gles2::GLES2Implementation* gles2 = context_->GetImplementation();
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GLuint tmp_texture;
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gles2->GenTextures(1, &tmp_texture);
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gles2->BindTexture(texture_target, tmp_texture);
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gles2->TexParameteri(texture_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gles2->TexParameteri(texture_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gles2->TexParameteri(texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gles2->TexParameteri(texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  context_->copyTextureCHROMIUM(
267a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      texture_target, texture_id, tmp_texture, 0, GL_RGBA, GL_UNSIGNED_BYTE);
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GLuint fb;
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gles2->GenFramebuffers(1, &fb);
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gles2->BindFramebuffer(GL_FRAMEBUFFER, fb);
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gles2->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              texture_target, tmp_texture, 0);
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gles2->PixelStorei(GL_PACK_ALIGNMENT, 4);
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gles2->ReadPixels(0, 0, size.width(), size.height(), GL_BGRA_EXT,
276c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      GL_UNSIGNED_BYTE, read_pixels_bitmap_.pixelRef()->pixels());
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gles2->DeleteFramebuffers(1, &fb);
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gles2->DeleteTextures(1, &tmp_texture);
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(gles2->GetError(), static_cast<GLenum>(GL_NO_ERROR));
280bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  message_loop_async_waiter_.Signal();
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)base::SharedMemory* RendererGpuVideoDecoderFactories::CreateSharedMemory(
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t size) {
2857dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (main_message_loop_->BelongsToCurrentThread()) {
2867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return ChildThread::current()->AllocateSharedMemory(size);
2877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
288eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  main_message_loop_->PostTask(FROM_HERE, base::Bind(
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &RendererGpuVideoDecoderFactories::AsyncCreateSharedMemory, this,
290c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      size));
291c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
292c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::WaitableEvent* objects[] = {&aborted_waiter_,
293c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                    &render_thread_async_waiter_};
294c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (base::WaitableEvent::WaitMany(objects, arraysize(objects)) == 0)
295c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return NULL;
296c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return shared_memory_segment_.release();
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
299c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void RendererGpuVideoDecoderFactories::AsyncCreateSharedMemory(size_t size) {
300c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK_EQ(base::MessageLoop::current(),
301c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            ChildThread::current()->message_loop());
302c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
303c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  shared_memory_segment_.reset(
304c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      ChildThread::current()->AllocateSharedMemory(size));
305c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  render_thread_async_waiter_.Signal();
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)scoped_refptr<base::MessageLoopProxy>
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)RendererGpuVideoDecoderFactories::GetMessageLoop() {
310bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  return message_loop_;
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
313c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void RendererGpuVideoDecoderFactories::Abort() {
314c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  aborted_waiter_.Signal();
315c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
316c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
317c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool RendererGpuVideoDecoderFactories::IsAborted() {
318c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return aborted_waiter_.IsSignaled();
319c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
320c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
321bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdochscoped_refptr<media::GpuVideoDecoderFactories>
322bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben MurdochRendererGpuVideoDecoderFactories::Clone() {
323bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  scoped_refptr<RendererGpuVideoDecoderFactories> factories =
324bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      new RendererGpuVideoDecoderFactories();
325bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  factories->message_loop_ = message_loop_;
326bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  factories->main_message_loop_ = main_message_loop_;
327bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  factories->gpu_channel_host_ = gpu_channel_host_;
328bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  factories->context_ = context_;
329bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  return factories;
330bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch}
331bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
332c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void RendererGpuVideoDecoderFactories::AsyncDestroyVideoDecodeAccelerator() {
333c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // OK to release because Destroy() will delete the VDA instance.
334c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (vda_)
335c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    vda_.release()->Destroy();
336c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
337c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace content
339