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

Unified 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 side-by-side diff with in-line comments
Download patch
Index: blimp/client/android/compositor/blimp_compositor.cc
diff --git a/blimp/client/android/compositor/blimp_compositor.cc b/blimp/client/android/compositor/blimp_compositor.cc
new file mode 100644
index 0000000000000000000000000000000000000000..22f470f30c40952aaf111020b94907045fc515ac
--- /dev/null
+++ b/blimp/client/android/compositor/blimp_compositor.cc
@@ -0,0 +1,533 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "blimp/client/android/compositor/blimp_compositor.h"
+
+#include <android/native_window_jni.h>
+
+#include "base/bind_helpers.h"
+#include "base/command_line.h"
+#include "base/lazy_instance.h"
+#include "base/single_thread_task_runner.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_split.h"
+#include "base/sys_info.h"
+#include "base/thread_task_runner_handle.h"
+#include "base/threading/simple_thread.h"
+#include "base/threading/thread.h"
+#include "base/threading/thread_local.h"
+#include "base/threading/thread_restrictions.h"
+#include "blimp/client/android/compositor/blimp_context_provider.h"
+#include "blimp/client/android/compositor/blimp_output_surface.h"
+#include "cc/base/switches.h"
+#include "cc/layers/layer.h"
+#include "cc/layers/solid_color_layer.h"
+#include "cc/output/output_surface.h"
+#include "cc/raster/task_graph_runner.h"
+#include "cc/trees/layer_tree_host.h"
+#include "content/public/common/content_switches.h"
+#include "ui/gl/gl_surface.h"
+
+namespace {
+
+class SingleThreadTaskGraphRunner
+ : public cc::TaskGraphRunner,
+ public base::DelegateSimpleThread::Delegate {
+ public:
+ SingleThreadTaskGraphRunner()
+ : worker_thread_(
+ this,
+ "CompositorTileWorker1",
+ base::SimpleThread::Options(base::ThreadPriority::BACKGROUND)) {
+ worker_thread_.Start();
+ }
+
+ ~SingleThreadTaskGraphRunner() override {
+ Shutdown();
+ worker_thread_.Join();
+ }
+
+ private:
+ // Overridden from base::DelegateSimpleThread::Delegate:
+ void Run() override { cc::TaskGraphRunner::Run(); }
+
+ base::DelegateSimpleThread worker_thread_;
+};
+
+base::LazyInstance<SingleThreadTaskGraphRunner> g_task_graph_runner =
+ LAZY_INSTANCE_INITIALIZER;
+
+bool GetSwitchValueAsInt(const base::CommandLine& command_line,
+ const std::string& switch_string,
+ int min_value,
+ int max_value,
+ int* result) {
+ std::string string_value = command_line.GetSwitchValueASCII(switch_string);
+ int int_value;
+ if (base::StringToInt(string_value, &int_value) && int_value >= min_value &&
+ int_value <= max_value) {
+ *result = int_value;
+ return true;
+ } else {
+ return false;
+ }
+}
+
+void StringToUintVector(const std::string& str, std::vector<unsigned>* vector) {
+ DCHECK(vector->empty());
+ std::vector<std::string> pieces =
+ base::SplitString(str, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
+ DCHECK_EQ(pieces.size(), static_cast<size_t>(gfx::BufferFormat::LAST) + 1);
+ for (size_t i = 0; i < pieces.size(); ++i) {
+ unsigned number = 0;
+ bool succeed = base::StringToUint(pieces[i], &number);
+ DCHECK(succeed);
+ vector->push_back(number);
+ }
+}
+
+bool GetSwitchValueAsUInt(const base::CommandLine& command_line,
+ const std::string& switch_string,
+ unsigned min_value,
+ unsigned max_value,
+ unsigned* result) {
+ std::string string_value = command_line.GetSwitchValueASCII(switch_string);
+ unsigned uint_value;
+ if (base::StringToUint(string_value, &uint_value) &&
+ uint_value >= min_value && uint_value <= max_value) {
+ *result = uint_value;
+ return true;
+ } else {
+ return false;
+ }
+}
+
+gfx::Size CalculateDefaultTileSize(const gfx::Size& physical_size,
+ const gfx::Size& display_size) {
+ int default_tile_size = 256;
+ bool real_size_supported = true;
+ int display_width = physical_size.width();
+ int display_height = physical_size.height();
+ if (display_width == 0 || display_height == 0) {
+ real_size_supported = false;
+ display_width = display_size.width();
+ display_height = display_size.height();
+ }
+
+ int portrait_width = std::min(display_width, display_height);
+ int landscape_width = std::max(display_width, display_height);
+
+ if (real_size_supported) {
+ // Maximum HD dimensions should be 768x1280
+ // Maximum FHD dimensions should be 1200x1920
+ if (portrait_width > 768 || landscape_width > 1280)
+ default_tile_size = 384;
+ if (portrait_width > 1200 || landscape_width > 1920)
+ default_tile_size = 512;
+
+ // Adjust for some resolutions that barely straddle an extra
+ // tile when in portrait mode. This helps worst case scroll/raster
+ // by not needing a full extra tile for each row.
+ if (default_tile_size == 256 && portrait_width == 768)
+ default_tile_size += 32;
+ if (default_tile_size == 384 && portrait_width == 1200)
+ default_tile_size += 32;
+ } else {
+ // 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.
+ // So this just estimates the values above using tile counts.
+ int numTiles = (display_width * display_height) / (256 * 256);
+ if (numTiles > 16)
+ default_tile_size = 384;
+ if (numTiles >= 40)
+ default_tile_size = 512;
+ }
+
+ return gfx::Size(default_tile_size, default_tile_size);
+}
+
+void PopulateLayerTreeSettings(cc::LayerTreeSettings& settings,
+ const gfx::Size& physical_size,
+ const gfx::Size& display_size) {
+ base::CommandLine* cmd = base::CommandLine::ForCurrentProcess();
+
+ // For web contents, layer transforms should scale up the contents of layers
+ // to keep content always crisp when possible.
+ settings.layer_transforms_should_scale_layer_contents = true;
+
+ if (cmd->HasSwitch(switches::kDisableGpuVsync)) {
+ std::string display_vsync_string =
+ cmd->GetSwitchValueASCII(switches::kDisableGpuVsync);
+ if (display_vsync_string == "gpu") {
+ settings.renderer_settings.disable_display_vsync = true;
+ } else if (display_vsync_string == "beginframe") {
+ settings.wait_for_beginframe_interval = false;
+ } else {
+ settings.renderer_settings.disable_display_vsync = true;
+ settings.wait_for_beginframe_interval = false;
+ }
+ }
+ settings.main_frame_before_activation_enabled =
+ cmd->HasSwitch(cc::switches::kEnableMainFrameBeforeActivation) &&
+ !cmd->HasSwitch(cc::switches::kDisableMainFrameBeforeActivation);
+ settings.accelerated_animation_enabled =
+ !cmd->HasSwitch(cc::switches::kDisableThreadedAnimation);
+ settings.use_display_lists = cmd->HasSwitch(switches::kEnableSlimmingPaint);
+ // if (cmd->HasSwitch(switches::kEnableCompositorAnimationTimelines)) {
+ // settings.use_compositor_animation_timelines = true;
+ // blink::WebRuntimeFeatures::enableCompositorAnimationTimelines(true);
+ //}
+
+ settings.default_tile_size =
+ CalculateDefaultTileSize(physical_size, display_size);
+ if (cmd->HasSwitch(switches::kDefaultTileWidth)) {
+ int tile_width = 0;
+ GetSwitchValueAsInt(*cmd, switches::kDefaultTileWidth, 1,
+ std::numeric_limits<int>::max(), &tile_width);
+ settings.default_tile_size.set_width(tile_width);
+ }
+ if (cmd->HasSwitch(switches::kDefaultTileHeight)) {
+ int tile_height = 0;
+ GetSwitchValueAsInt(*cmd, switches::kDefaultTileHeight, 1,
+ std::numeric_limits<int>::max(), &tile_height);
+ settings.default_tile_size.set_height(tile_height);
+ }
+
+ int max_untiled_layer_width = settings.max_untiled_layer_size.width();
+ if (cmd->HasSwitch(switches::kMaxUntiledLayerWidth)) {
+ GetSwitchValueAsInt(*cmd, switches::kMaxUntiledLayerWidth, 1,
+ std::numeric_limits<int>::max(),
+ &max_untiled_layer_width);
+ }
+ int max_untiled_layer_height = settings.max_untiled_layer_size.height();
+ if (cmd->HasSwitch(switches::kMaxUntiledLayerHeight)) {
+ GetSwitchValueAsInt(*cmd, switches::kMaxUntiledLayerHeight, 1,
+ std::numeric_limits<int>::max(),
+ &max_untiled_layer_height);
+ }
+
+ settings.max_untiled_layer_size =
+ gfx::Size(max_untiled_layer_width, max_untiled_layer_height);
+
+ settings.gpu_rasterization_msaa_sample_count = 0;
+ if (cmd->HasSwitch(switches::kGpuRasterizationMSAASampleCount)) {
+ GetSwitchValueAsInt(*cmd, switches::kGpuRasterizationMSAASampleCount, 0,
+ std::numeric_limits<int>::max(),
+ &settings.gpu_rasterization_msaa_sample_count);
+ }
+
+ settings.gpu_rasterization_forced =
+ cmd->HasSwitch(switches::kForceGpuRasterization);
+ settings.gpu_rasterization_enabled =
+ cmd->HasSwitch(switches::kEnableGpuRasterization);
+
+ settings.can_use_lcd_text = false;
+ settings.use_distance_field_text =
+ cmd->HasSwitch(switches::kEnableDistanceFieldText);
+
+ settings.use_zero_copy = cmd->HasSwitch(switches::kEnableZeroCopy);
+ settings.use_one_copy = !cmd->HasSwitch(switches::kDisableOneCopy);
+ settings.enable_elastic_overscroll = false;
+
+ if (cmd->HasSwitch(switches::kContentImageTextureTarget)) {
+ settings.use_image_texture_targets.clear();
+ StringToUintVector(
+ cmd->GetSwitchValueASCII(switches::kContentImageTextureTarget),
+ &settings.use_image_texture_targets);
+ }
+
+ settings.gather_pixel_refs = false;
+ if (cmd->HasSwitch(switches::kNumRasterThreads)) {
+ int num_raster_threads = 0;
+ GetSwitchValueAsInt(*cmd, switches::kNumRasterThreads, 0,
+ std::numeric_limits<int>::max(), &num_raster_threads);
+ settings.gather_pixel_refs = num_raster_threads > 1;
+ }
+
+ if (cmd->HasSwitch(cc::switches::kTopControlsShowThreshold)) {
+ std::string top_threshold_str =
+ cmd->GetSwitchValueASCII(cc::switches::kTopControlsShowThreshold);
+ double show_threshold;
+ if (base::StringToDouble(top_threshold_str, &show_threshold) &&
+ show_threshold >= 0.f && show_threshold <= 1.f)
+ settings.top_controls_show_threshold = show_threshold;
+ }
+
+ if (cmd->HasSwitch(cc::switches::kTopControlsHideThreshold)) {
+ std::string top_threshold_str =
+ cmd->GetSwitchValueASCII(cc::switches::kTopControlsHideThreshold);
+ double hide_threshold;
+ if (base::StringToDouble(top_threshold_str, &hide_threshold) &&
+ hide_threshold >= 0.f && hide_threshold <= 1.f)
+ settings.top_controls_hide_threshold = hide_threshold;
+ }
+
+ settings.verify_property_trees =
+ cmd->HasSwitch(cc::switches::kEnablePropertyTreeVerification);
+ settings.renderer_settings.allow_antialiasing &=
+ !cmd->HasSwitch(cc::switches::kDisableCompositedAntialiasing);
+ // The means the renderer compositor has 2 possible modes:
+ // - Threaded compositing with a scheduler.
+ // - Single threaded compositing without a scheduler (for layout tests only).
+ // Using the scheduler in layout tests introduces additional composite steps
+ // that create flakiness.
+ settings.single_thread_proxy_scheduler = false;
+
+ // These flags should be mirrored by UI versions in ui/compositor/.
+ settings.initial_debug_state.show_debug_borders =
+ cmd->HasSwitch(cc::switches::kShowCompositedLayerBorders);
+ settings.initial_debug_state.show_fps_counter =
+ cmd->HasSwitch(cc::switches::kShowFPSCounter);
+ settings.initial_debug_state.show_layer_animation_bounds_rects =
+ cmd->HasSwitch(cc::switches::kShowLayerAnimationBounds);
+ settings.initial_debug_state.show_paint_rects =
+ cmd->HasSwitch(switches::kShowPaintRects);
+ settings.initial_debug_state.show_property_changed_rects =
+ cmd->HasSwitch(cc::switches::kShowPropertyChangedRects);
+ settings.initial_debug_state.show_surface_damage_rects =
+ cmd->HasSwitch(cc::switches::kShowSurfaceDamageRects);
+ settings.initial_debug_state.show_screen_space_rects =
+ cmd->HasSwitch(cc::switches::kShowScreenSpaceRects);
+ settings.initial_debug_state.show_replica_screen_space_rects =
+ cmd->HasSwitch(cc::switches::kShowReplicaScreenSpaceRects);
+
+ settings.initial_debug_state.SetRecordRenderingStats(
+ cmd->HasSwitch(cc::switches::kEnableGpuBenchmarking));
+
+ if (cmd->HasSwitch(cc::switches::kSlowDownRasterScaleFactor)) {
+ const int kMinSlowDownScaleFactor = 0;
+ const int kMaxSlowDownScaleFactor = INT_MAX;
+ GetSwitchValueAsInt(
+ *cmd, cc::switches::kSlowDownRasterScaleFactor, kMinSlowDownScaleFactor,
+ kMaxSlowDownScaleFactor,
+ &settings.initial_debug_state.slow_down_raster_scale_factor);
+ }
+
+ settings.invert_viewport_scroll_order =
+ cmd->HasSwitch(switches::kInvertViewportScrollOrder);
+
+ if (cmd->HasSwitch(cc::switches::kMaxUnusedResourceMemoryUsagePercentage)) {
+ int max_unused_resource_memory_percentage;
+ if (GetSwitchValueAsInt(
+ *cmd, cc::switches::kMaxUnusedResourceMemoryUsagePercentage, 0, 100,
+ &max_unused_resource_memory_percentage)) {
+ settings.max_unused_resource_memory_percentage =
+ max_unused_resource_memory_percentage;
+ }
+ }
+
+ settings.strict_layer_property_change_checking =
+ cmd->HasSwitch(cc::switches::kStrictLayerPropertyChangeChecking);
+
+#if defined(OS_ANDROID)
+ bool has_synchronous_compositor_factory = false;
+ // SynchronousCompositorFactory* synchronous_compositor_factory =
+ // SynchronousCompositorFactory::GetInstance();
+
+ // We can't use GPU rasterization on low-end devices, because the Ganesh
+ // cache would consume too much memory.
+ if (base::SysInfo::IsLowEndDevice())
+ settings.gpu_rasterization_enabled = false;
+ settings.using_synchronous_renderer_compositor =
+ has_synchronous_compositor_factory;
+ settings.record_full_layer = false; // widget_->DoesRecordFullLayer();
+ settings.max_partial_texture_updates = 0;
+ if (has_synchronous_compositor_factory) {
nyquist 2015/08/19 07:48:06 Would we be certain to get one of these blocks alw
+ // Android WebView uses system scrollbars, so make ours invisible.
+ settings.scrollbar_animator = cc::LayerTreeSettings::NO_ANIMATOR;
+ settings.solid_color_scrollbar_color = SK_ColorTRANSPARENT;
+ } else {
+ settings.scrollbar_animator = cc::LayerTreeSettings::LINEAR_FADE;
+ settings.scrollbar_fade_delay_ms = 300;
+ settings.scrollbar_fade_resize_delay_ms = 2000;
+ settings.scrollbar_fade_duration_ms = 300;
+ settings.solid_color_scrollbar_color = SkColorSetARGB(128, 128, 128, 128);
+ }
+ settings.renderer_settings.highp_threshold_min = 2048;
+ // Android WebView handles root layer flings itself.
+ settings.ignore_root_layer_flings = has_synchronous_compositor_factory;
+ // Memory policy on Android WebView does not depend on whether device is
+ // low end, so always use default policy.
+ bool use_low_memory_policy =
+ base::SysInfo::IsLowEndDevice() && !has_synchronous_compositor_factory;
+ // RGBA_4444 textures are only enabled for low end devices
+ // and are disabled for Android WebView as it doesn't support the format.
+ settings.renderer_settings.use_rgba_4444_textures = use_low_memory_policy;
+ if (use_low_memory_policy) {
+ // On low-end we want to be very carefull about killing other
+ // apps. So initially we use 50% more memory to avoid flickering
+ // or raster-on-demand.
+ settings.max_memory_for_prepaint_percentage = 67;
+ } else {
+ // On other devices we have increased memory excessively to avoid
+ // raster-on-demand already, so now we reserve 50% _only_ to avoid
+ // raster-on-demand, and use 50% of the memory otherwise.
+ settings.max_memory_for_prepaint_percentage = 50;
+ }
+ // Webview does not own the surface so should not clear it.
+ settings.renderer_settings.should_clear_root_render_pass =
+ !has_synchronous_compositor_factory;
+
+ // TODO(danakj): Only do this on low end devices.
+ settings.create_low_res_tiling = true;
+
+// settings.use_external_begin_frame_source = true;
+
+#elif !defined(OS_MACOSX)
+ if (ui::IsOverlayScrollbarEnabled()) {
+ settings.scrollbar_animator = cc::LayerTreeSettings::THINNING;
+ settings.solid_color_scrollbar_color = SkColorSetARGB(128, 128, 128, 128);
+ } else {
+ settings.scrollbar_animator = cc::LayerTreeSettings::LINEAR_FADE;
+ settings.solid_color_scrollbar_color = SkColorSetARGB(128, 128, 128, 128);
+ }
+ settings.scrollbar_fade_delay_ms = 500;
+ settings.scrollbar_fade_resize_delay_ms = 500;
+ settings.scrollbar_fade_duration_ms = 300;
+
+ // When pinching in, only show the pinch-viewport overlay scrollbars if the
+ // page scale is at least some threshold away from the minimum. i.e. don't
+ // show the pinch scrollbars when at minimum scale.
+ settings.scrollbar_show_scale_threshold = 1.05f;
+#endif
+
+ if (cmd->HasSwitch(switches::kEnableLowResTiling))
+ settings.create_low_res_tiling = true;
+ if (cmd->HasSwitch(switches::kDisableLowResTiling))
+ settings.create_low_res_tiling = false;
+ if (cmd->HasSwitch(cc::switches::kEnableBeginFrameScheduling))
+ settings.use_external_begin_frame_source = true;
+}
+
+} // namespace
+
+namespace blimp {
+
+scoped_ptr<BlimpCompositor> BlimpCompositor::Create(
+ const gfx::Size& physical_size,
+ const gfx::Size& display_size,
+ float device_scale_factor) {
+ return make_scoped_ptr(
+ new BlimpCompositor(physical_size, display_size, device_scale_factor));
+}
+
+BlimpCompositor::BlimpCompositor(const gfx::Size& physical_size,
+ const gfx::Size& display_size,
+ float device_scale_factor)
+ : device_scale_factor_(device_scale_factor),
+ window_(nullptr),
+ weak_factory_(this) {
+ PopulateLayerTreeSettings(settings_, physical_size, display_size);
+}
+
+BlimpCompositor::~BlimpCompositor() {}
+
+void BlimpCompositor::SetSurface(JNIEnv* env, jobject jsurface) {
+ if (window_) {
+ ANativeWindow_release(window_);
+ window_ = nullptr;
+ SetVisible(false);
+ }
+
+ if (!jsurface)
+ return;
+
+ base::android::ScopedJavaLocalFrame scoped_local_reference_frame(env);
+ window_ = ANativeWindow_fromSurface(env, jsurface);
+ // TODO(dtrainor): Investigate ref counts!
+ // ANativeWindow_acquire(window_);
+ // ANativeWindow_release(window_);
+
+ SetVisible(true);
+}
+
+void BlimpCompositor::SetVisible(bool visible) {
+ if (visible && !host_) {
+ // Create the LayerTreeHost
+ cc::LayerTreeHost::InitParams params;
+ params.client = this;
+ params.shared_bitmap_manager = nullptr;
+ params.gpu_memory_buffer_manager = nullptr;
+ params.task_graph_runner = g_task_graph_runner.Pointer();
+ params.main_task_runner = base::ThreadTaskRunnerHandle::Get();
+ params.settings = &settings_;
+ host_ =
+ cc::LayerTreeHost::CreateThreaded(GetCompositorTaskRunner(), &params);
+
+ host_->SetVisible(true);
+ host_->SetLayerTreeHostClientReady();
+ host_->SetViewportSize(viewport_size_);
+ host_->SetDeviceScaleFactor(device_scale_factor_);
+
+ // Dummy Layers
+ scoped_refptr<cc::Layer> root(
+ cc::SolidColorLayer::Create(cc::LayerSettings()));
+ root->SetBounds(gfx::Size(300, 300));
+ root->SetBackgroundColor(SK_ColorRED);
+ root->SetIsDrawable(true);
+ host_->SetRootLayer(root);
+
+ } else if (!visible && host_) {
+ // Destroy the LayerTreeHost
+ host_.reset();
+ }
+}
+
+void BlimpCompositor::SetSize(const gfx::Size& size) {
+ viewport_size_ = size;
+ if (host_)
+ host_->SetViewportSize(viewport_size_);
+}
+
+void BlimpCompositor::Layout() {}
+
+void BlimpCompositor::RequestNewOutputSurface() {
+ scoped_refptr<BlimpContextProvider> context_provider =
+ BlimpContextProvider::Create(window_);
+
+ scoped_ptr<cc::OutputSurface> output_surface(
+ new BlimpOutputSurface(context_provider));
+
+ host_->SetOutputSurface(output_surface.Pass());
+}
+
+void BlimpCompositor::DidInitializeOutputSurface() {}
+
+void BlimpCompositor::DidFailToInitializeOutputSurface() {}
+
+void BlimpCompositor::DidCommit() {}
+
+void BlimpCompositor::DidCompleteSwapBuffers() {}
+
+void BlimpCompositor::ScheduleComposite() {}
+
+void BlimpCompositor::ScheduleAnimation() {}
+
+void BlimpCompositor::DidPostSwapBuffers() {}
+
+void BlimpCompositor::DidAbortSwapBuffers() {}
+
+scoped_refptr<base::SingleThreadTaskRunner>
+BlimpCompositor::GetCompositorTaskRunner() {
+ if (!compositor_thread_) {
+ base::Thread::Options thread_options;
+#if defined(OS_ANDROID)
+ thread_options.priority = base::ThreadPriority::DISPLAY;
+#endif
+ compositor_thread_.reset(new base::Thread("Compositor"));
+ compositor_thread_->StartWithOptions(thread_options);
+
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner =
+ compositor_thread_->task_runner();
+ task_runner->PostTask(
+ FROM_HERE,
+ base::Bind(base::IgnoreResult(&base::ThreadRestrictions::SetIOAllowed),
+ false));
+
+ return task_runner;
+ } else {
+ return compositor_thread_->task_runner();
+ }
+}
+
+} // namespace blimp

Powered by Google App Engine
This is Rietveld 408576698