Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(315)

Side by Side Diff: blimp/client/android/compositor/blimp_compositor.cc

Issue 1295243003: Initial commit of the blimp/ folder and target (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 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 "blimp/client/android/compositor/blimp_compositor.h"
6
7 #include <android/native_window_jni.h>
8
9 #include "base/bind_helpers.h"
10 #include "base/command_line.h"
11 #include "base/lazy_instance.h"
12 #include "base/single_thread_task_runner.h"
13 #include "base/strings/string_number_conversions.h"
14 #include "base/strings/string_split.h"
15 #include "base/sys_info.h"
16 #include "base/thread_task_runner_handle.h"
17 #include "base/threading/simple_thread.h"
18 #include "base/threading/thread.h"
19 #include "base/threading/thread_local.h"
20 #include "base/threading/thread_restrictions.h"
21 #include "blimp/client/android/compositor/blimp_context_provider.h"
22 #include "blimp/client/android/compositor/blimp_output_surface.h"
23 #include "cc/base/switches.h"
24 #include "cc/layers/layer.h"
25 #include "cc/layers/solid_color_layer.h"
26 #include "cc/output/output_surface.h"
27 #include "cc/raster/task_graph_runner.h"
28 #include "cc/trees/layer_tree_host.h"
29 #include "content/public/common/content_switches.h"
30 #include "ui/gl/gl_surface.h"
31
32 namespace {
33
34 class SingleThreadTaskGraphRunner
35 : public cc::TaskGraphRunner,
36 public base::DelegateSimpleThread::Delegate {
37 public:
38 SingleThreadTaskGraphRunner()
39 : worker_thread_(
40 this,
41 "CompositorTileWorker1",
42 base::SimpleThread::Options(base::ThreadPriority::BACKGROUND)) {
43 worker_thread_.Start();
44 }
45
46 ~SingleThreadTaskGraphRunner() override {
47 Shutdown();
48 worker_thread_.Join();
49 }
50
51 private:
52 // Overridden from base::DelegateSimpleThread::Delegate:
53 void Run() override { cc::TaskGraphRunner::Run(); }
54
55 base::DelegateSimpleThread worker_thread_;
56 };
57
58 base::LazyInstance<SingleThreadTaskGraphRunner> g_task_graph_runner =
59 LAZY_INSTANCE_INITIALIZER;
60
61 bool GetSwitchValueAsInt(const base::CommandLine& command_line,
62 const std::string& switch_string,
63 int min_value,
64 int max_value,
65 int* result) {
66 std::string string_value = command_line.GetSwitchValueASCII(switch_string);
67 int int_value;
68 if (base::StringToInt(string_value, &int_value) && int_value >= min_value &&
69 int_value <= max_value) {
70 *result = int_value;
71 return true;
72 } else {
73 return false;
74 }
75 }
76
77 void StringToUintVector(const std::string& str, std::vector<unsigned>* vector) {
78 DCHECK(vector->empty());
79 std::vector<std::string> pieces =
80 base::SplitString(str, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
81 DCHECK_EQ(pieces.size(), static_cast<size_t>(gfx::BufferFormat::LAST) + 1);
82 for (size_t i = 0; i < pieces.size(); ++i) {
83 unsigned number = 0;
84 bool succeed = base::StringToUint(pieces[i], &number);
85 DCHECK(succeed);
86 vector->push_back(number);
87 }
88 }
89
90 bool GetSwitchValueAsUInt(const base::CommandLine& command_line,
91 const std::string& switch_string,
92 unsigned min_value,
93 unsigned max_value,
94 unsigned* result) {
95 std::string string_value = command_line.GetSwitchValueASCII(switch_string);
96 unsigned uint_value;
97 if (base::StringToUint(string_value, &uint_value) &&
98 uint_value >= min_value && uint_value <= max_value) {
99 *result = uint_value;
100 return true;
101 } else {
102 return false;
103 }
104 }
105
106 gfx::Size CalculateDefaultTileSize(const gfx::Size& physical_size,
107 const gfx::Size& display_size) {
108 int default_tile_size = 256;
109 bool real_size_supported = true;
110 int display_width = physical_size.width();
111 int display_height = physical_size.height();
112 if (display_width == 0 || display_height == 0) {
113 real_size_supported = false;
114 display_width = display_size.width();
115 display_height = display_size.height();
116 }
117
118 int portrait_width = std::min(display_width, display_height);
119 int landscape_width = std::max(display_width, display_height);
120
121 if (real_size_supported) {
122 // Maximum HD dimensions should be 768x1280
123 // Maximum FHD dimensions should be 1200x1920
124 if (portrait_width > 768 || landscape_width > 1280)
125 default_tile_size = 384;
126 if (portrait_width > 1200 || landscape_width > 1920)
127 default_tile_size = 512;
128
129 // Adjust for some resolutions that barely straddle an extra
130 // tile when in portrait mode. This helps worst case scroll/raster
131 // by not needing a full extra tile for each row.
132 if (default_tile_size == 256 && portrait_width == 768)
133 default_tile_size += 32;
134 if (default_tile_size == 384 && portrait_width == 1200)
135 default_tile_size += 32;
136 } else {
137 // We don't know the exact resolution due to screen controls etc.
nyquist 2015/08/19 07:48:06 Optional nit: Add comma at end of line, and lowerc
David Trainor- moved to gerrit 2015/08/21 00:49:46 Done.
138 // So this just estimates the values above using tile counts.
139 int numTiles = (display_width * display_height) / (256 * 256);
140 if (numTiles > 16)
141 default_tile_size = 384;
142 if (numTiles >= 40)
143 default_tile_size = 512;
144 }
145
146 return gfx::Size(default_tile_size, default_tile_size);
147 }
148
149 void PopulateLayerTreeSettings(cc::LayerTreeSettings& settings,
150 const gfx::Size& physical_size,
151 const gfx::Size& display_size) {
152 base::CommandLine* cmd = base::CommandLine::ForCurrentProcess();
153
154 // For web contents, layer transforms should scale up the contents of layers
155 // to keep content always crisp when possible.
156 settings.layer_transforms_should_scale_layer_contents = true;
157
158 if (cmd->HasSwitch(switches::kDisableGpuVsync)) {
159 std::string display_vsync_string =
160 cmd->GetSwitchValueASCII(switches::kDisableGpuVsync);
161 if (display_vsync_string == "gpu") {
162 settings.renderer_settings.disable_display_vsync = true;
163 } else if (display_vsync_string == "beginframe") {
164 settings.wait_for_beginframe_interval = false;
165 } else {
166 settings.renderer_settings.disable_display_vsync = true;
167 settings.wait_for_beginframe_interval = false;
168 }
169 }
170 settings.main_frame_before_activation_enabled =
171 cmd->HasSwitch(cc::switches::kEnableMainFrameBeforeActivation) &&
172 !cmd->HasSwitch(cc::switches::kDisableMainFrameBeforeActivation);
173 settings.accelerated_animation_enabled =
174 !cmd->HasSwitch(cc::switches::kDisableThreadedAnimation);
175 settings.use_display_lists = cmd->HasSwitch(switches::kEnableSlimmingPaint);
176 // if (cmd->HasSwitch(switches::kEnableCompositorAnimationTimelines)) {
177 // settings.use_compositor_animation_timelines = true;
178 // blink::WebRuntimeFeatures::enableCompositorAnimationTimelines(true);
179 //}
180
181 settings.default_tile_size =
182 CalculateDefaultTileSize(physical_size, display_size);
183 if (cmd->HasSwitch(switches::kDefaultTileWidth)) {
184 int tile_width = 0;
185 GetSwitchValueAsInt(*cmd, switches::kDefaultTileWidth, 1,
186 std::numeric_limits<int>::max(), &tile_width);
187 settings.default_tile_size.set_width(tile_width);
188 }
189 if (cmd->HasSwitch(switches::kDefaultTileHeight)) {
190 int tile_height = 0;
191 GetSwitchValueAsInt(*cmd, switches::kDefaultTileHeight, 1,
192 std::numeric_limits<int>::max(), &tile_height);
193 settings.default_tile_size.set_height(tile_height);
194 }
195
196 int max_untiled_layer_width = settings.max_untiled_layer_size.width();
197 if (cmd->HasSwitch(switches::kMaxUntiledLayerWidth)) {
198 GetSwitchValueAsInt(*cmd, switches::kMaxUntiledLayerWidth, 1,
199 std::numeric_limits<int>::max(),
200 &max_untiled_layer_width);
201 }
202 int max_untiled_layer_height = settings.max_untiled_layer_size.height();
203 if (cmd->HasSwitch(switches::kMaxUntiledLayerHeight)) {
204 GetSwitchValueAsInt(*cmd, switches::kMaxUntiledLayerHeight, 1,
205 std::numeric_limits<int>::max(),
206 &max_untiled_layer_height);
207 }
208
209 settings.max_untiled_layer_size =
210 gfx::Size(max_untiled_layer_width, max_untiled_layer_height);
211
212 settings.gpu_rasterization_msaa_sample_count = 0;
213 if (cmd->HasSwitch(switches::kGpuRasterizationMSAASampleCount)) {
214 GetSwitchValueAsInt(*cmd, switches::kGpuRasterizationMSAASampleCount, 0,
215 std::numeric_limits<int>::max(),
216 &settings.gpu_rasterization_msaa_sample_count);
217 }
218
219 settings.gpu_rasterization_forced =
220 cmd->HasSwitch(switches::kForceGpuRasterization);
221 settings.gpu_rasterization_enabled =
222 cmd->HasSwitch(switches::kEnableGpuRasterization);
223
224 settings.can_use_lcd_text = false;
225 settings.use_distance_field_text =
226 cmd->HasSwitch(switches::kEnableDistanceFieldText);
227
228 settings.use_zero_copy = cmd->HasSwitch(switches::kEnableZeroCopy);
229 settings.use_one_copy = !cmd->HasSwitch(switches::kDisableOneCopy);
230 settings.enable_elastic_overscroll = false;
231
232 if (cmd->HasSwitch(switches::kContentImageTextureTarget)) {
233 settings.use_image_texture_targets.clear();
234 StringToUintVector(
235 cmd->GetSwitchValueASCII(switches::kContentImageTextureTarget),
236 &settings.use_image_texture_targets);
237 }
238
239 settings.gather_pixel_refs = false;
240 if (cmd->HasSwitch(switches::kNumRasterThreads)) {
241 int num_raster_threads = 0;
242 GetSwitchValueAsInt(*cmd, switches::kNumRasterThreads, 0,
243 std::numeric_limits<int>::max(), &num_raster_threads);
244 settings.gather_pixel_refs = num_raster_threads > 1;
245 }
246
247 if (cmd->HasSwitch(cc::switches::kTopControlsShowThreshold)) {
248 std::string top_threshold_str =
249 cmd->GetSwitchValueASCII(cc::switches::kTopControlsShowThreshold);
250 double show_threshold;
251 if (base::StringToDouble(top_threshold_str, &show_threshold) &&
252 show_threshold >= 0.f && show_threshold <= 1.f)
253 settings.top_controls_show_threshold = show_threshold;
254 }
255
256 if (cmd->HasSwitch(cc::switches::kTopControlsHideThreshold)) {
257 std::string top_threshold_str =
258 cmd->GetSwitchValueASCII(cc::switches::kTopControlsHideThreshold);
259 double hide_threshold;
260 if (base::StringToDouble(top_threshold_str, &hide_threshold) &&
261 hide_threshold >= 0.f && hide_threshold <= 1.f)
262 settings.top_controls_hide_threshold = hide_threshold;
263 }
264
265 settings.verify_property_trees =
266 cmd->HasSwitch(cc::switches::kEnablePropertyTreeVerification);
267 settings.renderer_settings.allow_antialiasing &=
268 !cmd->HasSwitch(cc::switches::kDisableCompositedAntialiasing);
269 // The means the renderer compositor has 2 possible modes:
270 // - Threaded compositing with a scheduler.
271 // - Single threaded compositing without a scheduler (for layout tests only).
272 // Using the scheduler in layout tests introduces additional composite steps
273 // that create flakiness.
274 settings.single_thread_proxy_scheduler = false;
275
276 // These flags should be mirrored by UI versions in ui/compositor/.
277 settings.initial_debug_state.show_debug_borders =
278 cmd->HasSwitch(cc::switches::kShowCompositedLayerBorders);
279 settings.initial_debug_state.show_fps_counter =
280 cmd->HasSwitch(cc::switches::kShowFPSCounter);
281 settings.initial_debug_state.show_layer_animation_bounds_rects =
282 cmd->HasSwitch(cc::switches::kShowLayerAnimationBounds);
283 settings.initial_debug_state.show_paint_rects =
284 cmd->HasSwitch(switches::kShowPaintRects);
285 settings.initial_debug_state.show_property_changed_rects =
286 cmd->HasSwitch(cc::switches::kShowPropertyChangedRects);
287 settings.initial_debug_state.show_surface_damage_rects =
288 cmd->HasSwitch(cc::switches::kShowSurfaceDamageRects);
289 settings.initial_debug_state.show_screen_space_rects =
290 cmd->HasSwitch(cc::switches::kShowScreenSpaceRects);
291 settings.initial_debug_state.show_replica_screen_space_rects =
292 cmd->HasSwitch(cc::switches::kShowReplicaScreenSpaceRects);
293
294 settings.initial_debug_state.SetRecordRenderingStats(
295 cmd->HasSwitch(cc::switches::kEnableGpuBenchmarking));
296
297 if (cmd->HasSwitch(cc::switches::kSlowDownRasterScaleFactor)) {
298 const int kMinSlowDownScaleFactor = 0;
299 const int kMaxSlowDownScaleFactor = INT_MAX;
300 GetSwitchValueAsInt(
301 *cmd, cc::switches::kSlowDownRasterScaleFactor, kMinSlowDownScaleFactor,
302 kMaxSlowDownScaleFactor,
303 &settings.initial_debug_state.slow_down_raster_scale_factor);
304 }
305
306 settings.invert_viewport_scroll_order =
307 cmd->HasSwitch(switches::kInvertViewportScrollOrder);
308
309 if (cmd->HasSwitch(cc::switches::kMaxUnusedResourceMemoryUsagePercentage)) {
310 int max_unused_resource_memory_percentage;
311 if (GetSwitchValueAsInt(
312 *cmd, cc::switches::kMaxUnusedResourceMemoryUsagePercentage, 0, 100,
313 &max_unused_resource_memory_percentage)) {
314 settings.max_unused_resource_memory_percentage =
315 max_unused_resource_memory_percentage;
316 }
317 }
318
319 settings.strict_layer_property_change_checking =
320 cmd->HasSwitch(cc::switches::kStrictLayerPropertyChangeChecking);
321
322 #if defined(OS_ANDROID)
323 bool has_synchronous_compositor_factory = false;
324 // SynchronousCompositorFactory* synchronous_compositor_factory =
325 // SynchronousCompositorFactory::GetInstance();
326
327 // We can't use GPU rasterization on low-end devices, because the Ganesh
328 // cache would consume too much memory.
329 if (base::SysInfo::IsLowEndDevice())
330 settings.gpu_rasterization_enabled = false;
331 settings.using_synchronous_renderer_compositor =
332 has_synchronous_compositor_factory;
333 settings.record_full_layer = false; // widget_->DoesRecordFullLayer();
334 settings.max_partial_texture_updates = 0;
335 if (has_synchronous_compositor_factory) {
nyquist 2015/08/19 07:48:06 Would we be certain to get one of these blocks alw
336 // Android WebView uses system scrollbars, so make ours invisible.
337 settings.scrollbar_animator = cc::LayerTreeSettings::NO_ANIMATOR;
338 settings.solid_color_scrollbar_color = SK_ColorTRANSPARENT;
339 } else {
340 settings.scrollbar_animator = cc::LayerTreeSettings::LINEAR_FADE;
341 settings.scrollbar_fade_delay_ms = 300;
342 settings.scrollbar_fade_resize_delay_ms = 2000;
343 settings.scrollbar_fade_duration_ms = 300;
344 settings.solid_color_scrollbar_color = SkColorSetARGB(128, 128, 128, 128);
345 }
346 settings.renderer_settings.highp_threshold_min = 2048;
347 // Android WebView handles root layer flings itself.
348 settings.ignore_root_layer_flings = has_synchronous_compositor_factory;
349 // Memory policy on Android WebView does not depend on whether device is
350 // low end, so always use default policy.
351 bool use_low_memory_policy =
352 base::SysInfo::IsLowEndDevice() && !has_synchronous_compositor_factory;
353 // RGBA_4444 textures are only enabled for low end devices
354 // and are disabled for Android WebView as it doesn't support the format.
355 settings.renderer_settings.use_rgba_4444_textures = use_low_memory_policy;
356 if (use_low_memory_policy) {
357 // On low-end we want to be very carefull about killing other
358 // apps. So initially we use 50% more memory to avoid flickering
359 // or raster-on-demand.
360 settings.max_memory_for_prepaint_percentage = 67;
361 } else {
362 // On other devices we have increased memory excessively to avoid
363 // raster-on-demand already, so now we reserve 50% _only_ to avoid
364 // raster-on-demand, and use 50% of the memory otherwise.
365 settings.max_memory_for_prepaint_percentage = 50;
366 }
367 // Webview does not own the surface so should not clear it.
368 settings.renderer_settings.should_clear_root_render_pass =
369 !has_synchronous_compositor_factory;
370
371 // TODO(danakj): Only do this on low end devices.
372 settings.create_low_res_tiling = true;
373
374 // settings.use_external_begin_frame_source = true;
375
376 #elif !defined(OS_MACOSX)
377 if (ui::IsOverlayScrollbarEnabled()) {
378 settings.scrollbar_animator = cc::LayerTreeSettings::THINNING;
379 settings.solid_color_scrollbar_color = SkColorSetARGB(128, 128, 128, 128);
380 } else {
381 settings.scrollbar_animator = cc::LayerTreeSettings::LINEAR_FADE;
382 settings.solid_color_scrollbar_color = SkColorSetARGB(128, 128, 128, 128);
383 }
384 settings.scrollbar_fade_delay_ms = 500;
385 settings.scrollbar_fade_resize_delay_ms = 500;
386 settings.scrollbar_fade_duration_ms = 300;
387
388 // When pinching in, only show the pinch-viewport overlay scrollbars if the
389 // page scale is at least some threshold away from the minimum. i.e. don't
390 // show the pinch scrollbars when at minimum scale.
391 settings.scrollbar_show_scale_threshold = 1.05f;
392 #endif
393
394 if (cmd->HasSwitch(switches::kEnableLowResTiling))
395 settings.create_low_res_tiling = true;
396 if (cmd->HasSwitch(switches::kDisableLowResTiling))
397 settings.create_low_res_tiling = false;
398 if (cmd->HasSwitch(cc::switches::kEnableBeginFrameScheduling))
399 settings.use_external_begin_frame_source = true;
400 }
401
402 } // namespace
403
404 namespace blimp {
405
406 scoped_ptr<BlimpCompositor> BlimpCompositor::Create(
407 const gfx::Size& physical_size,
408 const gfx::Size& display_size,
409 float device_scale_factor) {
410 return make_scoped_ptr(
411 new BlimpCompositor(physical_size, display_size, device_scale_factor));
412 }
413
414 BlimpCompositor::BlimpCompositor(const gfx::Size& physical_size,
415 const gfx::Size& display_size,
416 float device_scale_factor)
417 : device_scale_factor_(device_scale_factor),
418 window_(nullptr),
419 weak_factory_(this) {
420 PopulateLayerTreeSettings(settings_, physical_size, display_size);
421 }
422
423 BlimpCompositor::~BlimpCompositor() {}
424
425 void BlimpCompositor::SetSurface(JNIEnv* env, jobject jsurface) {
426 if (window_) {
427 ANativeWindow_release(window_);
428 window_ = nullptr;
429 SetVisible(false);
430 }
431
432 if (!jsurface)
433 return;
434
435 base::android::ScopedJavaLocalFrame scoped_local_reference_frame(env);
436 window_ = ANativeWindow_fromSurface(env, jsurface);
437 // TODO(dtrainor): Investigate ref counts!
438 // ANativeWindow_acquire(window_);
439 // ANativeWindow_release(window_);
440
441 SetVisible(true);
442 }
443
444 void BlimpCompositor::SetVisible(bool visible) {
445 if (visible && !host_) {
446 // Create the LayerTreeHost
447 cc::LayerTreeHost::InitParams params;
448 params.client = this;
449 params.shared_bitmap_manager = nullptr;
450 params.gpu_memory_buffer_manager = nullptr;
451 params.task_graph_runner = g_task_graph_runner.Pointer();
452 params.main_task_runner = base::ThreadTaskRunnerHandle::Get();
453 params.settings = &settings_;
454 host_ =
455 cc::LayerTreeHost::CreateThreaded(GetCompositorTaskRunner(), &params);
456
457 host_->SetVisible(true);
458 host_->SetLayerTreeHostClientReady();
459 host_->SetViewportSize(viewport_size_);
460 host_->SetDeviceScaleFactor(device_scale_factor_);
461
462 // Dummy Layers
463 scoped_refptr<cc::Layer> root(
464 cc::SolidColorLayer::Create(cc::LayerSettings()));
465 root->SetBounds(gfx::Size(300, 300));
466 root->SetBackgroundColor(SK_ColorRED);
467 root->SetIsDrawable(true);
468 host_->SetRootLayer(root);
469
470 } else if (!visible && host_) {
471 // Destroy the LayerTreeHost
472 host_.reset();
473 }
474 }
475
476 void BlimpCompositor::SetSize(const gfx::Size& size) {
477 viewport_size_ = size;
478 if (host_)
479 host_->SetViewportSize(viewport_size_);
480 }
481
482 void BlimpCompositor::Layout() {}
483
484 void BlimpCompositor::RequestNewOutputSurface() {
485 scoped_refptr<BlimpContextProvider> context_provider =
486 BlimpContextProvider::Create(window_);
487
488 scoped_ptr<cc::OutputSurface> output_surface(
489 new BlimpOutputSurface(context_provider));
490
491 host_->SetOutputSurface(output_surface.Pass());
492 }
493
494 void BlimpCompositor::DidInitializeOutputSurface() {}
495
496 void BlimpCompositor::DidFailToInitializeOutputSurface() {}
497
498 void BlimpCompositor::DidCommit() {}
499
500 void BlimpCompositor::DidCompleteSwapBuffers() {}
501
502 void BlimpCompositor::ScheduleComposite() {}
503
504 void BlimpCompositor::ScheduleAnimation() {}
505
506 void BlimpCompositor::DidPostSwapBuffers() {}
507
508 void BlimpCompositor::DidAbortSwapBuffers() {}
509
510 scoped_refptr<base::SingleThreadTaskRunner>
511 BlimpCompositor::GetCompositorTaskRunner() {
512 if (!compositor_thread_) {
513 base::Thread::Options thread_options;
514 #if defined(OS_ANDROID)
515 thread_options.priority = base::ThreadPriority::DISPLAY;
516 #endif
517 compositor_thread_.reset(new base::Thread("Compositor"));
518 compositor_thread_->StartWithOptions(thread_options);
519
520 scoped_refptr<base::SingleThreadTaskRunner> task_runner =
521 compositor_thread_->task_runner();
522 task_runner->PostTask(
523 FROM_HERE,
524 base::Bind(base::IgnoreResult(&base::ThreadRestrictions::SetIOAllowed),
525 false));
526
527 return task_runner;
528 } else {
529 return compositor_thread_->task_runner();
530 }
531 }
532
533 } // namespace blimp
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698