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