Home | History | Annotate | Download | only in renderer_host
      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
      3 // found in the LICENSE file.
      4 
      5 #include "content/browser/renderer_host/image_transport_factory_android.h"
      6 
      7 #include "base/lazy_instance.h"
      8 #include "base/memory/singleton.h"
      9 #include "base/strings/stringprintf.h"
     10 #include "content/browser/gpu/browser_gpu_channel_host_factory.h"
     11 #include "content/browser/renderer_host/compositor_impl_android.h"
     12 #include "content/common/gpu/client/gl_helper.h"
     13 #include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h"
     14 #include "content/common/gpu/gpu_process_launch_causes.h"
     15 #include "third_party/WebKit/public/platform/WebGraphicsContext3D.h"
     16 #include "third_party/khronos/GLES2/gl2.h"
     17 #include "ui/gfx/android/device_display_info.h"
     18 #include "webkit/common/gpu/webgraphicscontext3d_in_process_command_buffer_impl.h"
     19 
     20 namespace content {
     21 
     22 base::LazyInstance<ObserverList<ImageTransportFactoryAndroidObserver> >::Leaky
     23     g_factory_observers = LAZY_INSTANCE_INITIALIZER;
     24 
     25 class GLContextLostListener
     26     : public WebKit::WebGraphicsContext3D::WebGraphicsContextLostCallback {
     27  public:
     28   // WebGraphicsContextLostCallback implementation.
     29   virtual void onContextLost() OVERRIDE;
     30  private:
     31   static void DidLoseContext();
     32 };
     33 
     34 namespace {
     35 
     36 using webkit::gpu::WebGraphicsContext3DInProcessCommandBufferImpl;
     37 
     38 static ImageTransportFactoryAndroid* g_factory = NULL;
     39 
     40 class DirectGLImageTransportFactory : public ImageTransportFactoryAndroid {
     41  public:
     42   DirectGLImageTransportFactory();
     43   virtual ~DirectGLImageTransportFactory();
     44 
     45   virtual uint32_t InsertSyncPoint() OVERRIDE { return 0; }
     46   virtual void WaitSyncPoint(uint32_t sync_point) OVERRIDE {}
     47   virtual uint32_t CreateTexture() OVERRIDE {
     48     return context_->createTexture();
     49   }
     50   virtual void DeleteTexture(uint32_t id) OVERRIDE {
     51     context_->deleteTexture(id);
     52   }
     53   virtual void AcquireTexture(
     54       uint32 texture_id, const signed char* mailbox_name) OVERRIDE {}
     55   virtual WebKit::WebGraphicsContext3D* GetContext3D() OVERRIDE {
     56     return context_.get();
     57   }
     58   virtual GLHelper* GetGLHelper() OVERRIDE { return NULL; }
     59 
     60  private:
     61   scoped_ptr<WebKit::WebGraphicsContext3D> context_;
     62 
     63   DISALLOW_COPY_AND_ASSIGN(DirectGLImageTransportFactory);
     64 };
     65 
     66 DirectGLImageTransportFactory::DirectGLImageTransportFactory() {
     67   WebKit::WebGraphicsContext3D::Attributes attrs;
     68   attrs.shareResources = true;
     69   attrs.noAutomaticFlushes = true;
     70   context_ = webkit::gpu::WebGraphicsContext3DInProcessCommandBufferImpl::
     71       CreateViewContext(attrs, NULL);
     72   context_->setContextLostCallback(context_lost_listener_.get());
     73   if (context_->makeContextCurrent())
     74     context_->pushGroupMarkerEXT(
     75         base::StringPrintf("DirectGLImageTransportFactory-%p",
     76                            context_.get()).c_str());
     77 }
     78 
     79 DirectGLImageTransportFactory::~DirectGLImageTransportFactory() {
     80   context_->setContextLostCallback(NULL);
     81 }
     82 
     83 class CmdBufferImageTransportFactory : public ImageTransportFactoryAndroid {
     84  public:
     85   CmdBufferImageTransportFactory();
     86   virtual ~CmdBufferImageTransportFactory();
     87 
     88   virtual uint32_t InsertSyncPoint() OVERRIDE;
     89   virtual void WaitSyncPoint(uint32_t sync_point) OVERRIDE;
     90   virtual uint32_t CreateTexture() OVERRIDE;
     91   virtual void DeleteTexture(uint32_t id) OVERRIDE;
     92   virtual void AcquireTexture(
     93       uint32 texture_id, const signed char* mailbox_name) OVERRIDE;
     94   virtual WebKit::WebGraphicsContext3D* GetContext3D() OVERRIDE {
     95     return context_.get();
     96   }
     97   virtual GLHelper* GetGLHelper() OVERRIDE;
     98 
     99  private:
    100   scoped_ptr<WebGraphicsContext3DCommandBufferImpl> context_;
    101   scoped_ptr<GLHelper> gl_helper_;
    102 
    103   DISALLOW_COPY_AND_ASSIGN(CmdBufferImageTransportFactory);
    104 };
    105 
    106 CmdBufferImageTransportFactory::CmdBufferImageTransportFactory() {
    107   WebKit::WebGraphicsContext3D::Attributes attrs;
    108   attrs.shareResources = true;
    109   GpuChannelHostFactory* factory = BrowserGpuChannelHostFactory::instance();
    110   GURL url("chrome://gpu/ImageTransportFactoryAndroid");
    111   base::WeakPtr<WebGraphicsContext3DSwapBuffersClient> swap_client;
    112   context_.reset(new WebGraphicsContext3DCommandBufferImpl(0, // offscreen
    113                                                            url,
    114                                                            factory,
    115                                                            swap_client));
    116   static const size_t kBytesPerPixel = 4;
    117   gfx::DeviceDisplayInfo display_info;
    118   size_t full_screen_texture_size_in_bytes =
    119       display_info.GetDisplayHeight() *
    120       display_info.GetDisplayWidth() *
    121       kBytesPerPixel;
    122   context_->setContextLostCallback(context_lost_listener_.get());
    123   context_->Initialize(
    124       attrs,
    125       false,
    126       CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE,
    127       64 * 1024,  // command buffer size
    128       64 * 1024,  // starting buffer size
    129       64 * 1024,  // min buffer size
    130       std::min(3 * full_screen_texture_size_in_bytes,
    131                kDefaultMaxTransferBufferSize));
    132 
    133   if (context_->makeContextCurrent())
    134     context_->pushGroupMarkerEXT(
    135         base::StringPrintf("CmdBufferImageTransportFactory-%p",
    136                            context_.get()).c_str());
    137 }
    138 
    139 CmdBufferImageTransportFactory::~CmdBufferImageTransportFactory() {
    140   context_->setContextLostCallback(NULL);
    141 }
    142 
    143 uint32_t CmdBufferImageTransportFactory::InsertSyncPoint() {
    144   if (!context_->makeContextCurrent()) {
    145     LOG(ERROR) << "Failed to make helper context current.";
    146     return 0;
    147   }
    148   return context_->insertSyncPoint();
    149 }
    150 
    151 void CmdBufferImageTransportFactory::WaitSyncPoint(uint32_t sync_point) {
    152   if (!context_->makeContextCurrent()) {
    153     LOG(ERROR) << "Failed to make helper context current.";
    154     return;
    155   }
    156   context_->waitSyncPoint(sync_point);
    157 }
    158 
    159 uint32_t CmdBufferImageTransportFactory::CreateTexture() {
    160   if (!context_->makeContextCurrent()) {
    161     LOG(ERROR) << "Failed to make helper context current.";
    162     return false;
    163   }
    164   return context_->createTexture();
    165 }
    166 
    167 void CmdBufferImageTransportFactory::DeleteTexture(uint32_t id) {
    168   if (!context_->makeContextCurrent()) {
    169     LOG(ERROR) << "Failed to make helper context current.";
    170     return;
    171   }
    172   context_->deleteTexture(id);
    173 }
    174 
    175 void CmdBufferImageTransportFactory::AcquireTexture(
    176     uint32 texture_id, const signed char* mailbox_name) {
    177   if (!context_->makeContextCurrent()) {
    178     LOG(ERROR) << "Failed to make helper context current.";
    179     return;
    180   }
    181   context_->bindTexture(GL_TEXTURE_2D, texture_id);
    182   context_->consumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox_name);
    183   context_->flush();
    184 }
    185 
    186 GLHelper* CmdBufferImageTransportFactory::GetGLHelper() {
    187   if (!gl_helper_)
    188     gl_helper_.reset(new GLHelper(context_.get()));
    189 
    190   return gl_helper_.get();
    191 }
    192 
    193 }  // anonymous namespace
    194 
    195 // static
    196 ImageTransportFactoryAndroid* ImageTransportFactoryAndroid::GetInstance() {
    197   if (!g_factory) {
    198     if (CompositorImpl::UsesDirectGL())
    199       g_factory = new DirectGLImageTransportFactory();
    200     else
    201       g_factory = new CmdBufferImageTransportFactory();
    202   }
    203 
    204   return g_factory;
    205 }
    206 
    207 ImageTransportFactoryAndroid::ImageTransportFactoryAndroid()
    208     : context_lost_listener_(new GLContextLostListener()) {}
    209 
    210 ImageTransportFactoryAndroid::~ImageTransportFactoryAndroid() {}
    211 
    212 void ImageTransportFactoryAndroid::AddObserver(
    213     ImageTransportFactoryAndroidObserver* observer) {
    214   g_factory_observers.Get().AddObserver(observer);
    215 }
    216 
    217 void ImageTransportFactoryAndroid::RemoveObserver(
    218     ImageTransportFactoryAndroidObserver* observer) {
    219   g_factory_observers.Get().RemoveObserver(observer);
    220 }
    221 
    222 void GLContextLostListener::onContextLost() {
    223   // Need to post a task because the command buffer client cannot be deleted
    224   // from within this callback.
    225   LOG(ERROR) << "Context lost.";
    226   base::MessageLoop::current()->PostTask(
    227       FROM_HERE,
    228       base::Bind(&GLContextLostListener::DidLoseContext));
    229 }
    230 
    231 void GLContextLostListener::DidLoseContext() {
    232   delete g_factory;
    233   g_factory = NULL;
    234   FOR_EACH_OBSERVER(ImageTransportFactoryAndroidObserver,
    235       g_factory_observers.Get(),
    236       OnLostResources());
    237 }
    238 
    239 } // namespace content
    240