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 "base/bind.h"
6#include "base/macros.h"
7#include "base/message_loop/message_loop.h"
8#include "cc/surfaces/surface_id_allocator.h"
9#include "mojo/application/application_runner_chromium.h"
10#include "mojo/examples/surfaces_app/child.mojom.h"
11#include "mojo/examples/surfaces_app/embedder.h"
12#include "mojo/public/c/system/main.h"
13#include "mojo/public/cpp/application/application_connection.h"
14#include "mojo/public/cpp/application/application_delegate.h"
15#include "mojo/public/cpp/system/core.h"
16#include "mojo/services/gles2/command_buffer.mojom.h"
17#include "mojo/services/public/cpp/geometry/geometry_type_converters.h"
18#include "mojo/services/public/cpp/surfaces/surfaces_type_converters.h"
19#include "mojo/services/public/interfaces/gpu/gpu.mojom.h"
20#include "mojo/services/public/interfaces/native_viewport/native_viewport.mojom.h"
21#include "mojo/services/public/interfaces/surfaces/surfaces.mojom.h"
22#include "mojo/services/public/interfaces/surfaces/surfaces_service.mojom.h"
23#include "ui/gfx/rect.h"
24
25namespace mojo {
26namespace examples {
27
28class SurfacesApp : public ApplicationDelegate,
29                    public SurfaceClient,
30                    public NativeViewportClient {
31 public:
32  SurfacesApp() {}
33  virtual ~SurfacesApp() {}
34
35  // ApplicationDelegate implementation
36  virtual bool ConfigureIncomingConnection(
37      ApplicationConnection* connection) OVERRIDE {
38    connection->ConnectToService("mojo:mojo_native_viewport_service",
39                                 &viewport_);
40    viewport_.set_client(this);
41
42    connection->ConnectToService("mojo:mojo_surfaces_service",
43                                 &surfaces_service_);
44    surfaces_service_->CreateSurfaceConnection(base::Bind(
45        &SurfacesApp::SurfaceConnectionCreated, base::Unretained(this)));
46
47    size_ = gfx::Size(800, 600);
48
49    viewport_->Create(Size::From(size_));
50    viewport_->Show();
51
52    child_size_ = gfx::Size(size_.width() / 3, size_.height() / 2);
53    connection->ConnectToService("mojo:mojo_surfaces_child_app", &child_one_);
54    connection->ConnectToService("mojo:mojo_surfaces_child_gl_app",
55                                 &child_two_);
56    child_one_->ProduceFrame(Color::From(SK_ColorBLUE),
57                             Size::From(child_size_),
58                             base::Bind(&SurfacesApp::ChildOneProducedFrame,
59                                        base::Unretained(this)));
60    child_two_->ProduceFrame(Color::From(SK_ColorGREEN),
61                             Size::From(child_size_),
62                             base::Bind(&SurfacesApp::ChildTwoProducedFrame,
63                                        base::Unretained(this)));
64    return true;
65  }
66
67  void ChildOneProducedFrame(SurfaceIdPtr id) {
68    child_one_id_ = id.To<cc::SurfaceId>();
69  }
70
71  void ChildTwoProducedFrame(SurfaceIdPtr id) {
72    child_two_id_ = id.To<cc::SurfaceId>();
73  }
74
75  void Draw(int offset) {
76    int bounced_offset = offset;
77    if (offset > 200)
78      bounced_offset = 400 - offset;
79    embedder_->ProduceFrame(
80        child_one_id_, child_two_id_, child_size_, size_, bounced_offset);
81    base::MessageLoop::current()->PostDelayedTask(
82        FROM_HERE,
83        base::Bind(
84            &SurfacesApp::Draw, base::Unretained(this), (offset + 2) % 400),
85        base::TimeDelta::FromMilliseconds(50));
86  }
87
88  void SurfaceConnectionCreated(SurfacePtr surface, uint32_t id_namespace) {
89    surface_ = surface.Pass();
90    surface_.set_client(this);
91    embedder_.reset(new Embedder(surface_.get()));
92    allocator_.reset(new cc::SurfaceIdAllocator(id_namespace));
93
94    onscreen_id_ = allocator_->GenerateId();
95    embedder_->SetSurfaceId(onscreen_id_);
96    surface_->CreateSurface(SurfaceId::From(onscreen_id_), Size::From(size_));
97    viewport_->SubmittedFrame(SurfaceId::From(onscreen_id_));
98    Draw(10);
99  }
100
101  // SurfaceClient implementation.
102  virtual void ReturnResources(Array<ReturnedResourcePtr> resources) OVERRIDE {
103    DCHECK(!resources.size());
104  }
105  // NativeViewportClient implementation.
106  virtual void OnCreated(uint64_t native_viewport_id) OVERRIDE {}
107  virtual void OnBoundsChanged(mojo::SizePtr bounds) OVERRIDE {}
108  virtual void OnDestroyed() OVERRIDE {}
109  virtual void OnEvent(mojo::EventPtr event,
110                       const mojo::Callback<void()>& callback) OVERRIDE {
111    callback.Run();
112  }
113
114 private:
115  SurfacesServicePtr surfaces_service_;
116  SurfacePtr surface_;
117  cc::SurfaceId onscreen_id_;
118  scoped_ptr<cc::SurfaceIdAllocator> allocator_;
119  scoped_ptr<Embedder> embedder_;
120  ChildPtr child_one_;
121  cc::SurfaceId child_one_id_;
122  ChildPtr child_two_;
123  cc::SurfaceId child_two_id_;
124  gfx::Size size_;
125  gfx::Size child_size_;
126
127  NativeViewportPtr viewport_;
128
129  DISALLOW_COPY_AND_ASSIGN(SurfacesApp);
130};
131
132}  // namespace examples
133}  // namespace mojo
134
135MojoResult MojoMain(MojoHandle shell_handle) {
136  mojo::ApplicationRunnerChromium runner(new mojo::examples::SurfacesApp);
137  return runner.Run(shell_handle);
138}
139