| Index: blimp/client/core/compositor/compositor_deps_provider.cc
|
| diff --git a/blimp/client/core/compositor/compositor_deps_provider.cc b/blimp/client/core/compositor/compositor_deps_provider.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..ea9709054842ea9ec02ff68c6376bd11a7433027
|
| --- /dev/null
|
| +++ b/blimp/client/core/compositor/compositor_deps_provider.cc
|
| @@ -0,0 +1,369 @@
|
| +// Copyright 2016 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/core/compositor/compositor_deps_provider.h"
|
| +
|
| +#include "base/memory/ptr_util.h"
|
| +#include "base/single_thread_task_runner.h"
|
| +#include "base/sys_info.h"
|
| +#include "base/threading/thread.h"
|
| +#include "blimp/client/core/compositor/blimp_context_provider.h"
|
| +#include "blimp/client/core/compositor/blimp_gpu_memory_buffer_manager.h"
|
| +#include "cc/output/compositor_frame.h"
|
| +#include "cc/output/output_surface.h"
|
| +#include "cc/raster/single_thread_task_graph_runner.h"
|
| +#include "cc/trees/layer_tree_settings.h"
|
| +#include "gpu/command_buffer/client/context_support.h"
|
| +
|
| +#if defined(OS_ANDROID)
|
| +#include "ui/gfx/android/device_display_info.h"
|
| +#endif
|
| +
|
| +namespace blimp {
|
| +namespace client {
|
| +
|
| +namespace {
|
| +
|
| +#if defined(OS_ANDROID)
|
| +// The minimum valid content width in a tile. This is used to make sure the
|
| +// width of the content on the rightmost tile isn't a tiny sliver.
|
| +const int kMinimumTileContentWidthPixels = 64;
|
| +#endif
|
| +
|
| +// Minimal implementation of cc::OutputSurface.
|
| +class DirectRenderingOutputSurface : public cc::OutputSurface {
|
| + public:
|
| + explicit DirectRenderingOutputSurface(
|
| + scoped_refptr<BlimpContextProvider> context_provider)
|
| + : cc::OutputSurface(std::move(context_provider), nullptr, nullptr) {}
|
| +
|
| + ~DirectRenderingOutputSurface() override {}
|
| +
|
| + // OutputSurface implementation.
|
| + void SwapBuffers(cc::CompositorFrame frame) override {
|
| + // See cc::OutputSurface::SwapBuffers() comment for details.
|
| + context_provider_->ContextSupport()->Swap();
|
| + cc::OutputSurface::PostSwapBuffersComplete();
|
| + }
|
| +
|
| + uint32_t GetFramebufferCopyTextureFormat() override {
|
| + auto* gl = static_cast<BlimpContextProvider*>(context_provider());
|
| + return gl->GetCopyTextureInternalFormat();
|
| + }
|
| +
|
| + private:
|
| + DISALLOW_COPY_AND_ASSIGN(DirectRenderingOutputSurface);
|
| +};
|
| +
|
| +// TaskGraphRunner that runs on a single thread. See
|
| +// cc::SingleThreadTaskGraphRunner for details. Used by client's compositor.
|
| +class BlimpTaskGraphRunner : public cc::SingleThreadTaskGraphRunner {
|
| + public:
|
| + BlimpTaskGraphRunner() {
|
| + Start("BlimpCompositorWorker",
|
| + base::SimpleThread::Options(base::ThreadPriority::BACKGROUND));
|
| + }
|
| +
|
| + ~BlimpTaskGraphRunner() override { Shutdown(); }
|
| +
|
| + private:
|
| + DISALLOW_COPY_AND_ASSIGN(BlimpTaskGraphRunner);
|
| +};
|
| +
|
| +CompositorDepsProvider* current_compositor_deps_provider = nullptr;
|
| +
|
| +} // namespace
|
| +
|
| +// static
|
| +CompositorDepsProvider* CompositorDepsProvider::current() {
|
| + return current_compositor_deps_provider;
|
| +}
|
| +
|
| +CompositorDepsProvider::CompositorDepsProvider(bool use_direct_rendering)
|
| + : use_direct_rendering_(use_direct_rendering) {
|
| + DCHECK(!current_compositor_deps_provider);
|
| + current_compositor_deps_provider = this;
|
| +}
|
| +
|
| +CompositorDepsProvider::~CompositorDepsProvider() {
|
| + DCHECK(current_compositor_deps_provider);
|
| + current_compositor_deps_provider = nullptr;
|
| +}
|
| +
|
| +cc::LayerTreeSettings* CompositorDepsProvider::GetLayerTreeSettings() {
|
| + if (!settings_.get()) {
|
| + settings_ = base::MakeUnique<cc::LayerTreeSettings>();
|
| + GenerateLayerTreeSettings(settings_.get());
|
| + }
|
| +
|
| + return settings_.get();
|
| +}
|
| +
|
| +std::unique_ptr<cc::OutputSurface>
|
| +CompositorDepsProvider::CreateDirectRenderingOutputSurface(
|
| + gfx::AcceleratedWidget widget) {
|
| + DCHECK(use_direct_rendering_);
|
| + DCHECK_NE(widget, gfx::kNullAcceleratedWidget);
|
| +
|
| + scoped_refptr<BlimpContextProvider> context_provider =
|
| + BlimpContextProvider::Create(widget, GetGpuMemoryBufferManager());
|
| +
|
| + return base::MakeUnique<DirectRenderingOutputSurface>(context_provider);
|
| +}
|
| +
|
| +cc::TaskGraphRunner* CompositorDepsProvider::GetTaskGraphRunner() {
|
| + if (!task_graph_runner_)
|
| + task_graph_runner_ = base::MakeUnique<BlimpTaskGraphRunner>();
|
| + return task_graph_runner_.get();
|
| +}
|
| +
|
| +gpu::GpuMemoryBufferManager*
|
| +CompositorDepsProvider::GetGpuMemoryBufferManager() {
|
| + if (use_direct_rendering_) {
|
| + if (!gpu_memory_buffer_manager_)
|
| + gpu_memory_buffer_manager_ =
|
| + base::MakeUnique<BlimpGpuMemoryBufferManager>();
|
| + return gpu_memory_buffer_manager_.get();
|
| + }
|
| +
|
| + return nullptr;
|
| +}
|
| +
|
| +scoped_refptr<base::SingleThreadTaskRunner>
|
| +CompositorDepsProvider::GetCompositorTaskRunner() {
|
| + if (compositor_thread_)
|
| + return compositor_thread_->task_runner();
|
| +
|
| + 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));
|
| + // TODO(dtrainor): Determine whether or not we can disallow waiting.
|
| +
|
| + return task_runner;
|
| +}
|
| +
|
| +void CompositorDepsProvider::GenerateLayerTreeSettings(
|
| + cc::LayerTreeSettings* settings) {
|
| + // TODO(khushalsagar): The server should selectively send only those
|
| + // LayerTreeSettings which should remain consistent across the server and
|
| + // client. Since it currently overrides all settings, ignore them.
|
| + // See crbug/577985.
|
| +
|
| + // 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;
|
| +
|
| + settings->main_frame_before_activation_enabled = false;
|
| + settings->default_tile_size = gfx::Size(256, 256);
|
| + settings->gpu_rasterization_msaa_sample_count = 0;
|
| + settings->gpu_rasterization_forced = false;
|
| + settings->gpu_rasterization_enabled = false;
|
| + settings->can_use_lcd_text = false;
|
| + settings->use_distance_field_text = false;
|
| +#if defined(OS_MACOSX)
|
| + settings->use_zero_copy = true;
|
| +#else
|
| + settings->use_zero_copy = false;
|
| +#endif
|
| + settings->enable_elastic_overscroll = false;
|
| + settings->image_decode_tasks_enabled = false;
|
| + settings->single_thread_proxy_scheduler = false;
|
| + settings->initial_debug_state.show_debug_borders = false;
|
| + settings->initial_debug_state.show_fps_counter = false;
|
| + settings->initial_debug_state.show_layer_animation_bounds_rects = false;
|
| + settings->initial_debug_state.show_paint_rects = false;
|
| + settings->initial_debug_state.show_property_changed_rects = false;
|
| + settings->initial_debug_state.show_surface_damage_rects = false;
|
| + settings->initial_debug_state.show_screen_space_rects = false;
|
| + settings->initial_debug_state.show_replica_screen_space_rects = false;
|
| + settings->initial_debug_state.SetRecordRenderingStats(false);
|
| +
|
| +#if defined(OS_ANDROID)
|
| + if (base::SysInfo::IsLowEndDevice())
|
| + settings->gpu_rasterization_enabled = false;
|
| + settings->using_synchronous_renderer_compositor = false;
|
| + 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;
|
| + settings->ignore_root_layer_flings = false;
|
| + bool use_low_memory_policy = base::SysInfo::IsLowEndDevice();
|
| + 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;
|
| +
|
| + settings->renderer_settings.preferred_tile_format = cc::RGBA_4444;
|
| + } 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;
|
| + }
|
| + settings->renderer_settings.should_clear_root_render_pass = true;
|
| +
|
| + // TODO(danakj): Only do this on low end devices.
|
| + settings->create_low_res_tiling = true;
|
| +
|
| +// TODO(dtrainor): Investigate whether or not we want to use an external
|
| +// source here.
|
| +// settings->use_external_begin_frame_source = true;
|
| +
|
| +#elif !defined(OS_MACOSX)
|
| + 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.
|
| +// TODO(dtrainor): Update this since https://crrev.com/1267603004 landed.
|
| +// settings->scrollbar_show_scale_threshold = 1.05f;
|
| +#endif
|
| +
|
| + // Set the GpuMemoryPolicy.
|
| + cc::ManagedMemoryPolicy memory_policy = settings->memory_policy_;
|
| + memory_policy.bytes_limit_when_visible = 0;
|
| +
|
| +#if defined(OS_ANDROID)
|
| + // We can't query available GPU memory from the system on Android.
|
| + // Physical memory is also mis-reported sometimes (eg. Nexus 10 reports
|
| + // 1262MB when it actually has 2GB, while Razr M has 1GB but only reports
|
| + // 128MB java heap size). First we estimate physical memory using both.
|
| + size_t dalvik_mb = base::SysInfo::DalvikHeapSizeMB();
|
| + size_t physical_mb = base::SysInfo::AmountOfPhysicalMemoryMB();
|
| + size_t physical_memory_mb = 0;
|
| + if (dalvik_mb >= 256)
|
| + physical_memory_mb = dalvik_mb * 4;
|
| + else
|
| + physical_memory_mb = std::max(dalvik_mb * 4, (physical_mb * 4) / 3);
|
| +
|
| + // Now we take a default of 1/8th of memory on high-memory devices,
|
| + // and gradually scale that back for low-memory devices (to be nicer
|
| + // to other apps so they don't get killed). Examples:
|
| + // Nexus 4/10(2GB) 256MB (normally 128MB)
|
| + // Droid Razr M(1GB) 114MB (normally 57MB)
|
| + // Galaxy Nexus(1GB) 100MB (normally 50MB)
|
| + // Xoom(1GB) 100MB (normally 50MB)
|
| + // Nexus S(low-end) 8MB (normally 8MB)
|
| + // Note that the compositor now uses only some of this memory for
|
| + // pre-painting and uses the rest only for 'emergencies'.
|
| + if (memory_policy.bytes_limit_when_visible == 0) {
|
| + // NOTE: Non-low-end devices use only 50% of these limits,
|
| + // except during 'emergencies' where 100% can be used.
|
| + if (!base::SysInfo::IsLowEndDevice()) {
|
| + if (physical_memory_mb >= 1536)
|
| + memory_policy.bytes_limit_when_visible =
|
| + physical_memory_mb / 8; // >192MB
|
| + else if (physical_memory_mb >= 1152)
|
| + memory_policy.bytes_limit_when_visible =
|
| + physical_memory_mb / 8; // >144MB
|
| + else if (physical_memory_mb >= 768)
|
| + memory_policy.bytes_limit_when_visible =
|
| + physical_memory_mb / 10; // >76MB
|
| + else
|
| + memory_policy.bytes_limit_when_visible =
|
| + physical_memory_mb / 12; // <64MB
|
| + } else {
|
| + // Low-end devices have 512MB or less memory by definition
|
| + // so we hard code the limit rather than relying on the heuristics
|
| + // above. Low-end devices use 4444 textures so we can use a lower limit.
|
| + memory_policy.bytes_limit_when_visible = 8;
|
| + }
|
| + memory_policy.bytes_limit_when_visible =
|
| + memory_policy.bytes_limit_when_visible * 1024 * 1024;
|
| + // Clamp the observed value to a specific range on Android.
|
| + memory_policy.bytes_limit_when_visible =
|
| + std::max(memory_policy.bytes_limit_when_visible,
|
| + static_cast<size_t>(8 * 1024 * 1024));
|
| + memory_policy.bytes_limit_when_visible =
|
| + std::min(memory_policy.bytes_limit_when_visible,
|
| + static_cast<size_t>(256 * 1024 * 1024));
|
| + }
|
| + memory_policy.priority_cutoff_when_visible =
|
| + gpu::MemoryAllocation::CUTOFF_ALLOW_EVERYTHING;
|
| +#else
|
| + // Ignore what the system said and give all clients the same maximum
|
| + // allocation on desktop platforms.
|
| + memory_policy.bytes_limit_when_visible = 512 * 1024 * 1024;
|
| + memory_policy.priority_cutoff_when_visible =
|
| + gpu::MemoryAllocation::CUTOFF_ALLOW_NICE_TO_HAVE;
|
| +#endif
|
| +
|
| +#if defined(OS_ANDROID)
|
| + // Calculate the correct raster tile size to use. Assuming a square tile.
|
| + DCHECK_EQ(settings->default_tile_size.width(),
|
| + settings->default_tile_size.height());
|
| +
|
| + gfx::DeviceDisplayInfo info;
|
| + bool real_size_supported = true;
|
| + int display_width = info.GetPhysicalDisplayWidth();
|
| + int display_height = info.GetPhysicalDisplayHeight();
|
| + if (display_width == 0 || display_height == 0) {
|
| + real_size_supported = false;
|
| + display_width = info.GetDisplayWidth();
|
| + display_height = info.GetDisplayHeight();
|
| + }
|
| +
|
| + int portrait_width = std::min(display_width, display_height);
|
| + int landscape_width = std::max(display_width, display_height);
|
| +
|
| + int default_tile_size = settings->default_tile_size.width();
|
| + 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.
|
| + int right_tile_width = ((portrait_width - 1) % default_tile_size) + 1;
|
| + if (right_tile_width < kMinimumTileContentWidthPixels) {
|
| + // Figure out the new tile count without the small edge tile.
|
| + int full_tile_count = portrait_width / default_tile_size;
|
| + DCHECK_GT(full_tile_count, 0);
|
| +
|
| + // Calculate the ideal new tile width with the new tile count.
|
| + default_tile_size = std::ceil(static_cast<float>(portrait_width) /
|
| + static_cast<float>(full_tile_count));
|
| +
|
| + // Round up to nearest 32 for GPU efficiency.
|
| + if (default_tile_size & 0x1F)
|
| + default_tile_size = (default_tile_size & ~0x1F) + 32;
|
| + }
|
| + } else {
|
| + // We don't know the exact resolution due to screen controls etc., so this
|
| + // just estimates the values above using tile counts.
|
| + int numTiles = (portrait_width * landscape_width) / (256 * 256);
|
| + if (numTiles > 16)
|
| + default_tile_size = 384;
|
| + if (numTiles >= 40)
|
| + default_tile_size = 512;
|
| + }
|
| + settings->default_tile_size.SetSize(default_tile_size, default_tile_size);
|
| +#endif
|
| +
|
| + settings->abort_commit_before_output_surface_creation = false;
|
| +}
|
| +
|
| +} // namespace client
|
| +} // namespace blimp
|
|
|