Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(51)

Side by Side Diff: examples/ui/spinning_cube/spinning_cube_view.cc

Issue 1559723002: Update the UI examples. (Closed) Base URL: git@github.com:domokit/mojo.git@moz-14
Patch Set: Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "examples/ui/spinning_cube/spinning_cube_view.h"
6
7 #ifndef GL_GLEXT_PROTOTYPES
8 #define GL_GLEXT_PROTOTYPES
9 #endif
5 #include <GLES2/gl2.h> 10 #include <GLES2/gl2.h>
6 #include <GLES2/gl2extmojo.h> 11 #include <GLES2/gl2extmojo.h>
7 #include <MGL/mgl.h>
8 12
9 #include "base/message_loop/message_loop.h" 13 #include "base/bind.h"
10 #include "examples/ui/spinning_cube/spinning_cube_view.h" 14 #include "mojo/services/geometry/cpp/geometry_util.h"
11 15
12 namespace examples { 16 namespace examples {
13 17
18 constexpr uint32_t kCubeImageResourceId = 1;
19 constexpr uint32_t kRootNodeId = mojo::gfx::composition::kSceneRootNodeId;
20
21 // TODO(johngro) : investigate extending mojom with a formal flags type which it
22 // generates good bindings for, so we don't need to resort to this.
23 static constexpr bool operator&(const mojo::EventFlags& f1,
24 const mojo::EventFlags& f2) {
25 return ((static_cast<uint32_t>(f1) & static_cast<uint32_t>(f2)) != 0);
26 }
27
28 static float CalculateDragDistance(const mojo::PointF& start,
29 const mojo::PointF& end) {
30 return hypot(start.x - end.x, start.y - end.y);
viettrungluu 2016/01/13 00:10:57 - include <math.h> for this - possibly, you may wa
jeffbrown 2016/01/26 08:14:17 Let's use <cmath>. Note that this code was just c
31 }
32
33 static float GetRandomColor() {
34 return static_cast<float>(rand()) / static_cast<float>(RAND_MAX);
35 }
36
37 // Return a direction multiplier to apply to drag distances:
38 // 1 for natural (positive) motion, -1 for reverse (negative) motion
39 static int GetEventDirection(const mojo::PointF& current,
40 const mojo::PointF& initial,
41 const mojo::PointF& last) {
42 // Axis of motion is determined by coarse alignment of overall movement
43 bool use_x =
44 std::abs(current.y - initial.y) < std::abs(current.x - initial.x);
viettrungluu 2016/01/13 00:10:57 To get the std::abs overloads for float or double,
jeffbrown 2016/01/26 08:14:17 Since we want the float version I just included cm
45 // Current direction is determined by comparison with previous point
46 float delta = use_x ? (current.x - last.x) : (current.y - last.y);
47 return delta > 0 ? -1 : 1;
48 }
49
14 SpinningCubeView::SpinningCubeView( 50 SpinningCubeView::SpinningCubeView(
15 mojo::ApplicationImpl* app, 51 mojo::ApplicationImpl* app_impl,
16 const mojo::ui::ViewProvider::CreateViewCallback& callback) 52 const mojo::ui::ViewProvider::CreateViewCallback& create_view_callback)
17 : callback_(callback), 53 : GLView(app_impl, "SpinningCube", create_view_callback),
18 binding_(this), 54 choreographer_(scene(), this),
19 context_owner_(app->shell()), 55 input_handler_(view_service_provider(), this),
20 texture_cache_(context_owner_.context(), &resource_returner_),
21 surface_id_namespace_(0),
22 draw_scheduled_(false),
23 weak_ptr_factory_(this) { 56 weak_ptr_factory_(this) {
24 app->ConnectToService("mojo:surfaces_service", &surfaces_); 57 gl_renderer()->gl_context()->MakeCurrent();
25 app->ConnectToService("mojo:view_manager_service", &view_manager_); 58 cube_.Init();
26
27 surfaces_->SetResourceReturner(resource_returner_.Pass());
28 surfaces_->GetIdNamespace(
29 base::Bind(&SpinningCubeView::OnSurfaceIdNamespaceAvailable,
30 base::Unretained(this)));
31
32 InitCube();
33 } 59 }
34 60
35 SpinningCubeView::~SpinningCubeView() {} 61 SpinningCubeView::~SpinningCubeView() {}
36 62
37 void SpinningCubeView::OnSurfaceIdNamespaceAvailable(uint32_t id_namespace) {
38 surface_id_namespace_ = id_namespace;
39 InitView();
40 }
41
42 void SpinningCubeView::InitView() {
43 mojo::ui::ViewPtr view;
44 binding_.Bind(mojo::GetProxy(&view));
45 view_manager_->RegisterView(view.Pass(), mojo::GetProxy(&view_host_),
46 callback_);
47
48 view_host_->GetServiceProvider(mojo::GetProxy(&view_service_provider_));
49 }
50
51 void SpinningCubeView::OnLayout(mojo::ui::ViewLayoutParamsPtr layout_params, 63 void SpinningCubeView::OnLayout(mojo::ui::ViewLayoutParamsPtr layout_params,
52 mojo::Array<uint32_t> children_needing_layout, 64 mojo::Array<uint32_t> children_needing_layout,
53 const OnLayoutCallback& callback) { 65 const OnLayoutCallback& callback) {
54 // Create a new surface the first time or if the size has changed. 66 size_.width = layout_params->constraints->max_width;
55 mojo::Size new_size; 67 size_.height = layout_params->constraints->max_height;
56 new_size.width = layout_params->constraints->max_width;
57 new_size.height = layout_params->constraints->max_height;
58 if (!surface_id_ || !size_.Equals(new_size)) {
59 if (!surface_id_) {
60 surface_id_ = mojo::SurfaceId::New();
61 surface_id_->id_namespace = surface_id_namespace_;
62 } else {
63 surfaces_->DestroySurface(surface_id_->local);
64 }
65 surface_id_->local++;
66 size_ = new_size;
67 surfaces_->CreateSurface(surface_id_->local);
68 }
69 68
70 // Submit the new layout information. 69 // Submit the new layout information.
71 auto info = mojo::ui::ViewLayoutInfo::New(); 70 auto info = mojo::ui::ViewLayoutResult::New();
72 info->size = size_.Clone(); 71 info->size = size_.Clone();
73 info->surface_id = surface_id_->Clone();
74 callback.Run(info.Pass()); 72 callback.Run(info.Pass());
75 73
76 // Draw! 74 // Draw!
77 ScheduleDraw(); 75 choreographer_.ScheduleDraw();
78 } 76 }
79 77
80 void SpinningCubeView::OnChildUnavailable( 78 void SpinningCubeView::OnEvent(mojo::EventPtr event,
81 uint32_t child_key, 79 const OnEventCallback& callback) {
82 const OnChildUnavailableCallback& callback) { 80 if (!event->pointer_data) {
83 callback.Run(); 81 callback.Run(false);
84 }
85
86 void SpinningCubeView::InitCube() {
87 context_owner_.context()->MakeCurrent();
88 cube_.Init();
89 last_draw_ = mojo::GetTimeTicksNow();
90 }
91
92 void SpinningCubeView::DrawCube() {
93 draw_scheduled_ = false;
94
95 scoped_ptr<mojo::TextureCache::TextureInfo> texture_info =
96 texture_cache_.GetTexture(size_);
97 if (!texture_info) {
98 LOG(ERROR) << "Could not allocate texture of size " << size_.width << "x"
99 << size_.height;
100 return; 82 return;
101 } 83 }
102 84
103 context_owner_.context()->MakeCurrent(); 85 switch (event->action) {
104 scoped_ptr<mojo::GLTexture> texture = texture_info->TakeTexture(); 86 case mojo::EventType::POINTER_DOWN:
87 if (event->flags & mojo::EventFlags::RIGHT_MOUSE_BUTTON)
88 break;
89 capture_point_.x = event->pointer_data->x;
90 capture_point_.y = event->pointer_data->y;
91 last_drag_point_ = capture_point_;
92 drag_start_time_ = mojo::GetTimeTicksNow();
93 cube_.SetFlingMultiplier(0.0f, 1.0f);
94 break;
105 95
106 GLuint fbo = 0u; 96 case mojo::EventType::POINTER_MOVE: {
107 glGenFramebuffers(1, &fbo); 97 if (!(event->flags & mojo::EventFlags::LEFT_MOUSE_BUTTON) &&
108 glBindFramebuffer(GL_FRAMEBUFFER, fbo); 98 event->pointer_data->kind == mojo::PointerKind::MOUSE) {
109 GLuint depth_buffer = 0u; 99 break;
110 glGenRenderbuffers(1, &depth_buffer); 100 }
111 glBindRenderbuffer(GL_RENDERBUFFER, depth_buffer); 101 mojo::PointF event_location;
112 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, size_.width, 102 event_location.x = event->pointer_data->x;
113 size_.height); 103 event_location.y = event->pointer_data->y;
114 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 104 int direction =
115 texture->texture_id(), 0); 105 GetEventDirection(event_location, capture_point_, last_drag_point_);
116 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, 106 cube_.UpdateForDragDistance(
117 GL_RENDERBUFFER, depth_buffer); 107 direction * CalculateDragDistance(last_drag_point_, event_location));
118 DCHECK_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE), 108 last_drag_point_ = event_location;
119 glCheckFramebufferStatus(GL_FRAMEBUFFER)); 109 break;
120 glClearColor(1, 0, 0, 0.5); 110 }
121 111
122 cube_.set_size(size_.width, size_.height); 112 case mojo::EventType::POINTER_UP: {
113 if (event->flags & mojo::EventFlags::RIGHT_MOUSE_BUTTON) {
114 cube_.set_color(GetRandomColor(), GetRandomColor(), GetRandomColor());
115 break;
116 }
117 mojo::PointF event_location;
118 event_location.x = event->pointer_data->x;
119 event_location.y = event->pointer_data->y;
120 MojoTimeTicks offset = mojo::GetTimeTicksNow() - drag_start_time_;
121 float delta = static_cast<float>(offset) / 1000000.f;
122 // Last drag point is the same as current point here; use initial capture
123 // point instead
124 int direction =
125 GetEventDirection(event_location, capture_point_, capture_point_);
126 cube_.SetFlingMultiplier(
127 direction * CalculateDragDistance(capture_point_, event_location),
128 delta);
129 capture_point_ = last_drag_point_ = mojo::PointF();
130 break;
131 }
123 132
124 MojoTimeTicks now = mojo::GetTimeTicksNow(); 133 default:
125 MojoTimeTicks offset = now - last_draw_; 134 break;
126 cube_.UpdateForTimeDelta(offset * 0.000001f); 135 }
127 last_draw_ = now;
128 136
129 cube_.Draw(); 137 callback.Run(true);
130
131 glDeleteFramebuffers(1, &fbo);
132 glDeleteRenderbuffers(1, &depth_buffer);
133
134 mojo::FramePtr frame = mojo::TextureUploader::GetUploadFrame(
135 context_owner_.context(), texture_info->resource_id(), texture);
136 surfaces_->SubmitFrame(surface_id_->local, frame.Pass(),
137 base::Bind(&SpinningCubeView::OnSurfaceSubmitted,
138 base::Unretained(this)));
139
140 texture_cache_.NotifyPendingResourceReturn(texture_info->resource_id(),
141 texture.Pass());
142 } 138 }
143 139
144 void SpinningCubeView::OnSurfaceSubmitted() { 140 void SpinningCubeView::OnDraw(
145 ScheduleDraw(); 141 const mojo::gfx::composition::FrameInfo& frame_info,
142 const base::TimeDelta& time_delta) {
143 // Update the state of the cube.
144 cube_.UpdateForTimeDelta(time_delta.InSecondsF());
145
146 // Update the contents of the scene.
147 mojo::Rect bounds;
148 bounds.width = size_.width;
149 bounds.height = size_.height;
150
151 auto update = mojo::gfx::composition::SceneUpdate::New();
152 mojo::gfx::composition::ResourcePtr cube_resource = gl_renderer()->DrawGL(
153 size_, true,
154 base::Bind(&SpinningCubeView::DrawCubeWithGL, base::Unretained(this)));
155 DCHECK(cube_resource);
156 update->resources.insert(kCubeImageResourceId, cube_resource.Pass());
157
158 auto root_node = mojo::gfx::composition::Node::New();
159 root_node->content_transform = mojo::Transform::New();
160 mojo::SetIdentityTransform(root_node->content_transform.get());
161 root_node->content_transform->matrix[5] = -1; // flip image vertically
abarth 2016/01/10 23:09:31 Why?
jeffbrown 2016/01/26 08:23:06 I'm not sure exactly. The coordinate system ends
162 root_node->content_transform->matrix[7] = size_.height;
163 root_node->op = mojo::gfx::composition::NodeOp::New();
164 root_node->op->set_image(mojo::gfx::composition::ImageNodeOp::New());
165 root_node->op->get_image()->content_rect = bounds.Clone();
166 root_node->op->get_image()->image_resource_id = kCubeImageResourceId;
167 update->nodes.insert(kRootNodeId, root_node.Pass());
168
169 auto metadata = mojo::gfx::composition::SceneMetadata::New();
170 metadata->presentation_time = frame_info.presentation_time;
171
172 // Publish the scene.
173 scene()->Update(update.Pass());
174 scene()->Publish(metadata.Pass());
175
176 // Loop!
177 choreographer_.ScheduleDraw();
146 } 178 }
147 179
148 void SpinningCubeView::ScheduleDraw() { 180 void SpinningCubeView::DrawCubeWithGL() {
149 if (!draw_scheduled_) { 181 cube_.set_size(size_.width, size_.height);
150 draw_scheduled_ = true; 182 cube_.Draw();
151
152 // TODO(jeffbrown): For now, we need to throttle this down because
153 // drawing as fast as we can appears to cause starvation of the
154 // Mojo message loop and makes X11 unhappy.
155 base::MessageLoop::current()->PostDelayedTask(
156 FROM_HERE,
157 base::Bind(&SpinningCubeView::DrawCube, weak_ptr_factory_.GetWeakPtr()),
158 base::TimeDelta::FromMilliseconds(30));
159 }
160 } 183 }
161 184
162 } // namespace examples 185 } // namespace examples
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698