#include "gpu/GLES2/gl2extchromium.h"
#include "ui/gfx/frame_time.h"
#include "ui/gfx/geometry/rect_conversions.h"
-#include "ui/gfx/size_conversions.h"
-#include "ui/gfx/vector2d_conversions.h"
+#include "ui/gfx/geometry/size_conversions.h"
+#include "ui/gfx/geometry/vector2d_conversions.h"
namespace cc {
namespace {
+// Small helper class that saves the current viewport location as the user sees
+// it and resets to the same location.
+class ViewportAnchor {
+ public:
+ ViewportAnchor(LayerImpl* inner_scroll, LayerImpl* outer_scroll)
+ : inner_(inner_scroll),
+ outer_(outer_scroll) {
+ viewport_in_content_coordinates_ = inner_->TotalScrollOffset();
+
+ if (outer_)
+ viewport_in_content_coordinates_ += outer_->TotalScrollOffset();
+ }
+
+ void ResetViewportToAnchoredPosition() {
+ DCHECK(outer_);
+
+ inner_->ClampScrollToMaxScrollOffset();
+ outer_->ClampScrollToMaxScrollOffset();
+
+ gfx::ScrollOffset viewport_location = inner_->TotalScrollOffset() +
+ outer_->TotalScrollOffset();
+
+ gfx::Vector2dF delta =
+ viewport_in_content_coordinates_.DeltaFrom(viewport_location);
+
+ delta = outer_->ScrollBy(delta);
+ inner_->ScrollBy(delta);
+ }
+
+ private:
+ LayerImpl* inner_;
+ LayerImpl* outer_;
+ gfx::ScrollOffset viewport_in_content_coordinates_;
+};
+
+
void DidVisibilityChange(LayerTreeHostImpl* id, bool visible) {
if (visible) {
TRACE_EVENT_ASYNC_BEGIN1("webkit",
unsigned GetMapImageTextureTarget(
const ContextProvider::Capabilities& context_capabilities) {
+// TODO(reveman): This should be a setting passed to the compositor instead
+// of hard-coded here. The target that need to be used depends on our choice
+// of GpuMemoryBuffer type. Note: SURFACE_TEXTURE needs EXTERNAL_OES,
+// IO_SURFACE needs RECTANGLE_ARB. crbug.com/431059
+#if defined(OS_ANDROID)
if (context_capabilities.gpu.egl_image_external)
return GL_TEXTURE_EXTERNAL_OES;
+#endif
if (context_capabilities.gpu.texture_rectangle)
return GL_TEXTURE_RECTANGLE_ARB;
new LayerTreeHostImplTimeSourceAdapter(layer_tree_host_impl,
time_source));
}
- virtual ~LayerTreeHostImplTimeSourceAdapter() {
+ ~LayerTreeHostImplTimeSourceAdapter() override {
time_source_->SetClient(NULL);
time_source_->SetActive(false);
}
- virtual void OnTimerTick() OVERRIDE {
+ void OnTimerTick() override {
// In single threaded mode we attempt to simulate changing the current
// thread by maintaining a fake thread id. When we switch from one
// thread to another, we construct DebugScopedSetXXXThread objects that
LayerTreeHostImplClient* client,
Proxy* proxy,
RenderingStatsInstrumentation* rendering_stats_instrumentation,
- SharedBitmapManager* manager,
+ SharedBitmapManager* shared_bitmap_manager,
+ gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
int id) {
- return make_scoped_ptr(new LayerTreeHostImpl(
- settings, client, proxy, rendering_stats_instrumentation, manager, id));
+ return make_scoped_ptr(new LayerTreeHostImpl(settings,
+ client,
+ proxy,
+ rendering_stats_instrumentation,
+ shared_bitmap_manager,
+ gpu_memory_buffer_manager,
+ id));
}
LayerTreeHostImpl::LayerTreeHostImpl(
LayerTreeHostImplClient* client,
Proxy* proxy,
RenderingStatsInstrumentation* rendering_stats_instrumentation,
- SharedBitmapManager* manager,
+ SharedBitmapManager* shared_bitmap_manager,
+ gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
int id)
- : client_(client),
+ : BeginFrameSourceMixIn(),
+ client_(client),
proxy_(proxy),
use_gpu_rasterization_(false),
input_handler_client_(NULL),
rendering_stats_instrumentation_(rendering_stats_instrumentation),
micro_benchmark_controller_(this),
need_to_update_visible_tiles_before_draw_(false),
- shared_bitmap_manager_(manager),
- id_(id) {
+ shared_bitmap_manager_(shared_bitmap_manager),
+ gpu_memory_buffer_manager_(gpu_memory_buffer_manager),
+ id_(id),
+ requires_high_res_to_draw_(false) {
DCHECK(proxy_->IsImplThread());
DidVisibilityChange(this, visible_);
animation_registrar_->set_supports_scroll_animations(
if (pending_tree_)
pending_tree_->Shutdown();
active_tree_->Shutdown();
- recycle_tree_.reset();
- pending_tree_.reset();
- active_tree_.reset();
+ recycle_tree_ = nullptr;
+ pending_tree_ = nullptr;
+ active_tree_ = nullptr;
DestroyTileManager();
}
scoped_ptr<SwapPromiseMonitor>
LayerTreeHostImpl::CreateLatencyInfoSwapPromiseMonitor(
ui::LatencyInfo* latency) {
- return scoped_ptr<SwapPromiseMonitor>(
+ return make_scoped_ptr(
new LatencyInfoSwapPromiseMonitor(latency, NULL, this));
}
LayerImpl* layer,
const OcclusionTracker<LayerImpl>& occlusion_tracker,
AppendQuadsData* append_quads_data) {
- layer->AppendQuads(target_render_pass, occlusion_tracker, append_quads_data);
+ layer->AppendQuads(
+ target_render_pass,
+ occlusion_tracker.GetCurrentOcclusionForLayer(layer->draw_transform()),
+ append_quads_data);
}
static void AppendQuadsForRenderSurfaceLayer(
if (append_quads_data.num_incomplete_tiles ||
append_quads_data.num_missing_tiles) {
frame->contains_incomplete_tile = true;
- if (active_tree()->RequiresHighResToDraw())
+ if (RequiresHighResToDraw())
draw_result = DRAW_ABORTED_MISSING_HIGH_RES_CONTENT;
}
draw_result = DRAW_SUCCESS;
#if DCHECK_IS_ON
- for (size_t i = 0; i < frame->render_passes.size(); ++i) {
- for (QuadList::Iterator iter = frame->render_passes[i]->quad_list.begin();
- iter != frame->render_passes[i]->quad_list.end();
- ++iter)
- DCHECK(iter->shared_quad_state);
- DCHECK(frame->render_passes_by_id.find(frame->render_passes[i]->id)
- != frame->render_passes_by_id.end());
+ for (const auto& render_pass : frame->render_passes) {
+ for (const auto& quad : render_pass->quad_list)
+ DCHECK(quad->shared_quad_state);
+ DCHECK(frame->render_passes_by_id.find(render_pass->id) !=
+ frame->render_passes_by_id.end());
}
#endif
DCHECK(frame->render_passes.back()->output_rect.origin().IsOrigin());
// Now follow up for all RenderPass quads and remove their RenderPasses
// recursively.
const QuadList& quad_list = removed_pass->quad_list;
- QuadList::ConstBackToFrontIterator quad_list_iterator =
- quad_list.BackToFrontBegin();
- for (; quad_list_iterator != quad_list.BackToFrontEnd();
+ for (auto quad_list_iterator = quad_list.BackToFrontBegin();
+ quad_list_iterator != quad_list.BackToFrontEnd();
++quad_list_iterator) {
- const DrawQuad* current_quad = &*quad_list_iterator;
+ const DrawQuad* current_quad = *quad_list_iterator;
if (current_quad->material != DrawQuad::RENDER_PASS)
continue;
// If any quad or RenderPass draws into this RenderPass, then keep it.
const QuadList& quad_list = render_pass->quad_list;
- for (QuadList::ConstBackToFrontIterator quad_list_iterator =
- quad_list.BackToFrontBegin();
+ for (auto quad_list_iterator = quad_list.BackToFrontBegin();
quad_list_iterator != quad_list.BackToFrontEnd();
++quad_list_iterator) {
- const DrawQuad* current_quad = &*quad_list_iterator;
+ const DrawQuad* current_quad = *quad_list_iterator;
if (current_quad->material != DrawQuad::RENDER_PASS)
return false;
it = culler.RenderPassListNext(it)) {
const RenderPass* current_pass = frame->render_passes[it];
const QuadList& quad_list = current_pass->quad_list;
- QuadList::ConstBackToFrontIterator quad_list_iterator =
- quad_list.BackToFrontBegin();
- for (; quad_list_iterator != quad_list.BackToFrontEnd();
+ for (auto quad_list_iterator = quad_list.BackToFrontBegin();
+ quad_list_iterator != quad_list.BackToFrontEnd();
++quad_list_iterator) {
- const DrawQuad* current_quad = &*quad_list_iterator;
+ const DrawQuad* current_quad = *quad_list_iterator;
if (current_quad->material != DrawQuad::RENDER_PASS)
continue;
active_tree_ = LayerTreeImpl::create(this);
if (pending_tree_)
pending_tree_->DetachLayerTree();
- pending_tree_.reset();
+ pending_tree_ = nullptr;
if (recycle_tree_)
recycle_tree_->DetachLayerTree();
- recycle_tree_.reset();
-}
-
-void LayerTreeHostImpl::ResetRecycleTreeForTesting() {
- if (recycle_tree_)
- recycle_tree_->DetachLayerTree();
- recycle_tree_.reset();
+ recycle_tree_ = nullptr;
}
void LayerTreeHostImpl::EnforceManagedMemoryPolicy(
100);
DCHECK(resource_pool_);
- resource_pool_->CheckBusyResources();
+ resource_pool_->CheckBusyResources(false);
// Soft limit is used for resource pool such that memory returns to soft
// limit after going over.
resource_pool_->SetResourceUsageLimits(
// Release all staging resources when invisible.
if (staging_resource_pool_) {
- staging_resource_pool_->CheckBusyResources();
+ staging_resource_pool_->CheckBusyResources(false);
staging_resource_pool_->SetResourceUsageLimits(
std::numeric_limits<size_t>::max(),
std::numeric_limits<size_t>::max(),
if (!layer->HasValidTilePriorities())
continue;
- PictureLayerImpl* twin_layer = layer->GetTwinLayer();
+ PictureLayerImpl* twin_layer = layer->GetPendingOrActiveTwinLayer();
// Ignore the twin layer when tile priorities are invalid.
// TODO(vmpstr): Iterators should handle this instead. crbug.com/381704
void LayerTreeHostImpl::BuildRasterQueue(RasterTilePriorityQueue* queue,
TreePriority tree_priority) {
+ TRACE_EVENT0("cc", "LayerTreeHostImpl::BuildRasterQueue");
picture_layer_pairs_.clear();
GetPictureLayerImplPairs(&picture_layer_pairs_);
queue->Build(picture_layer_pairs_, tree_priority);
void LayerTreeHostImpl::BuildEvictionQueue(EvictionTilePriorityQueue* queue,
TreePriority tree_priority) {
+ TRACE_EVENT0("cc", "LayerTreeHostImpl::BuildEvictionQueue");
picture_layer_pairs_.clear();
GetPictureLayerImplPairs(&picture_layer_pairs_);
queue->Build(picture_layer_pairs_, tree_priority);
}
void LayerTreeHostImpl::BeginFrame(const BeginFrameArgs& args) {
- client_->BeginFrame(args);
+ CallOnBeginFrame(args);
}
void LayerTreeHostImpl::DidSwapBuffers() {
if (tile_manager_) {
DCHECK(resource_pool_);
- resource_pool_->CheckBusyResources();
+ resource_pool_->CheckBusyResources(false);
resource_pool_->ReduceResourceUsage();
}
// If we're not visible, we likely released resources, so we want to
if (!InnerViewportScrollLayer())
return metadata;
- metadata.root_scroll_offset = active_tree_->TotalScrollOffset();
+ // TODO(miletus) : Change the metadata to hold ScrollOffset.
+ metadata.root_scroll_offset = gfx::ScrollOffsetToVector2dF(
+ active_tree_->TotalScrollOffset());
return metadata;
}
fps_counter_->SaveTimeStamp(frame_begin_time,
!output_surface_->context_provider());
- bool on_main_thread = false;
- rendering_stats_instrumentation_->IncrementFrameCount(
- 1, on_main_thread);
+ rendering_stats_instrumentation_->IncrementFrameCount(1);
if (tile_manager_) {
memory_history_->SaveEntry(
// We have released tilings for both active and pending tree.
// We would not have any content to draw until the pending tree is activated.
// Prevent the active tree from drawing until activation.
- active_tree_->SetRequiresHighResToDraw();
+ SetRequiresHighResToDraw();
}
const RendererCapabilitiesImpl&
}
bool LayerTreeHostImpl::SwapBuffers(const LayerTreeHostImpl::FrameData& frame) {
- active_tree()->ResetRequiresHighResToDraw();
+ ResetRequiresHighResToDraw();
if (frame.has_no_damage) {
active_tree()->BreakSwapPromises(SwapPromise::SWAP_FAILS);
return false;
return true;
}
-void LayerTreeHostImpl::SetNeedsBeginFrame(bool enable) {
+void LayerTreeHostImpl::OnNeedsBeginFramesChange(bool enable) {
if (output_surface_)
output_surface_->SetNeedsBeginFrame(enable);
else
begin_impl_frame_interval_ = args.interval;
}
-void LayerTreeHostImpl::UpdateInnerViewportContainerSize() {
- LayerImpl* container_layer = active_tree_->InnerViewportContainerLayer();
- if (!container_layer)
+void LayerTreeHostImpl::UpdateViewportContainerSizes() {
+ LayerImpl* inner_container = active_tree_->InnerViewportContainerLayer();
+ LayerImpl* outer_container = active_tree_->OuterViewportContainerLayer();
+
+ if (!inner_container || !top_controls_manager_)
return;
- if (top_controls_manager_) {
- container_layer->SetBoundsDelta(
- gfx::Vector2dF(0, active_tree_->top_controls_layout_height() -
- active_tree_->total_top_controls_content_offset()));
- }
+ ViewportAnchor anchor(InnerViewportScrollLayer(),
+ OuterViewportScrollLayer());
+
+ // Adjust the inner viewport by shrinking/expanding the container to account
+ // for the change in top controls height since the last Resize from Blink.
+ inner_container->SetBoundsDelta(
+ gfx::Vector2dF(0, active_tree_->top_controls_layout_height() -
+ active_tree_->total_top_controls_content_offset()));
+
+ if (!outer_container || outer_container->BoundsForScrolling().IsEmpty())
+ return;
+
+ // Adjust the outer viewport container as well, since adjusting only the
+ // inner may cause its bounds to exceed those of the outer, causing scroll
+ // clamping. We adjust it so it maintains the same aspect ratio as the
+ // inner viewport.
+ float aspect_ratio = inner_container->BoundsForScrolling().width() /
+ inner_container->BoundsForScrolling().height();
+ float target_height = outer_container->BoundsForScrolling().width() /
+ aspect_ratio;
+ float current_outer_height = outer_container->BoundsForScrolling().height() -
+ outer_container->bounds_delta().y();
+ gfx::Vector2dF delta(0, target_height - current_outer_height);
+
+ outer_container->SetBoundsDelta(delta);
+ active_tree_->InnerViewportScrollLayer()->SetBoundsDelta(delta);
+
+ anchor.ResetViewportToAnchoredPosition();
}
void LayerTreeHostImpl::SetTopControlsLayoutHeight(float height) {
return;
active_tree_->set_top_controls_layout_height(height);
- UpdateInnerViewportContainerSize();
+ UpdateViewportContainerSizes();
SetFullRootLayerDamage();
}
+void LayerTreeHostImpl::SynchronouslyInitializeAllTiles() {
+ // Only valid for the single-threaded non-scheduled/synchronous case
+ // using the zero copy raster worker pool.
+ single_thread_synchronous_task_graph_runner_->RunUntilIdle();
+}
+
void LayerTreeHostImpl::DidLoseOutputSurface() {
if (resource_provider_)
resource_provider_->DidLoseOutputSurface();
top_controls_manager_->top_controls_height());
}
- UpdateInnerViewportContainerSize();
+ UpdateViewportContainerSizes();
} else {
active_tree_->ProcessUIResourceRequestQueue();
}
if (debug_state_.continuous_painting) {
const RenderingStats& stats =
rendering_stats_instrumentation_->GetRenderingStats();
- paint_time_counter_->SavePaintTime(stats.main_stats.paint_time +
- stats.main_stats.record_time +
- stats.impl_stats.rasterize_time);
+ // TODO(hendrikw): This requires a different metric when we commit directly
+ // to the active tree. See crbug.com/429311.
+ paint_time_counter_->SavePaintTime(
+ stats.impl_stats.commit_to_activate_duration.GetLastTimeDelta() +
+ stats.impl_stats.draw_duration.GetLastTimeDelta());
}
if (time_source_client_adapter_ && time_source_client_adapter_->Active())
// If we just became visible, we have to ensure that we draw high res tiles,
// to prevent checkerboard/low res flashes.
if (visible_)
- active_tree()->SetRequiresHighResToDraw();
+ SetRequiresHighResToDraw();
else
EvictAllUIResources();
DCHECK(settings_.impl_side_painting);
DCHECK(output_surface_);
DCHECK(resource_provider_);
- DCHECK(proxy_->ImplThreadTaskRunner());
+
+ CreateResourceAndRasterWorkerPool(
+ &raster_worker_pool_, &resource_pool_, &staging_resource_pool_);
+ DCHECK(raster_worker_pool_);
+ DCHECK(resource_pool_);
+
+ base::SingleThreadTaskRunner* task_runner =
+ proxy_->HasImplThread() ? proxy_->ImplThreadTaskRunner()
+ : proxy_->MainThreadTaskRunner();
+ DCHECK(task_runner);
+ size_t scheduled_raster_task_limit =
+ IsSynchronousSingleThreaded() ? std::numeric_limits<size_t>::max()
+ : settings_.scheduled_raster_task_limit;
+ tile_manager_ = TileManager::Create(this,
+ task_runner,
+ resource_pool_.get(),
+ raster_worker_pool_->AsRasterizer(),
+ rendering_stats_instrumentation_,
+ scheduled_raster_task_limit);
+
+ UpdateTileManagerMemoryPolicy(ActualManagedMemoryPolicy());
+ need_to_update_visible_tiles_before_draw_ = false;
+}
+
+void LayerTreeHostImpl::CreateResourceAndRasterWorkerPool(
+ scoped_ptr<RasterWorkerPool>* raster_worker_pool,
+ scoped_ptr<ResourcePool>* resource_pool,
+ scoped_ptr<ResourcePool>* staging_resource_pool) {
+ base::SingleThreadTaskRunner* task_runner =
+ proxy_->HasImplThread() ? proxy_->ImplThreadTaskRunner()
+ : proxy_->MainThreadTaskRunner();
+ DCHECK(task_runner);
ContextProvider* context_provider = output_surface_->context_provider();
+ bool should_use_zero_copy_rasterizer =
+ settings_.use_zero_copy || IsSynchronousSingleThreaded();
+
if (!context_provider) {
- resource_pool_ =
+ *resource_pool =
ResourcePool::Create(resource_provider_.get(),
GL_TEXTURE_2D,
resource_provider_->best_texture_format());
- raster_worker_pool_ =
- BitmapRasterWorkerPool::Create(proxy_->ImplThreadTaskRunner(),
+ *raster_worker_pool =
+ BitmapRasterWorkerPool::Create(task_runner,
RasterWorkerPool::GetTaskGraphRunner(),
resource_provider_.get());
} else if (use_gpu_rasterization_) {
- resource_pool_ =
+ *resource_pool =
ResourcePool::Create(resource_provider_.get(),
GL_TEXTURE_2D,
resource_provider_->best_texture_format());
- raster_worker_pool_ =
- GpuRasterWorkerPool::Create(proxy_->ImplThreadTaskRunner(),
+ *raster_worker_pool =
+ GpuRasterWorkerPool::Create(task_runner,
context_provider,
- resource_provider_.get());
- } else if (UseZeroCopyRasterizer()) {
- resource_pool_ = ResourcePool::Create(
+ resource_provider_.get(),
+ settings_.use_distance_field_text);
+ } else if (should_use_zero_copy_rasterizer && CanUseZeroCopyRasterizer()) {
+ *resource_pool = ResourcePool::Create(
resource_provider_.get(),
GetMapImageTextureTarget(context_provider->ContextCapabilities()),
resource_provider_->best_texture_format());
- raster_worker_pool_ =
- ZeroCopyRasterWorkerPool::Create(proxy_->ImplThreadTaskRunner(),
- RasterWorkerPool::GetTaskGraphRunner(),
- resource_provider_.get());
- } else if (UseOneCopyRasterizer()) {
+ TaskGraphRunner* task_graph_runner;
+ if (IsSynchronousSingleThreaded()) {
+ DCHECK(!single_thread_synchronous_task_graph_runner_);
+ single_thread_synchronous_task_graph_runner_.reset(new TaskGraphRunner);
+ task_graph_runner = single_thread_synchronous_task_graph_runner_.get();
+ } else {
+ task_graph_runner = RasterWorkerPool::GetTaskGraphRunner();
+ }
+
+ *raster_worker_pool = ZeroCopyRasterWorkerPool::Create(
+ task_runner, task_graph_runner, resource_provider_.get());
+ } else if (settings_.use_one_copy && CanUseOneCopyRasterizer()) {
// We need to create a staging resource pool when using copy rasterizer.
- staging_resource_pool_ = ResourcePool::Create(
+ *staging_resource_pool = ResourcePool::Create(
resource_provider_.get(),
GetMapImageTextureTarget(context_provider->ContextCapabilities()),
resource_provider_->best_texture_format());
- resource_pool_ =
+ *resource_pool =
ResourcePool::Create(resource_provider_.get(),
GL_TEXTURE_2D,
resource_provider_->best_texture_format());
- raster_worker_pool_ =
- OneCopyRasterWorkerPool::Create(proxy_->ImplThreadTaskRunner(),
+ *raster_worker_pool =
+ OneCopyRasterWorkerPool::Create(task_runner,
RasterWorkerPool::GetTaskGraphRunner(),
context_provider,
resource_provider_.get(),
staging_resource_pool_.get());
} else {
- resource_pool_ = ResourcePool::Create(
+ *resource_pool = ResourcePool::Create(
resource_provider_.get(),
GL_TEXTURE_2D,
resource_provider_->memory_efficient_texture_format());
- raster_worker_pool_ = PixelBufferRasterWorkerPool::Create(
- proxy_->ImplThreadTaskRunner(),
+ *raster_worker_pool = PixelBufferRasterWorkerPool::Create(
+ task_runner,
RasterWorkerPool::GetTaskGraphRunner(),
context_provider,
resource_provider_.get(),
GetMaxTransferBufferUsageBytes(context_provider->ContextCapabilities(),
settings_.refresh_rate));
}
-
- tile_manager_ =
- TileManager::Create(this,
- proxy_->ImplThreadTaskRunner(),
- resource_pool_.get(),
- raster_worker_pool_->AsRasterizer(),
- rendering_stats_instrumentation_);
-
- UpdateTileManagerMemoryPolicy(ActualManagedMemoryPolicy());
- need_to_update_visible_tiles_before_draw_ = false;
}
void LayerTreeHostImpl::DestroyTileManager() {
- tile_manager_.reset();
- resource_pool_.reset();
- staging_resource_pool_.reset();
- raster_worker_pool_.reset();
+ tile_manager_ = nullptr;
+ resource_pool_ = nullptr;
+ staging_resource_pool_ = nullptr;
+ raster_worker_pool_ = nullptr;
+ single_thread_synchronous_task_graph_runner_ = nullptr;
}
bool LayerTreeHostImpl::UsePendingTreeForSync() const {
return settings_.impl_side_painting;
}
-bool LayerTreeHostImpl::UseZeroCopyRasterizer() const {
- return settings_.use_zero_copy && GetRendererCapabilities().using_map_image;
+bool LayerTreeHostImpl::IsSynchronousSingleThreaded() const {
+ return !proxy_->HasImplThread() && !settings_.single_thread_proxy_scheduler;
+}
+
+bool LayerTreeHostImpl::CanUseZeroCopyRasterizer() const {
+ return GetRendererCapabilities().using_image;
}
-bool LayerTreeHostImpl::UseOneCopyRasterizer() const {
+bool LayerTreeHostImpl::CanUseOneCopyRasterizer() const {
// Sync query support is required by one-copy rasterizer.
- return settings_.use_one_copy && GetRendererCapabilities().using_map_image &&
+ return GetRendererCapabilities().using_image &&
resource_provider_->use_sync_query();
}
ReleaseTreeResources();
// Note: order is important here.
- renderer_.reset();
+ renderer_ = nullptr;
DestroyTileManager();
- resource_provider_.reset();
- output_surface_.reset();
+ resource_provider_ = nullptr;
+ output_surface_ = nullptr;
if (!output_surface->BindToClient(this))
return false;
resource_provider_ =
ResourceProvider::Create(output_surface_.get(),
shared_bitmap_manager_,
+ gpu_memory_buffer_manager_,
proxy_->blocking_main_thread_task_runner(),
settings_.highp_threshold_min,
settings_.use_rgba_4444_textures,
- settings_.texture_id_allocation_chunk_size,
- settings_.use_distance_field_text);
+ settings_.texture_id_allocation_chunk_size);
if (output_surface_->capabilities().deferred_gl_initialization)
EnforceZeroBudget(true);
// There will not be anything to draw here, so set high res
// to avoid checkerboards, typically when we are recovering
// from lost context.
- active_tree_->SetRequiresHighResToDraw();
+ SetRequiresHighResToDraw();
return true;
}
DCHECK(output_surface_->context_provider());
ReleaseTreeResources();
- renderer_.reset();
+ renderer_ = nullptr;
DestroyTileManager();
resource_provider_->InitializeGL();
DCHECK(output_surface_->context_provider());
ReleaseTreeResources();
- renderer_.reset();
+ renderer_ = nullptr;
DestroyTileManager();
resource_provider_->InitializeSoftware();
device_viewport_size_ = device_viewport_size;
- UpdateInnerViewportContainerSize();
+ UpdateViewportContainerSizes();
client_->OnCanDrawStateChanged(CanDraw());
SetFullRootLayerDamage();
active_tree_->set_needs_update_draw_properties();
}
void LayerTreeHostImpl::DidChangeTopControlsPosition() {
- UpdateInnerViewportContainerSize();
+ UpdateViewportContainerSizes();
SetNeedsRedraw();
SetNeedsAnimate();
active_tree_->set_needs_update_draw_properties();
ScrollOffsetAnimationCurve* curve =
animation->curve()->ToScrollOffsetAnimationCurve();
- gfx::Vector2dF new_target = curve->target_value() + scroll_delta;
- new_target.SetToMax(gfx::Vector2dF());
+ gfx::ScrollOffset new_target =
+ gfx::ScrollOffsetWithDelta(curve->target_value(), scroll_delta);
+ new_target.SetToMax(gfx::ScrollOffset());
new_target.SetToMin(layer_impl->MaxScrollOffset());
curve->UpdateTarget(animation->TrimTimeToCurrentIteration(
if (!layer_impl->scrollable())
continue;
- gfx::Vector2dF current_offset = layer_impl->TotalScrollOffset();
- gfx::Vector2dF target_offset = current_offset + pending_delta;
- target_offset.SetToMax(gfx::Vector2dF());
+ gfx::ScrollOffset current_offset = layer_impl->TotalScrollOffset();
+ gfx::ScrollOffset target_offset =
+ ScrollOffsetWithDelta(current_offset, pending_delta);
+ target_offset.SetToMax(gfx::ScrollOffset());
target_offset.SetToMin(layer_impl->MaxScrollOffset());
- gfx::Vector2dF actual_delta = target_offset - current_offset;
+ gfx::Vector2dF actual_delta = target_offset.DeltaFrom(current_offset);
const float kEpsilon = 0.1f;
bool can_layer_scroll = (std::abs(actual_delta.x()) > kEpsilon ||
curve->SetInitialValue(current_offset);
scoped_ptr<Animation> animation =
- Animation::Create(curve.PassAs<AnimationCurve>(),
+ Animation::Create(curve.Pass(),
AnimationIdProvider::NextAnimationId(),
AnimationIdProvider::NextGroupId(),
Animation::ScrollOffset);
return layer_impl->ScrollDelta() - previous_delta;
}
-bool LayerTreeHostImpl::ScrollBy(const gfx::Point& viewport_point,
- const gfx::Vector2dF& scroll_delta) {
+bool LayerTreeHostImpl::ShouldTopControlsConsumeScroll(
+ const gfx::Vector2dF& scroll_delta) const {
+ DCHECK(CurrentlyScrollingLayer());
+
+ if (!top_controls_manager_)
+ return false;
+
+ // Always consume if it's in the direction to show the top controls.
+ if (scroll_delta.y() < 0)
+ return true;
+
+ if (CurrentlyScrollingLayer() != InnerViewportScrollLayer() &&
+ CurrentlyScrollingLayer() != OuterViewportScrollLayer())
+ return false;
+
+ if (InnerViewportScrollLayer()->MaxScrollOffset().y() > 0)
+ return true;
+
+ if (OuterViewportScrollLayer() &&
+ OuterViewportScrollLayer()->MaxScrollOffset().y() > 0)
+ return true;
+
+ return false;
+}
+
+InputHandlerScrollResult LayerTreeHostImpl::ScrollBy(
+ const gfx::Point& viewport_point,
+ const gfx::Vector2dF& scroll_delta) {
TRACE_EVENT0("cc", "LayerTreeHostImpl::ScrollBy");
if (!CurrentlyScrollingLayer())
- return false;
+ return InputHandlerScrollResult();
gfx::Vector2dF pending_delta = scroll_delta;
gfx::Vector2dF unused_root_delta;
bool did_scroll_x = false;
bool did_scroll_y = false;
bool did_scroll_top_controls = false;
- // TODO(wjmaclean) Should we guard against CurrentlyScrollingLayer() == 0
- // here?
- bool consume_by_top_controls =
- top_controls_manager_ &&
- (((CurrentlyScrollingLayer() == InnerViewportScrollLayer() ||
- CurrentlyScrollingLayer() == OuterViewportScrollLayer()) &&
- InnerViewportScrollLayer()->MaxScrollOffset().y() > 0) ||
- scroll_delta.y() < 0);
- for (LayerImpl* layer_impl = CurrentlyScrollingLayer();
+ bool consume_by_top_controls = ShouldTopControlsConsumeScroll(scroll_delta);
+
+ // There's an edge case where the outer viewport isn't scrollable when the
+ // scroll starts, however, as the top controls show the outer viewport becomes
+ // scrollable. Therefore, always try scrolling the outer viewport before the
+ // inner.
+ // TODO(bokan): Move the top controls logic out of the loop since the scroll
+ // that causes the outer viewport to become scrollable will still be applied
+ // to the inner viewport.
+ LayerImpl* start_layer = CurrentlyScrollingLayer();
+ if (start_layer == InnerViewportScrollLayer() && OuterViewportScrollLayer())
+ start_layer = OuterViewportScrollLayer();
+
+ for (LayerImpl* layer_impl = start_layer;
layer_impl;
layer_impl = layer_impl->parent()) {
if (!layer_impl->scrollable())
continue;
- if (layer_impl == InnerViewportScrollLayer()) {
- // Only allow bubble scrolling when the scroll is in the direction to make
- // the top controls visible.
- gfx::Vector2dF applied_delta;
- gfx::Vector2dF excess_delta;
+ if (layer_impl == InnerViewportScrollLayer() ||
+ layer_impl == OuterViewportScrollLayer()) {
if (consume_by_top_controls) {
- excess_delta = top_controls_manager_->ScrollBy(pending_delta);
- applied_delta = pending_delta - excess_delta;
+ gfx::Vector2dF excess_delta =
+ top_controls_manager_->ScrollBy(pending_delta);
+ gfx::Vector2dF applied_delta = pending_delta - excess_delta;
pending_delta = excess_delta;
// Force updating of vertical adjust values if needed.
- if (applied_delta.y() != 0) {
+ if (applied_delta.y() != 0)
did_scroll_top_controls = true;
- layer_impl->ScrollbarParametersDidChange();
- }
}
// Track root layer deltas for reporting overscroll.
- unused_root_delta = pending_delta;
+ if (layer_impl == InnerViewportScrollLayer())
+ unused_root_delta = pending_delta;
}
gfx::Vector2dF applied_delta;
unused_root_delta.set_y(0.0f);
// Disable overscroll on axes which is impossible to scroll.
if (settings_.report_overscroll_only_for_scrollable_axes) {
- if (std::abs(active_tree_->TotalMaxScrollOffset().x()) <= kEpsilon)
+ if (std::abs(active_tree_->TotalMaxScrollOffset().x()) <= kEpsilon ||
+ !layer_impl->user_scrollable_horizontal())
unused_root_delta.set_x(0.0f);
- if (std::abs(active_tree_->TotalMaxScrollOffset().y()) <= kEpsilon)
+ if (std::abs(active_tree_->TotalMaxScrollOffset().y()) <= kEpsilon ||
+ !layer_impl->user_scrollable_vertical())
unused_root_delta.set_y(0.0f);
}
}
+ // Scrolls should bubble perfectly between the outer and inner viewports.
+ bool allow_unrestricted_bubbling_for_current_layer =
+ layer_impl == OuterViewportScrollLayer();
+ bool allow_bubbling_for_current_layer =
+ allow_unrestricted_bubbling_for_current_layer || should_bubble_scrolls_;
+
// If the layer wasn't able to move, try the next one in the hierarchy.
bool did_move_layer_x = std::abs(applied_delta.x()) > kEpsilon;
bool did_move_layer_y = std::abs(applied_delta.y()) > kEpsilon;
did_scroll_x |= did_move_layer_x;
did_scroll_y |= did_move_layer_y;
if (!did_move_layer_x && !did_move_layer_y) {
- // Scrolls should always bubble between the outer and inner viewports
- if (should_bubble_scrolls_ || !did_lock_scrolling_layer_ ||
- layer_impl == OuterViewportScrollLayer())
+ if (allow_bubbling_for_current_layer || !did_lock_scrolling_layer_)
continue;
else
break;
}
did_lock_scrolling_layer_ = true;
- if (!should_bubble_scrolls_) {
+ if (!allow_bubbling_for_current_layer) {
active_tree_->SetCurrentlyScrollingLayer(layer_impl);
break;
}
- // If the applied delta is within 45 degrees of the input delta, bail out to
- // make it easier to scroll just one layer in one direction without
- // affecting any of its parents.
- float angle_threshold = 45;
- if (MathUtil::SmallestAngleBetweenVectors(
- applied_delta, pending_delta) < angle_threshold) {
- pending_delta = gfx::Vector2d();
- break;
- }
+ if (allow_unrestricted_bubbling_for_current_layer) {
+ pending_delta -= applied_delta;
+ } else {
+ // If the applied delta is within 45 degrees of the input delta, bail out
+ // to make it easier to scroll just one layer in one direction without
+ // affecting any of its parents.
+ float angle_threshold = 45;
+ if (MathUtil::SmallestAngleBetweenVectors(applied_delta, pending_delta) <
+ angle_threshold) {
+ pending_delta = gfx::Vector2dF();
+ break;
+ }
- // Allow further movement only on an axis perpendicular to the direction in
- // which the layer moved.
- gfx::Vector2dF perpendicular_axis(-applied_delta.y(), applied_delta.x());
- pending_delta = MathUtil::ProjectVector(pending_delta, perpendicular_axis);
+ // Allow further movement only on an axis perpendicular to the direction
+ // in which the layer moved.
+ gfx::Vector2dF perpendicular_axis(-applied_delta.y(), applied_delta.x());
+ pending_delta =
+ MathUtil::ProjectVector(pending_delta, perpendicular_axis);
+ }
if (gfx::ToRoundedVector2d(pending_delta).IsZero())
break;
accumulated_root_overscroll_.set_x(0);
if (did_scroll_y)
accumulated_root_overscroll_.set_y(0);
-
accumulated_root_overscroll_ += unused_root_delta;
- bool did_overscroll = !unused_root_delta.IsZero();
- if (did_overscroll && input_handler_client_) {
- input_handler_client_->DidOverscroll(
- viewport_point, accumulated_root_overscroll_, unused_root_delta);
- }
- return did_scroll_content || did_scroll_top_controls;
+ InputHandlerScrollResult scroll_result;
+ scroll_result.did_scroll = did_scroll_content || did_scroll_top_controls;
+ scroll_result.did_overscroll_root = !unused_root_delta.IsZero();
+ scroll_result.accumulated_root_overscroll = accumulated_root_overscroll_;
+ scroll_result.unused_scroll_delta = unused_root_delta;
+ return scroll_result;
}
// This implements scrolling by page as described here:
}
void LayerTreeHostImpl::OnRootLayerDelegatedScrollOffsetChanged() {
- DCHECK(root_layer_scroll_offset_delegate_ != NULL);
+ DCHECK(root_layer_scroll_offset_delegate_);
client_->SetNeedsCommitOnImplThread();
+ SetNeedsRedraw();
+ active_tree_->OnRootLayerDelegatedScrollOffsetChanged();
active_tree_->set_needs_update_draw_properties();
}
SetViewportDamage(gfx::Rect(DrawViewportSize()));
}
+void LayerTreeHostImpl::ScrollViewportInnerFirst(gfx::Vector2dF scroll_delta) {
+ DCHECK(InnerViewportScrollLayer());
+ LayerImpl* scroll_layer = InnerViewportScrollLayer();
+
+ gfx::Vector2dF unused_delta = scroll_layer->ScrollBy(scroll_delta);
+ if (!unused_delta.IsZero() && OuterViewportScrollLayer())
+ OuterViewportScrollLayer()->ScrollBy(unused_delta);
+}
+
void LayerTreeHostImpl::ScrollViewportBy(gfx::Vector2dF scroll_delta) {
DCHECK(InnerViewportScrollLayer());
LayerImpl* scroll_layer = OuterViewportScrollLayer()
if (!page_scale_animation_)
return;
- gfx::Vector2dF scroll_total = active_tree_->TotalScrollOffset();
+ gfx::ScrollOffset scroll_total = active_tree_->TotalScrollOffset();
if (!page_scale_animation_->IsAnimationStarted())
page_scale_animation_->StartAnimation(monotonic_time);
active_tree_->SetPageScaleDelta(
page_scale_animation_->PageScaleFactorAtTime(monotonic_time) /
active_tree_->page_scale_factor());
- gfx::Vector2dF next_scroll =
- page_scale_animation_->ScrollOffsetAtTime(monotonic_time);
+ gfx::ScrollOffset next_scroll = gfx::ScrollOffset(
+ page_scale_animation_->ScrollOffsetAtTime(monotonic_time));
- ScrollViewportBy(next_scroll - scroll_total);
+ ScrollViewportInnerFirst(next_scroll.DeltaFrom(scroll_total));
SetNeedsRedraw();
if (page_scale_animation_->IsAnimationCompleteAtTime(monotonic_time)) {
- page_scale_animation_.reset();
+ page_scale_animation_ = nullptr;
client_->SetNeedsCommitOnImplThread();
client_->RenewTreePriority();
} else {
DidModifyTilePriorities();
}
+TreePriority LayerTreeHostImpl::GetTreePriority() const {
+ return global_tile_state_.tree_priority;
+}
+
void LayerTreeHostImpl::UpdateCurrentBeginFrameArgs(
const BeginFrameArgs& args) {
DCHECK(!current_begin_frame_args_.IsValid());
BeginFrameArgs::DefaultInterval());
}
+void LayerTreeHostImpl::AsValueInto(base::debug::TracedValue* value) const {
+ return AsValueWithFrameInto(NULL, value);
+}
+
scoped_refptr<base::debug::ConvertableToTraceFormat>
LayerTreeHostImpl::AsValue() const {
return AsValueWithFrame(NULL);