// Copyright 2014 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 "cc/surfaces/display.h" #include "base/message_loop/message_loop.h" #include "cc/output/compositor_frame.h" #include "cc/output/direct_renderer.h" #include "cc/output/gl_renderer.h" #include "cc/output/software_renderer.h" #include "cc/surfaces/display_client.h" #include "cc/surfaces/surface.h" namespace cc { static ResourceProvider::ResourceId ResourceRemapHelper( bool* invalid_frame, const ResourceProvider::ResourceIdMap& child_to_parent_map, ResourceProvider::ResourceIdArray* resources_in_frame, ResourceProvider::ResourceId id) { ResourceProvider::ResourceIdMap::const_iterator it = child_to_parent_map.find(id); if (it == child_to_parent_map.end()) { *invalid_frame = true; return 0; } DCHECK_EQ(it->first, id); ResourceProvider::ResourceId remapped_id = it->second; resources_in_frame->push_back(id); return remapped_id; } Display::Display(DisplayClient* client, SurfaceManager* manager, SharedBitmapManager* bitmap_manager) : client_(client), manager_(manager), aggregator_(manager), bitmap_manager_(bitmap_manager) { } Display::~Display() { } void Display::Resize(const gfx::Size& size) { current_surface_.reset(new Surface(manager_, this, size)); } void Display::InitializeOutputSurface() { if (output_surface_) return; scoped_ptr output_surface = client_->CreateOutputSurface(); if (!output_surface->BindToClient(this)) return; int highp_threshold_min = 0; bool use_rgba_4444_texture_format = false; size_t id_allocation_chunk_size = 1; bool use_distance_field_text = false; scoped_ptr resource_provider = ResourceProvider::Create(output_surface.get(), bitmap_manager_, highp_threshold_min, use_rgba_4444_texture_format, id_allocation_chunk_size, use_distance_field_text); if (!resource_provider) return; LayerTreeSettings settings; if (output_surface->context_provider()) { TextureMailboxDeleter* texture_mailbox_deleter = NULL; scoped_ptr renderer = GLRenderer::Create(this, &settings, output_surface.get(), resource_provider.get(), texture_mailbox_deleter, highp_threshold_min); if (!renderer) return; renderer_ = renderer.Pass(); } else { scoped_ptr renderer = SoftwareRenderer::Create( this, &settings, output_surface.get(), resource_provider.get()); if (!renderer) return; renderer_ = renderer.Pass(); } output_surface_ = output_surface.Pass(); resource_provider_ = resource_provider.Pass(); child_id_ = resource_provider_->CreateChild( base::Bind(&Display::ReturnResources, base::Unretained(this))); } bool Display::Draw() { if (!current_surface_) return false; InitializeOutputSurface(); if (!output_surface_) return false; // TODO(jamesr): Use the surface aggregator instead. scoped_ptr frame_data(new DelegatedFrameData); CompositorFrame* current_frame = current_surface_->GetEligibleFrame(); frame_data->resource_list = current_frame->delegated_frame_data->resource_list; RenderPass::CopyAll(current_frame->delegated_frame_data->render_pass_list, &frame_data->render_pass_list); if (frame_data->render_pass_list.empty()) return false; const ResourceProvider::ResourceIdMap& resource_map = resource_provider_->GetChildToParentMap(child_id_); resource_provider_->ReceiveFromChild(child_id_, frame_data->resource_list); bool invalid_frame = false; ResourceProvider::ResourceIdArray resources_in_frame; DrawQuad::ResourceIteratorCallback remap_resources_to_parent_callback = base::Bind(&ResourceRemapHelper, &invalid_frame, resource_map, &resources_in_frame); for (size_t i = 0; i < frame_data->render_pass_list.size(); ++i) { RenderPass* pass = frame_data->render_pass_list[i]; for (size_t j = 0; j < pass->quad_list.size(); ++j) { DrawQuad* quad = pass->quad_list[j]; quad->IterateResources(remap_resources_to_parent_callback); } } if (invalid_frame) return false; resource_provider_->DeclareUsedResourcesFromChild(child_id_, resources_in_frame); float device_scale_factor = 1.0f; gfx::Rect device_viewport_rect = gfx::Rect(current_surface_->size()); gfx::Rect device_clip_rect = device_viewport_rect; bool disable_picture_quad_image_filtering = false; renderer_->DrawFrame(&frame_data->render_pass_list, device_scale_factor, device_viewport_rect, device_clip_rect, disable_picture_quad_image_filtering); CompositorFrameMetadata metadata; renderer_->SwapBuffers(metadata); return true; } int Display::CurrentSurfaceID() { return current_surface_ ? current_surface_->surface_id() : 0; } void Display::ReturnResources(const ReturnedResourceArray& resources) { } } // namespace cc