image_transport_factory_android.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
1674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen// Use of this source code is governed by a BSD-style license that can be
3674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen// found in the LICENSE file.
4674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
5674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen#include "content/browser/renderer_host/image_transport_factory_android.h"
6674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
7674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen#include "base/lazy_instance.h"
8674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen#include "base/strings/stringprintf.h"
9674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen#include "content/browser/gpu/browser_gpu_channel_host_factory.h"
10674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen#include "content/common/gpu/client/gl_helper.h"
11674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen#include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h"
12674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen#include "content/common/gpu/gpu_process_launch_causes.h"
13674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen#include "gpu/command_buffer/client/gles2_implementation.h"
14674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen#include "third_party/WebKit/public/platform/WebGraphicsContext3D.h"
15674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen#include "third_party/khronos/GLES2/gl2.h"
16674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen#include "ui/gfx/android/device_display_info.h"
17674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
18674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogennamespace content {
19674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
20674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenbase::LazyInstance<ObserverList<ImageTransportFactoryAndroidObserver> >::Leaky
21674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    g_factory_observers = LAZY_INSTANCE_INITIALIZER;
22674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
23674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenclass GLContextLostListener
24674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    : public blink::WebGraphicsContext3D::WebGraphicsContextLostCallback {
25674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public:
26674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen  // WebGraphicsContextLostCallback implementation.
27674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen  virtual void onContextLost() OVERRIDE;
28674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private:
29674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen  static void DidLoseContext();
30674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen};
31674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
32674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogennamespace {
33674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
34674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenstatic ImageTransportFactoryAndroid* g_factory = NULL;
35674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
36674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenclass CmdBufferImageTransportFactory : public ImageTransportFactoryAndroid {
37674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public:
38674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen  CmdBufferImageTransportFactory();
39674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen  virtual ~CmdBufferImageTransportFactory();
40674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
41674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen  virtual uint32_t InsertSyncPoint() OVERRIDE;
42674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen  virtual void WaitSyncPoint(uint32_t sync_point) OVERRIDE;
43674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen  virtual uint32_t CreateTexture() OVERRIDE;
44674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen  virtual void DeleteTexture(uint32_t id) OVERRIDE;
45674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen  virtual void AcquireTexture(
46674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen      uint32 texture_id, const signed char* mailbox_name) OVERRIDE;
47674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen  virtual gpu::gles2::GLES2Interface* GetContextGL() OVERRIDE {
48674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    return context_->GetImplementation();
49674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen  }
50674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen  virtual GLHelper* GetGLHelper() OVERRIDE;
51674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen  virtual uint32 GetChannelID() OVERRIDE {
52674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    return BrowserGpuChannelHostFactory::instance()->GetGpuChannelId();
53674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen  }
54674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
55674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private:
56674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen  scoped_ptr<WebGraphicsContext3DCommandBufferImpl> context_;
57674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen  scoped_ptr<GLHelper> gl_helper_;
58674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
59674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen  DISALLOW_COPY_AND_ASSIGN(CmdBufferImageTransportFactory);
60674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen};
61674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
62674060f01e9090cd21b3c5656cc3204912ad17a6Jon BoekenoogenCmdBufferImageTransportFactory::CmdBufferImageTransportFactory() {
63674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen  BrowserGpuChannelHostFactory* factory =
64674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen      BrowserGpuChannelHostFactory::instance();
65674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen  scoped_refptr<GpuChannelHost> gpu_channel_host(factory->EstablishGpuChannelSync(
66674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen      CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE));
67674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen  DCHECK(gpu_channel_host);
68674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
69674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen  blink::WebGraphicsContext3D::Attributes attrs;
70674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen  attrs.shareResources = true;
71674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen  GURL url("chrome://gpu/ImageTransportFactoryAndroid");
72674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen  static const size_t kBytesPerPixel = 4;
73674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen  gfx::DeviceDisplayInfo display_info;
74674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen  size_t full_screen_texture_size_in_bytes = display_info.GetDisplayHeight() *
75674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                                             display_info.GetDisplayWidth() *
76674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                                             kBytesPerPixel;
77674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen  WebGraphicsContext3DCommandBufferImpl::SharedMemoryLimits limits;
78674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen  limits.command_buffer_size = 64 * 1024;
79674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen  limits.start_transfer_buffer_size = 64 * 1024;
80  limits.min_transfer_buffer_size = 64 * 1024;
81  limits.max_transfer_buffer_size = std::min(
82      3 * full_screen_texture_size_in_bytes, kDefaultMaxTransferBufferSize);
83  limits.mapped_memory_reclaim_limit =
84      WebGraphicsContext3DCommandBufferImpl::kNoLimit;
85  context_.reset(
86      new WebGraphicsContext3DCommandBufferImpl(0,  // offscreen
87                                                url,
88                                                gpu_channel_host.get(),
89                                                attrs,
90                                                false,
91                                                limits));
92  context_->setContextLostCallback(context_lost_listener_.get());
93  if (context_->makeContextCurrent())
94    context_->pushGroupMarkerEXT(
95        base::StringPrintf("CmdBufferImageTransportFactory-%p",
96                           context_.get()).c_str());
97}
98
99CmdBufferImageTransportFactory::~CmdBufferImageTransportFactory() {
100  context_->setContextLostCallback(NULL);
101}
102
103uint32_t CmdBufferImageTransportFactory::InsertSyncPoint() {
104  if (!context_->makeContextCurrent()) {
105    LOG(ERROR) << "Failed to make helper context current.";
106    return 0;
107  }
108  return context_->insertSyncPoint();
109}
110
111void CmdBufferImageTransportFactory::WaitSyncPoint(uint32_t sync_point) {
112  if (!context_->makeContextCurrent()) {
113    LOG(ERROR) << "Failed to make helper context current.";
114    return;
115  }
116  context_->waitSyncPoint(sync_point);
117}
118
119uint32_t CmdBufferImageTransportFactory::CreateTexture() {
120  if (!context_->makeContextCurrent()) {
121    LOG(ERROR) << "Failed to make helper context current.";
122    return false;
123  }
124  return context_->createTexture();
125}
126
127void CmdBufferImageTransportFactory::DeleteTexture(uint32_t id) {
128  if (!context_->makeContextCurrent()) {
129    LOG(ERROR) << "Failed to make helper context current.";
130    return;
131  }
132  context_->deleteTexture(id);
133}
134
135void CmdBufferImageTransportFactory::AcquireTexture(
136    uint32 texture_id, const signed char* mailbox_name) {
137  if (!context_->makeContextCurrent()) {
138    LOG(ERROR) << "Failed to make helper context current.";
139    return;
140  }
141  context_->bindTexture(GL_TEXTURE_2D, texture_id);
142  context_->consumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox_name);
143  context_->shallowFlushCHROMIUM();
144}
145
146GLHelper* CmdBufferImageTransportFactory::GetGLHelper() {
147  if (!gl_helper_)
148    gl_helper_.reset(new GLHelper(context_->GetImplementation(),
149                                  context_->GetContextSupport()));
150
151  return gl_helper_.get();
152}
153
154}  // anonymous namespace
155
156// static
157ImageTransportFactoryAndroid* ImageTransportFactoryAndroid::GetInstance() {
158  if (!g_factory)
159    g_factory = new CmdBufferImageTransportFactory();
160
161  return g_factory;
162}
163
164ImageTransportFactoryAndroid::ImageTransportFactoryAndroid()
165    : context_lost_listener_(new GLContextLostListener()) {}
166
167ImageTransportFactoryAndroid::~ImageTransportFactoryAndroid() {}
168
169void ImageTransportFactoryAndroid::AddObserver(
170    ImageTransportFactoryAndroidObserver* observer) {
171  g_factory_observers.Get().AddObserver(observer);
172}
173
174void ImageTransportFactoryAndroid::RemoveObserver(
175    ImageTransportFactoryAndroidObserver* observer) {
176  g_factory_observers.Get().RemoveObserver(observer);
177}
178
179void GLContextLostListener::onContextLost() {
180  // Need to post a task because the command buffer client cannot be deleted
181  // from within this callback.
182  LOG(ERROR) << "Context lost.";
183  base::MessageLoop::current()->PostTask(
184      FROM_HERE,
185      base::Bind(&GLContextLostListener::DidLoseContext));
186}
187
188void GLContextLostListener::DidLoseContext() {
189  delete g_factory;
190  g_factory = NULL;
191  FOR_EACH_OBSERVER(ImageTransportFactoryAndroidObserver,
192      g_factory_observers.Get(),
193      OnLostResources());
194}
195
196} // namespace content
197