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 20namespace content { 21 22base::LazyInstance<ObserverList<ImageTransportFactoryAndroidObserver> >::Leaky 23 g_factory_observers = LAZY_INSTANCE_INITIALIZER; 24 25class GLContextLostListener 26 : public WebKit::WebGraphicsContext3D::WebGraphicsContextLostCallback { 27 public: 28 // WebGraphicsContextLostCallback implementation. 29 virtual void onContextLost() OVERRIDE; 30 private: 31 static void DidLoseContext(); 32}; 33 34namespace { 35 36using webkit::gpu::WebGraphicsContext3DInProcessCommandBufferImpl; 37 38static ImageTransportFactoryAndroid* g_factory = NULL; 39 40class 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 66DirectGLImageTransportFactory::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 79DirectGLImageTransportFactory::~DirectGLImageTransportFactory() { 80 context_->setContextLostCallback(NULL); 81} 82 83class 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 106CmdBufferImageTransportFactory::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 139CmdBufferImageTransportFactory::~CmdBufferImageTransportFactory() { 140 context_->setContextLostCallback(NULL); 141} 142 143uint32_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 151void 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 159uint32_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 167void 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 175void 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 186GLHelper* 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 196ImageTransportFactoryAndroid* 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 207ImageTransportFactoryAndroid::ImageTransportFactoryAndroid() 208 : context_lost_listener_(new GLContextLostListener()) {} 209 210ImageTransportFactoryAndroid::~ImageTransportFactoryAndroid() {} 211 212void ImageTransportFactoryAndroid::AddObserver( 213 ImageTransportFactoryAndroidObserver* observer) { 214 g_factory_observers.Get().AddObserver(observer); 215} 216 217void ImageTransportFactoryAndroid::RemoveObserver( 218 ImageTransportFactoryAndroidObserver* observer) { 219 g_factory_observers.Get().RemoveObserver(observer); 220} 221 222void 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 231void 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