Home | History | Annotate | Download | only in view_manager
      1 // Copyright 2014 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 "mojo/services/view_manager/display_manager.h"
      6 
      7 #include "base/numerics/safe_conversions.h"
      8 #include "cc/surfaces/surface_id_allocator.h"
      9 #include "mojo/public/cpp/application/application_connection.h"
     10 #include "mojo/services/public/cpp/geometry/geometry_type_converters.h"
     11 #include "mojo/services/public/cpp/surfaces/surfaces_type_converters.h"
     12 #include "mojo/services/public/cpp/surfaces/surfaces_utils.h"
     13 #include "mojo/services/public/interfaces/gpu/gpu.mojom.h"
     14 #include "mojo/services/public/interfaces/surfaces/quads.mojom.h"
     15 #include "mojo/services/view_manager/connection_manager.h"
     16 
     17 namespace mojo {
     18 namespace service {
     19 namespace {
     20 
     21 gfx::Rect ConvertRectToRoot(const ServerView* view, const gfx::Rect& bounds) {
     22   gfx::Point origin(bounds.origin());
     23   while (view->parent()) {
     24     origin += view->bounds().OffsetFromOrigin();
     25     view = view->parent();
     26     if (!view->visible())
     27       return gfx::Rect();
     28   }
     29   return gfx::Rect(origin, bounds.size());
     30 }
     31 
     32 void DrawViewTree(Pass* pass, const ServerView* view, gfx::Vector2d offset) {
     33   if (!view->visible())
     34     return;
     35 
     36   gfx::Rect node_bounds = view->bounds() + offset;
     37   std::vector<const ServerView*> children(view->GetChildren());
     38   for (std::vector<const ServerView*>::reverse_iterator it = children.rbegin();
     39        it != children.rend();
     40        ++it) {
     41     DrawViewTree(pass, *it, offset + view->bounds().OffsetFromOrigin());
     42   }
     43 
     44   cc::SurfaceId node_id = view->surface_id();
     45 
     46   SurfaceQuadStatePtr surface_quad_state = SurfaceQuadState::New();
     47   surface_quad_state->surface = SurfaceId::From(node_id);
     48 
     49   gfx::Transform node_transform;
     50   node_transform.Translate(node_bounds.x(), node_bounds.y());
     51 
     52   QuadPtr surface_quad = Quad::New();
     53   surface_quad->material = Material::MATERIAL_SURFACE_CONTENT;
     54   surface_quad->rect = Rect::From(node_bounds);
     55   surface_quad->opaque_rect = Rect::From(node_bounds);
     56   surface_quad->visible_rect = Rect::From(node_bounds);
     57   surface_quad->needs_blending = true;
     58   surface_quad->shared_quad_state_index =
     59       base::saturated_cast<int32_t>(pass->shared_quad_states.size());
     60   surface_quad->surface_quad_state = surface_quad_state.Pass();
     61 
     62   SharedQuadStatePtr sqs = CreateDefaultSQS(node_bounds.size());
     63   sqs->content_to_target_transform = Transform::From(node_transform);
     64 
     65   pass->quads.push_back(surface_quad.Pass());
     66   pass->shared_quad_states.push_back(sqs.Pass());
     67 }
     68 
     69 }  // namespace
     70 
     71 DisplayManager::DisplayManager(
     72     ApplicationConnection* app_connection,
     73     ConnectionManager* connection_manager,
     74     const Callback<void()>& native_viewport_closed_callback)
     75     : connection_manager_(connection_manager),
     76       in_setup_(false),
     77       bounds_(800, 600),
     78       draw_timer_(false, false),
     79       weak_factory_(this) {
     80   app_connection->ConnectToService("mojo:mojo_native_viewport_service",
     81                                    &native_viewport_);
     82   native_viewport_.set_client(this);
     83   native_viewport_->Create(Size::From(bounds_));
     84   native_viewport_->Show();
     85   app_connection->ConnectToService("mojo:mojo_surfaces_service",
     86                                    &surfaces_service_);
     87   surfaces_service_->CreateSurfaceConnection(base::Bind(
     88       &DisplayManager::OnSurfaceConnectionCreated, weak_factory_.GetWeakPtr()));
     89 }
     90 
     91 DisplayManager::~DisplayManager() {
     92 }
     93 
     94 void DisplayManager::SchedulePaint(const ServerView* view,
     95                                    const gfx::Rect& bounds) {
     96   if (!view->visible())
     97     return;
     98   gfx::Rect root_relative_rect = ConvertRectToRoot(view, bounds);
     99   if (root_relative_rect.IsEmpty())
    100     return;
    101   dirty_rect_.Union(root_relative_rect);
    102   if (!draw_timer_.IsRunning()) {
    103     draw_timer_.Start(
    104         FROM_HERE,
    105         base::TimeDelta(),
    106         base::Bind(&DisplayManager::Draw, base::Unretained(this)));
    107   }
    108 }
    109 
    110 void DisplayManager::OnSurfaceConnectionCreated(SurfacePtr surface,
    111                                                 uint32_t id_namespace) {
    112   surface_ = surface.Pass();
    113   surface_.set_client(this);
    114   surface_id_allocator_.reset(new cc::SurfaceIdAllocator(id_namespace));
    115   Draw();
    116 }
    117 
    118 void DisplayManager::Draw() {
    119   if (!surface_)
    120     return;
    121   if (surface_id_.is_null()) {
    122     surface_id_ = surface_id_allocator_->GenerateId();
    123     surface_->CreateSurface(SurfaceId::From(surface_id_), Size::From(bounds_));
    124   }
    125 
    126   PassPtr pass = CreateDefaultPass(1, gfx::Rect(bounds_));
    127   pass->damage_rect = Rect::From(dirty_rect_);
    128 
    129   DrawViewTree(pass.get(), connection_manager_->root(), gfx::Vector2d());
    130 
    131   FramePtr frame = Frame::New();
    132   frame->passes.push_back(pass.Pass());
    133   frame->resources.resize(0u);
    134   surface_->SubmitFrame(SurfaceId::From(surface_id_), frame.Pass());
    135 
    136   native_viewport_->SubmittedFrame(SurfaceId::From(surface_id_));
    137 
    138   dirty_rect_ = gfx::Rect();
    139 }
    140 
    141 void DisplayManager::OnCreated(uint64_t native_viewport_id) {
    142 }
    143 
    144 void DisplayManager::OnDestroyed() {
    145   native_viewport_closed_callback_.Run();
    146 }
    147 
    148 void DisplayManager::OnBoundsChanged(SizePtr bounds) {
    149   bounds_ = bounds.To<gfx::Size>();
    150   connection_manager_->root()->SetBounds(gfx::Rect(bounds_));
    151   if (surface_id_.is_null())
    152     return;
    153   surface_->DestroySurface(SurfaceId::From(surface_id_));
    154   surface_id_ = cc::SurfaceId();
    155   SchedulePaint(connection_manager_->root(), gfx::Rect(bounds_));
    156 }
    157 
    158 void DisplayManager::OnEvent(EventPtr event,
    159                              const mojo::Callback<void()>& callback) {
    160   connection_manager_->DispatchViewInputEventToWindowManager(event.Pass());
    161   callback.Run();
    162 }
    163 
    164 void DisplayManager::ReturnResources(Array<ReturnedResourcePtr> resources) {
    165   DCHECK_EQ(0u, resources.size());
    166 }
    167 
    168 }  // namespace service
    169 }  // namespace mojo
    170