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/strings/stringprintf.h"
      9 #include "content/browser/gpu/browser_gpu_channel_host_factory.h"
     10 #include "content/common/gpu/client/gl_helper.h"
     11 #include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h"
     12 #include "content/common/gpu/gpu_process_launch_causes.h"
     13 #include "third_party/WebKit/public/platform/WebGraphicsContext3D.h"
     14 #include "third_party/khronos/GLES2/gl2.h"
     15 #include "ui/gfx/android/device_display_info.h"
     16 
     17 namespace content {
     18 
     19 base::LazyInstance<ObserverList<ImageTransportFactoryAndroidObserver> >::Leaky
     20     g_factory_observers = LAZY_INSTANCE_INITIALIZER;
     21 
     22 class GLContextLostListener
     23     : public blink::WebGraphicsContext3D::WebGraphicsContextLostCallback {
     24  public:
     25   // WebGraphicsContextLostCallback implementation.
     26   virtual void onContextLost() OVERRIDE;
     27  private:
     28   static void DidLoseContext();
     29 };
     30 
     31 namespace {
     32 
     33 static ImageTransportFactoryAndroid* g_factory = NULL;
     34 
     35 class CmdBufferImageTransportFactory : public ImageTransportFactoryAndroid {
     36  public:
     37   CmdBufferImageTransportFactory();
     38   virtual ~CmdBufferImageTransportFactory();
     39 
     40   virtual uint32_t InsertSyncPoint() OVERRIDE;
     41   virtual void WaitSyncPoint(uint32_t sync_point) OVERRIDE;
     42   virtual uint32_t CreateTexture() OVERRIDE;
     43   virtual void DeleteTexture(uint32_t id) OVERRIDE;
     44   virtual void AcquireTexture(
     45       uint32 texture_id, const signed char* mailbox_name) OVERRIDE;
     46   virtual blink::WebGraphicsContext3D* GetContext3D() OVERRIDE {
     47     return context_.get();
     48   }
     49   virtual GLHelper* GetGLHelper() OVERRIDE;
     50   virtual uint32 GetChannelID() OVERRIDE {
     51     return BrowserGpuChannelHostFactory::instance()->GetGpuChannelId();
     52   }
     53 
     54  private:
     55   scoped_ptr<WebGraphicsContext3DCommandBufferImpl> context_;
     56   scoped_ptr<GLHelper> gl_helper_;
     57 
     58   DISALLOW_COPY_AND_ASSIGN(CmdBufferImageTransportFactory);
     59 };
     60 
     61 CmdBufferImageTransportFactory::CmdBufferImageTransportFactory() {
     62   BrowserGpuChannelHostFactory* factory =
     63       BrowserGpuChannelHostFactory::instance();
     64   scoped_refptr<GpuChannelHost> gpu_channel_host(factory->EstablishGpuChannelSync(
     65       CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE));
     66   DCHECK(gpu_channel_host);
     67 
     68   blink::WebGraphicsContext3D::Attributes attrs;
     69   attrs.shareResources = true;
     70   GURL url("chrome://gpu/ImageTransportFactoryAndroid");
     71   static const size_t kBytesPerPixel = 4;
     72   gfx::DeviceDisplayInfo display_info;
     73   size_t full_screen_texture_size_in_bytes = display_info.GetDisplayHeight() *
     74                                              display_info.GetDisplayWidth() *
     75                                              kBytesPerPixel;
     76   WebGraphicsContext3DCommandBufferImpl::SharedMemoryLimits limits;
     77   limits.command_buffer_size = 64 * 1024;
     78   limits.start_transfer_buffer_size = 64 * 1024;
     79   limits.min_transfer_buffer_size = 64 * 1024;
     80   limits.max_transfer_buffer_size = std::min(
     81       3 * full_screen_texture_size_in_bytes, kDefaultMaxTransferBufferSize);
     82   limits.mapped_memory_reclaim_limit =
     83       WebGraphicsContext3DCommandBufferImpl::kNoLimit;
     84   context_.reset(
     85       new WebGraphicsContext3DCommandBufferImpl(0,  // offscreen
     86                                                 url,
     87                                                 gpu_channel_host.get(),
     88                                                 attrs,
     89                                                 false,
     90                                                 limits));
     91   context_->setContextLostCallback(context_lost_listener_.get());
     92   if (context_->makeContextCurrent())
     93     context_->pushGroupMarkerEXT(
     94         base::StringPrintf("CmdBufferImageTransportFactory-%p",
     95                            context_.get()).c_str());
     96 }
     97 
     98 CmdBufferImageTransportFactory::~CmdBufferImageTransportFactory() {
     99   context_->setContextLostCallback(NULL);
    100 }
    101 
    102 uint32_t CmdBufferImageTransportFactory::InsertSyncPoint() {
    103   if (!context_->makeContextCurrent()) {
    104     LOG(ERROR) << "Failed to make helper context current.";
    105     return 0;
    106   }
    107   return context_->insertSyncPoint();
    108 }
    109 
    110 void CmdBufferImageTransportFactory::WaitSyncPoint(uint32_t sync_point) {
    111   if (!context_->makeContextCurrent()) {
    112     LOG(ERROR) << "Failed to make helper context current.";
    113     return;
    114   }
    115   context_->waitSyncPoint(sync_point);
    116 }
    117 
    118 uint32_t CmdBufferImageTransportFactory::CreateTexture() {
    119   if (!context_->makeContextCurrent()) {
    120     LOG(ERROR) << "Failed to make helper context current.";
    121     return false;
    122   }
    123   return context_->createTexture();
    124 }
    125 
    126 void CmdBufferImageTransportFactory::DeleteTexture(uint32_t id) {
    127   if (!context_->makeContextCurrent()) {
    128     LOG(ERROR) << "Failed to make helper context current.";
    129     return;
    130   }
    131   context_->deleteTexture(id);
    132 }
    133 
    134 void CmdBufferImageTransportFactory::AcquireTexture(
    135     uint32 texture_id, const signed char* mailbox_name) {
    136   if (!context_->makeContextCurrent()) {
    137     LOG(ERROR) << "Failed to make helper context current.";
    138     return;
    139   }
    140   context_->bindTexture(GL_TEXTURE_2D, texture_id);
    141   context_->consumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox_name);
    142   context_->shallowFlushCHROMIUM();
    143 }
    144 
    145 GLHelper* CmdBufferImageTransportFactory::GetGLHelper() {
    146   if (!gl_helper_)
    147     gl_helper_.reset(new GLHelper(context_.get(),
    148                                   context_->GetContextSupport()));
    149 
    150   return gl_helper_.get();
    151 }
    152 
    153 }  // anonymous namespace
    154 
    155 // static
    156 ImageTransportFactoryAndroid* ImageTransportFactoryAndroid::GetInstance() {
    157   if (!g_factory)
    158     g_factory = new CmdBufferImageTransportFactory();
    159 
    160   return g_factory;
    161 }
    162 
    163 ImageTransportFactoryAndroid::ImageTransportFactoryAndroid()
    164     : context_lost_listener_(new GLContextLostListener()) {}
    165 
    166 ImageTransportFactoryAndroid::~ImageTransportFactoryAndroid() {}
    167 
    168 void ImageTransportFactoryAndroid::AddObserver(
    169     ImageTransportFactoryAndroidObserver* observer) {
    170   g_factory_observers.Get().AddObserver(observer);
    171 }
    172 
    173 void ImageTransportFactoryAndroid::RemoveObserver(
    174     ImageTransportFactoryAndroidObserver* observer) {
    175   g_factory_observers.Get().RemoveObserver(observer);
    176 }
    177 
    178 void GLContextLostListener::onContextLost() {
    179   // Need to post a task because the command buffer client cannot be deleted
    180   // from within this callback.
    181   LOG(ERROR) << "Context lost.";
    182   base::MessageLoop::current()->PostTask(
    183       FROM_HERE,
    184       base::Bind(&GLContextLostListener::DidLoseContext));
    185 }
    186 
    187 void GLContextLostListener::DidLoseContext() {
    188   delete g_factory;
    189   g_factory = NULL;
    190   FOR_EACH_OBSERVER(ImageTransportFactoryAndroidObserver,
    191       g_factory_observers.Get(),
    192       OnLostResources());
    193 }
    194 
    195 } // namespace content
    196