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 "gpu/command_buffer/client/gles2_implementation.h" 14#include "third_party/WebKit/public/platform/WebGraphicsContext3D.h" 15#include "third_party/khronos/GLES2/gl2.h" 16#include "ui/gfx/android/device_display_info.h" 17 18namespace content { 19 20base::LazyInstance<ObserverList<ImageTransportFactoryAndroidObserver> >::Leaky 21 g_factory_observers = LAZY_INSTANCE_INITIALIZER; 22 23class GLContextLostListener 24 : public blink::WebGraphicsContext3D::WebGraphicsContextLostCallback { 25 public: 26 // WebGraphicsContextLostCallback implementation. 27 virtual void onContextLost() OVERRIDE; 28 private: 29 static void DidLoseContext(); 30}; 31 32namespace { 33 34static ImageTransportFactoryAndroid* g_factory = NULL; 35 36class CmdBufferImageTransportFactory : public ImageTransportFactoryAndroid { 37 public: 38 CmdBufferImageTransportFactory(); 39 virtual ~CmdBufferImageTransportFactory(); 40 41 virtual GLHelper* GetGLHelper() OVERRIDE; 42 virtual uint32 GetChannelID() OVERRIDE { 43 return BrowserGpuChannelHostFactory::instance()->GetGpuChannelId(); 44 } 45 46 private: 47 scoped_ptr<WebGraphicsContext3DCommandBufferImpl> context_; 48 scoped_ptr<GLHelper> gl_helper_; 49 50 DISALLOW_COPY_AND_ASSIGN(CmdBufferImageTransportFactory); 51}; 52 53CmdBufferImageTransportFactory::CmdBufferImageTransportFactory() { 54 BrowserGpuChannelHostFactory* factory = 55 BrowserGpuChannelHostFactory::instance(); 56 scoped_refptr<GpuChannelHost> gpu_channel_host(factory->EstablishGpuChannelSync( 57 CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE)); 58 DCHECK(gpu_channel_host); 59 60 blink::WebGraphicsContext3D::Attributes attrs; 61 attrs.shareResources = true; 62 GURL url("chrome://gpu/ImageTransportFactoryAndroid"); 63 static const size_t kBytesPerPixel = 4; 64 gfx::DeviceDisplayInfo display_info; 65 size_t full_screen_texture_size_in_bytes = display_info.GetDisplayHeight() * 66 display_info.GetDisplayWidth() * 67 kBytesPerPixel; 68 WebGraphicsContext3DCommandBufferImpl::SharedMemoryLimits limits; 69 limits.command_buffer_size = 64 * 1024; 70 limits.start_transfer_buffer_size = 64 * 1024; 71 limits.min_transfer_buffer_size = 64 * 1024; 72 limits.max_transfer_buffer_size = std::min( 73 3 * full_screen_texture_size_in_bytes, kDefaultMaxTransferBufferSize); 74 limits.mapped_memory_reclaim_limit = 75 WebGraphicsContext3DCommandBufferImpl::kNoLimit; 76 bool lose_context_when_out_of_memory = false; 77 context_.reset( 78 new WebGraphicsContext3DCommandBufferImpl(0, // offscreen 79 url, 80 gpu_channel_host.get(), 81 attrs, 82 lose_context_when_out_of_memory, 83 limits, 84 NULL)); 85 context_->setContextLostCallback(context_lost_listener_.get()); 86 if (context_->InitializeOnCurrentThread()) 87 context_->pushGroupMarkerEXT( 88 base::StringPrintf("CmdBufferImageTransportFactory-%p", 89 context_.get()).c_str()); 90} 91 92CmdBufferImageTransportFactory::~CmdBufferImageTransportFactory() { 93 context_->setContextLostCallback(NULL); 94} 95 96GLHelper* CmdBufferImageTransportFactory::GetGLHelper() { 97 if (!gl_helper_) 98 gl_helper_.reset(new GLHelper(context_->GetImplementation(), 99 context_->GetContextSupport())); 100 101 return gl_helper_.get(); 102} 103 104} // anonymous namespace 105 106// static 107void ImageTransportFactoryAndroid::InitializeForUnitTests( 108 scoped_ptr<ImageTransportFactoryAndroid> test_factory) { 109 DCHECK(!g_factory); 110 g_factory = test_factory.release(); 111} 112 113// static 114void ImageTransportFactoryAndroid::TerminateForUnitTests() { 115 DCHECK(g_factory); 116 delete g_factory; 117 g_factory = NULL; 118} 119 120// static 121ImageTransportFactoryAndroid* ImageTransportFactoryAndroid::GetInstance() { 122 if (!g_factory) 123 g_factory = new CmdBufferImageTransportFactory(); 124 125 return g_factory; 126} 127 128ImageTransportFactoryAndroid::ImageTransportFactoryAndroid() 129 : context_lost_listener_(new GLContextLostListener()) {} 130 131ImageTransportFactoryAndroid::~ImageTransportFactoryAndroid() {} 132 133void ImageTransportFactoryAndroid::AddObserver( 134 ImageTransportFactoryAndroidObserver* observer) { 135 g_factory_observers.Get().AddObserver(observer); 136} 137 138void ImageTransportFactoryAndroid::RemoveObserver( 139 ImageTransportFactoryAndroidObserver* observer) { 140 g_factory_observers.Get().RemoveObserver(observer); 141} 142 143void GLContextLostListener::onContextLost() { 144 // Need to post a task because the command buffer client cannot be deleted 145 // from within this callback. 146 LOG(ERROR) << "Context lost."; 147 base::MessageLoop::current()->PostTask( 148 FROM_HERE, 149 base::Bind(&GLContextLostListener::DidLoseContext)); 150} 151 152void GLContextLostListener::DidLoseContext() { 153 delete g_factory; 154 g_factory = NULL; 155 FOR_EACH_OBSERVER(ImageTransportFactoryAndroidObserver, 156 g_factory_observers.Get(), 157 OnLostResources()); 158} 159 160} // namespace content 161