OLD | NEW |
| (Empty) |
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 "ui/gfx/compositor/compositor_cc.h" | |
6 | |
7 #include "base/command_line.h" | |
8 #include "third_party/skia/include/images/SkImageEncoder.h" | |
9 #include "third_party/skia/include/core/SkBitmap.h" | |
10 #include "third_party/WebKit/Source/WebKit/chromium/public/WebCompositor.h" | |
11 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebFloatPoin
t.h" | |
12 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebRect.h" | |
13 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebSize.h" | |
14 #include "ui/gfx/compositor/compositor_switches.h" | |
15 #include "ui/gfx/compositor/test_web_graphics_context_3d.h" | |
16 #include "ui/gfx/compositor/layer.h" | |
17 #include "ui/gfx/gl/gl_context.h" | |
18 #include "ui/gfx/gl/gl_surface.h" | |
19 #include "ui/gfx/gl/gl_implementation.h" | |
20 #include "ui/gfx/gl/scoped_make_current.h" | |
21 #include "webkit/glue/webthread_impl.h" | |
22 #include "webkit/gpu/webgraphicscontext3d_in_process_impl.h" | |
23 | |
24 namespace { | |
25 | |
26 const double kDefaultRefreshRate = 60.0; | |
27 const double kTestRefreshRate = 100.0; | |
28 | |
29 webkit_glue::WebThreadImpl* g_compositor_thread = NULL; | |
30 | |
31 bool test_compositor_enabled = false; | |
32 | |
33 } // anonymous namespace | |
34 | |
35 namespace ui { | |
36 | |
37 SharedResourcesCC::SharedResourcesCC() : initialized_(false) { | |
38 } | |
39 | |
40 | |
41 SharedResourcesCC::~SharedResourcesCC() { | |
42 } | |
43 | |
44 // static | |
45 SharedResourcesCC* SharedResourcesCC::GetInstance() { | |
46 // We use LeakySingletonTraits so that we don't race with | |
47 // the tear down of the gl_bindings. | |
48 SharedResourcesCC* instance = Singleton<SharedResourcesCC, | |
49 LeakySingletonTraits<SharedResourcesCC> >::get(); | |
50 if (instance->Initialize()) { | |
51 return instance; | |
52 } else { | |
53 instance->Destroy(); | |
54 return NULL; | |
55 } | |
56 } | |
57 | |
58 bool SharedResourcesCC::Initialize() { | |
59 if (initialized_) | |
60 return true; | |
61 | |
62 { | |
63 // The following line of code exists soley to disable IO restrictions | |
64 // on this thread long enough to perform the GL bindings. | |
65 // TODO(wjmaclean) Remove this when GL initialisation cleaned up. | |
66 base::ThreadRestrictions::ScopedAllowIO allow_io; | |
67 if (!gfx::GLSurface::InitializeOneOff() || | |
68 gfx::GetGLImplementation() == gfx::kGLImplementationNone) { | |
69 LOG(ERROR) << "Could not load the GL bindings"; | |
70 return false; | |
71 } | |
72 } | |
73 | |
74 surface_ = gfx::GLSurface::CreateOffscreenGLSurface(false, gfx::Size(1, 1)); | |
75 if (!surface_.get()) { | |
76 LOG(ERROR) << "Unable to create offscreen GL surface."; | |
77 return false; | |
78 } | |
79 | |
80 context_ = gfx::GLContext::CreateGLContext( | |
81 NULL, surface_.get(), gfx::PreferIntegratedGpu); | |
82 if (!context_.get()) { | |
83 LOG(ERROR) << "Unable to create GL context."; | |
84 return false; | |
85 } | |
86 | |
87 initialized_ = true; | |
88 return true; | |
89 } | |
90 | |
91 void SharedResourcesCC::Destroy() { | |
92 context_ = NULL; | |
93 surface_ = NULL; | |
94 | |
95 initialized_ = false; | |
96 } | |
97 | |
98 gfx::ScopedMakeCurrent* SharedResourcesCC::GetScopedMakeCurrent() { | |
99 DCHECK(initialized_); | |
100 if (initialized_) | |
101 return new gfx::ScopedMakeCurrent(context_.get(), surface_.get()); | |
102 else | |
103 return NULL; | |
104 } | |
105 | |
106 void* SharedResourcesCC::GetDisplay() { | |
107 return surface_->GetDisplay(); | |
108 } | |
109 | |
110 gfx::GLShareGroup* SharedResourcesCC::GetShareGroup() { | |
111 DCHECK(initialized_); | |
112 return context_->share_group(); | |
113 } | |
114 | |
115 TextureCC::TextureCC() | |
116 : texture_id_(0), | |
117 flipped_(false) { | |
118 } | |
119 | |
120 void TextureCC::SetCanvas(const SkCanvas& canvas, | |
121 const gfx::Point& origin, | |
122 const gfx::Size& overall_size) { | |
123 NOTREACHED(); | |
124 } | |
125 | |
126 void TextureCC::Draw(const ui::TextureDrawParams& params, | |
127 const gfx::Rect& clip_bounds_in_texture) { | |
128 NOTREACHED(); | |
129 } | |
130 | |
131 CompositorCC::CompositorCC(CompositorDelegate* delegate, | |
132 gfx::AcceleratedWidget widget, | |
133 const gfx::Size& size) | |
134 : Compositor(delegate, size), | |
135 widget_(widget), | |
136 root_web_layer_(WebKit::WebLayer::create()) { | |
137 WebKit::WebLayerTreeView::Settings settings; | |
138 CommandLine* command_line = CommandLine::ForCurrentProcess(); | |
139 settings.showFPSCounter = | |
140 command_line->HasSwitch(switches::kUIShowFPSCounter); | |
141 settings.showPlatformLayerTree = | |
142 command_line->HasSwitch(switches::kUIShowLayerTree); | |
143 settings.refreshRate = test_compositor_enabled ? | |
144 kTestRefreshRate : kDefaultRefreshRate; | |
145 settings.partialSwapEnabled = | |
146 command_line->HasSwitch(switches::kUIEnablePartialSwap); | |
147 | |
148 #ifndef WEBCOMPOSITOR_HAS_INITIALIZE | |
149 settings.enableCompositorThread = !!g_compositor_thread; | |
150 #endif | |
151 host_ = WebKit::WebLayerTreeView::create(this, root_web_layer_, settings); | |
152 root_web_layer_.setAnchorPoint(WebKit::WebFloatPoint(0.f, 0.f)); | |
153 OnWidgetSizeChanged(); | |
154 } | |
155 | |
156 CompositorCC::~CompositorCC() { | |
157 // There's a cycle between |root_web_layer_| and |host_|, which results in | |
158 // leaking and/or crashing. Explicitly set the root layer to NULL so the cycle | |
159 // is broken. | |
160 host_.setRootLayer(NULL); | |
161 } | |
162 | |
163 void CompositorCC::Initialize(bool use_thread) { | |
164 if (use_thread) | |
165 g_compositor_thread = new webkit_glue::WebThreadImpl("Browser Compositor"); | |
166 #ifdef WEBCOMPOSITOR_HAS_INITIALIZE | |
167 WebKit::WebCompositor::initialize(g_compositor_thread); | |
168 #else | |
169 if (use_thread) | |
170 WebKit::WebCompositor::setThread(g_compositor_thread); | |
171 #endif | |
172 } | |
173 | |
174 void CompositorCC::Terminate() { | |
175 #ifdef WEBCOMPOSITOR_HAS_INITIALIZE | |
176 WebKit::WebCompositor::shutdown(); | |
177 #endif | |
178 if (g_compositor_thread) { | |
179 delete g_compositor_thread; | |
180 g_compositor_thread = NULL; | |
181 } | |
182 } | |
183 | |
184 Texture* CompositorCC::CreateTexture() { | |
185 NOTREACHED(); | |
186 return NULL; | |
187 } | |
188 | |
189 void CompositorCC::Blur(const gfx::Rect& bounds) { | |
190 NOTIMPLEMENTED(); | |
191 } | |
192 | |
193 void CompositorCC::ScheduleDraw() { | |
194 if (g_compositor_thread) | |
195 host_.composite(); | |
196 else | |
197 Compositor::ScheduleDraw(); | |
198 } | |
199 | |
200 void CompositorCC::OnNotifyStart(bool clear) { | |
201 } | |
202 | |
203 void CompositorCC::OnNotifyEnd() { | |
204 } | |
205 | |
206 void CompositorCC::OnWidgetSizeChanged() { | |
207 host_.setViewportSize(size()); | |
208 root_web_layer_.setBounds(size()); | |
209 } | |
210 | |
211 void CompositorCC::OnRootLayerChanged() { | |
212 root_web_layer_.removeAllChildren(); | |
213 if (root_layer()) | |
214 root_web_layer_.addChild(root_layer()->web_layer()); | |
215 } | |
216 | |
217 void CompositorCC::DrawTree() { | |
218 host_.composite(); | |
219 } | |
220 | |
221 bool CompositorCC::CompositesAsynchronously() { | |
222 return g_compositor_thread != NULL; | |
223 } | |
224 | |
225 bool CompositorCC::ReadPixels(SkBitmap* bitmap, const gfx::Rect& bounds) { | |
226 if (bounds.right() > size().width() || bounds.bottom() > size().height()) | |
227 return false; | |
228 // Convert to OpenGL coordinates. | |
229 gfx::Point new_origin(bounds.x(), | |
230 size().height() - bounds.height() - bounds.y()); | |
231 | |
232 bitmap->setConfig(SkBitmap::kARGB_8888_Config, | |
233 bounds.width(), bounds.height()); | |
234 bitmap->allocPixels(); | |
235 SkAutoLockPixels lock_image(*bitmap); | |
236 unsigned char* pixels = static_cast<unsigned char*>(bitmap->getPixels()); | |
237 if (host_.compositeAndReadback(pixels, | |
238 gfx::Rect(new_origin, bounds.size()))) { | |
239 SwizzleRGBAToBGRAAndFlip(pixels, bounds.size()); | |
240 return true; | |
241 } | |
242 return false; | |
243 } | |
244 | |
245 void CompositorCC::animateAndLayout(double frameBeginTime) { | |
246 } | |
247 | |
248 void CompositorCC::updateAnimations(double frameBeginTime) { | |
249 } | |
250 | |
251 void CompositorCC::layout() { | |
252 } | |
253 | |
254 void CompositorCC::applyScrollAndScale(const WebKit::WebSize& scrollDelta, | |
255 float scaleFactor) { | |
256 } | |
257 | |
258 void CompositorCC::applyScrollDelta(const WebKit::WebSize&) { | |
259 } | |
260 | |
261 WebKit::WebGraphicsContext3D* CompositorCC::createContext3D() { | |
262 WebKit::WebGraphicsContext3D* context; | |
263 if (test_compositor_enabled) { | |
264 // Use context that results in no rendering to the screen. | |
265 context = new TestWebGraphicsContext3D(); | |
266 } else { | |
267 #if defined(OS_MACOSX) && !defined(USE_AURA) | |
268 // Non-Aura builds compile this code but doesn't call it. Unfortunately | |
269 // this is where we translate gfx::AcceleratedWidget to | |
270 // gfx::PluginWindowHandle, and they are different on non-Aura Mac. | |
271 // TODO(piman): remove ifdefs when AcceleratedWidget is rationalized on Mac. | |
272 NOTIMPLEMENTED(); | |
273 return NULL; | |
274 #else | |
275 gfx::GLShareGroup* share_group = | |
276 SharedResourcesCC::GetInstance()->GetShareGroup(); | |
277 context = new webkit::gpu::WebGraphicsContext3DInProcessImpl( | |
278 widget_, share_group); | |
279 #endif | |
280 } | |
281 WebKit::WebGraphicsContext3D::Attributes attrs; | |
282 context->initialize(attrs, 0, true); | |
283 | |
284 CommandLine* command_line = CommandLine::ForCurrentProcess(); | |
285 if (!command_line->HasSwitch(switches::kDisableUIVsync)) { | |
286 context->makeContextCurrent(); | |
287 gfx::GLContext* gl_context = gfx::GLContext::GetCurrent(); | |
288 gl_context->SetSwapInterval(1); | |
289 gl_context->ReleaseCurrent(NULL); | |
290 } | |
291 | |
292 return context; | |
293 } | |
294 | |
295 void CompositorCC::didCompleteSwapBuffers() { | |
296 NotifyEnd(); | |
297 } | |
298 | |
299 void CompositorCC::didRebindGraphicsContext(bool success) { | |
300 } | |
301 | |
302 void CompositorCC::scheduleComposite() { | |
303 ScheduleDraw(); | |
304 } | |
305 | |
306 Compositor* Compositor::Create(CompositorDelegate* owner, | |
307 gfx::AcceleratedWidget widget, | |
308 const gfx::Size& size) { | |
309 return new CompositorCC(owner, widget, size); | |
310 } | |
311 | |
312 COMPOSITOR_EXPORT void SetupTestCompositor() { | |
313 if (!CommandLine::ForCurrentProcess()->HasSwitch( | |
314 switches::kDisableTestCompositor)) { | |
315 test_compositor_enabled = true; | |
316 } | |
317 } | |
318 | |
319 COMPOSITOR_EXPORT void DisableTestCompositor() { | |
320 test_compositor_enabled = false; | |
321 } | |
322 | |
323 } // namespace ui | |
OLD | NEW |