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
18 namespace content {
19
20 base::LazyInstance<ObserverList<ImageTransportFactoryAndroidObserver> >::Leaky
21 g_factory_observers = LAZY_INSTANCE_INITIALIZER;
22
23 class GLContextLostListener
24 : public blink::WebGraphicsContext3D::WebGraphicsContextLostCallback {
25 public:
26 // WebGraphicsContextLostCallback implementation.
27 virtual void onContextLost() OVERRIDE;
28 private:
29 static void DidLoseContext();
30 };
31
32 namespace {
33
34 static ImageTransportFactoryAndroid* g_factory = NULL;
35
36 class CmdBufferImageTransportFactory : public ImageTransportFactoryAndroid {
37 public:
38 CmdBufferImageTransportFactory();
39 virtual ~CmdBufferImageTransportFactory();
40
41 virtual GLHelper* GetGLHelper() OVERRIDE;
GetChannelID()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
CmdBufferImageTransportFactory()53 CmdBufferImageTransportFactory::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_->makeContextCurrent())
87 context_->pushGroupMarkerEXT(
88 base::StringPrintf("CmdBufferImageTransportFactory-%p",
89 context_.get()).c_str());
90 }
91
~CmdBufferImageTransportFactory()92 CmdBufferImageTransportFactory::~CmdBufferImageTransportFactory() {
93 context_->setContextLostCallback(NULL);
94 }
95
GetGLHelper()96 GLHelper* 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
GetInstance()107 ImageTransportFactoryAndroid* ImageTransportFactoryAndroid::GetInstance() {
108 if (!g_factory)
109 g_factory = new CmdBufferImageTransportFactory();
110
111 return g_factory;
112 }
113
ImageTransportFactoryAndroid()114 ImageTransportFactoryAndroid::ImageTransportFactoryAndroid()
115 : context_lost_listener_(new GLContextLostListener()) {}
116
~ImageTransportFactoryAndroid()117 ImageTransportFactoryAndroid::~ImageTransportFactoryAndroid() {}
118
AddObserver(ImageTransportFactoryAndroidObserver * observer)119 void ImageTransportFactoryAndroid::AddObserver(
120 ImageTransportFactoryAndroidObserver* observer) {
121 g_factory_observers.Get().AddObserver(observer);
122 }
123
RemoveObserver(ImageTransportFactoryAndroidObserver * observer)124 void ImageTransportFactoryAndroid::RemoveObserver(
125 ImageTransportFactoryAndroidObserver* observer) {
126 g_factory_observers.Get().RemoveObserver(observer);
127 }
128
onContextLost()129 void GLContextLostListener::onContextLost() {
130 // Need to post a task because the command buffer client cannot be deleted
131 // from within this callback.
132 LOG(ERROR) << "Context lost.";
133 base::MessageLoop::current()->PostTask(
134 FROM_HERE,
135 base::Bind(&GLContextLostListener::DidLoseContext));
136 }
137
DidLoseContext()138 void GLContextLostListener::DidLoseContext() {
139 delete g_factory;
140 g_factory = NULL;
141 FOR_EACH_OBSERVER(ImageTransportFactoryAndroidObserver,
142 g_factory_observers.Get(),
143 OnLostResources());
144 }
145
146 } // namespace content
147