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

Side by Side Diff: examples/ui/noodles/noodles_view.cc

Issue 1558813002: Add a multi-threaded rendering example. (Closed) Base URL: git@github.com:domokit/mojo.git@moz-15
Patch Set: address feedback 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
« no previous file with comments | « examples/ui/noodles/noodles_view.h ('k') | examples/ui/noodles/rasterizer.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "examples/ui/noodles/noodles_view.h"
6
7 #include <math.h>
8
9 #include <cstdlib>
10
11 #include "base/bind.h"
12 #include "base/logging.h"
13 #include "base/message_loop/message_loop.h"
14 #include "examples/ui/noodles/frame.h"
15 #include "examples/ui/noodles/rasterizer.h"
16 #include "third_party/skia/include/core/SkCanvas.h"
17 #include "third_party/skia/include/core/SkColor.h"
18 #include "third_party/skia/include/core/SkPath.h"
19 #include "third_party/skia/include/core/SkPicture.h"
20 #include "third_party/skia/include/core/SkPictureRecorder.h"
21
22 namespace examples {
23
24 namespace {
25 constexpr double kSecondsBetweenChanges = 10.0;
26
27 template <typename T>
28 void Drop(scoped_ptr<T> ptr) {}
29
30 scoped_ptr<base::MessagePump> CreateMessagePumpMojo() {
31 return base::MessageLoop::CreateMessagePumpForType(
32 base::MessageLoop::TYPE_DEFAULT);
33 }
34
35 void Lissajous(SkPath* path, double ax, double ay, int wx, int wy, double p) {
36 uint32_t segments = ceil(fabs(ax) + fabs(ay)) / 2u + 1u;
37 for (uint32_t i = 0; i < segments; ++i) {
38 double t = M_PI * 2.0 * i / segments;
39 double x = ax * sin(t * wx);
40 double y = ay * sin(t * wy + p);
41 if (i == 0u)
42 path->moveTo(x, y);
43 else
44 path->lineTo(x, y);
45 }
46 path->close();
47 }
48 } // namespace
49
50 NoodlesView::NoodlesView(
51 mojo::ApplicationImpl* app_impl,
52 const mojo::ui::ViewProvider::CreateViewCallback& create_view_callback)
53 : BaseView(app_impl, "Noodles", create_view_callback),
54 choreographer_(scene(), this),
55 frame_queue_(std::make_shared<FrameQueue>()),
56 rasterizer_delegate_(
57 make_scoped_ptr(new RasterizerDelegate(frame_queue_))) {
58 base::Thread::Options options;
59 options.message_pump_factory = base::Bind(&CreateMessagePumpMojo);
60
61 rasterizer_thread_.reset(new base::Thread("noodles_rasterizer"));
62 rasterizer_thread_->StartWithOptions(options);
63 rasterizer_task_runner_ = rasterizer_thread_->message_loop()->task_runner();
64
65 rasterizer_task_runner_->PostTask(
66 FROM_HERE,
67 base::Bind(&RasterizerDelegate::CreateRasterizer,
68 base::Unretained(rasterizer_delegate_.get()),
69 base::Passed(app_impl->CreateApplicationConnector()),
70 base::Passed(TakeScene().PassInterface())));
71 }
72
73 NoodlesView::~NoodlesView() {
74 // Ensure destruction happens on the correct thread.
75 rasterizer_task_runner_->PostTask(
76 FROM_HERE, base::Bind(&Drop<RasterizerDelegate>,
77 base::Passed(&rasterizer_delegate_)));
78 }
79
80 void NoodlesView::OnLayout(mojo::ui::ViewLayoutParamsPtr layout_params,
81 mojo::Array<uint32_t> children_needing_layout,
82 const OnLayoutCallback& callback) {
83 size_.width = layout_params->constraints->max_width;
84 size_.height = layout_params->constraints->max_height;
85
86 // Submit the new layout information.
87 auto info = mojo::ui::ViewLayoutResult::New();
88 info->size = size_.Clone();
89 callback.Run(info.Pass());
90
91 choreographer_.ScheduleDraw();
92 }
93
94 void NoodlesView::OnDraw(const mojo::gfx::composition::FrameInfo& frame_info,
95 const base::TimeDelta& time_delta) {
96 choreographer_.ScheduleDraw();
97
98 // Update the animation.
99 alpha_ += time_delta.InSecondsF();
100
101 // Create and post a new frame to the renderer.
102 auto metadata = mojo::gfx::composition::SceneMetadata::New();
103 metadata->presentation_time = frame_info.presentation_time;
104 std::unique_ptr<Frame> frame(
105 new Frame(size_, CreatePicture(), metadata.Pass()));
106 if (frame_queue_->PutFrame(std::move(frame))) {
107 rasterizer_task_runner_->PostTask(
108 FROM_HERE, base::Bind(&RasterizerDelegate::PublishNextFrame,
109 base::Unretained(rasterizer_delegate_.get())));
110 }
111 }
112
113 skia::RefPtr<SkPicture> NoodlesView::CreatePicture() {
114 constexpr int count = 4;
115 constexpr int padding = 1;
116
117 if (alpha_ > kSecondsBetweenChanges) {
118 alpha_ = 0.0;
119 wx_ = rand() % 9 + 1;
120 wy_ = rand() % 9 + 1;
121 }
122
123 SkPictureRecorder recorder;
124 SkCanvas* canvas = recorder.beginRecording(size_.width, size_.height);
125
126 double cx = size_.width * 0.5;
127 double cy = size_.height * 0.5;
128 canvas->translate(cx, cy);
129
130 double phase = alpha_;
131 for (int i = 0; i < count; i++, phase += 0.1) {
132 SkPaint paint;
133 SkScalar hsv[3] = {fmod(phase * 120, 360), 1, 1};
134 paint.setColor(SkHSVToColor(hsv));
135 paint.setStyle(SkPaint::kStroke_Style);
136 paint.setAntiAlias(true);
137
138 SkPath path;
139 Lissajous(&path, cx - padding, cy - padding, wx_, wy_, phase);
140 canvas->drawPath(path, paint);
141 }
142
143 return skia::AdoptRef(recorder.endRecordingAsPicture());
144 }
145
146 NoodlesView::FrameQueue::FrameQueue() {}
147
148 NoodlesView::FrameQueue::~FrameQueue() {}
149
150 bool NoodlesView::FrameQueue::PutFrame(std::unique_ptr<Frame> frame) {
151 std::lock_guard<std::mutex> lock(mutex_);
152 bool was_empty = !next_frame_.get();
153 next_frame_.swap(frame);
154 return was_empty;
155 }
156
157 std::unique_ptr<Frame> NoodlesView::FrameQueue::TakeFrame() {
158 std::lock_guard<std::mutex> lock(mutex_);
159 return std::move(next_frame_);
160 }
161
162 NoodlesView::RasterizerDelegate::RasterizerDelegate(
163 const std::shared_ptr<FrameQueue>& frame_queue)
164 : frame_queue_(frame_queue) {
165 DCHECK(frame_queue_);
166 }
167
168 NoodlesView::RasterizerDelegate::~RasterizerDelegate() {}
169
170 void NoodlesView::RasterizerDelegate::CreateRasterizer(
171 mojo::InterfacePtrInfo<mojo::ApplicationConnector> connector_info,
172 mojo::InterfacePtrInfo<mojo::gfx::composition::Scene> scene_info) {
173 rasterizer_.reset(
174 new Rasterizer(mojo::MakeProxy(connector_info.Pass()).Pass(),
175 mojo::MakeProxy(scene_info.Pass()).Pass()));
176 }
177
178 void NoodlesView::RasterizerDelegate::PublishNextFrame() {
179 std::unique_ptr<Frame> frame(frame_queue_->TakeFrame());
180 DCHECK(frame);
181 rasterizer_->PublishFrame(std::move(frame));
182 }
183
184 } // namespace examples
OLDNEW
« no previous file with comments | « examples/ui/noodles/noodles_view.h ('k') | examples/ui/noodles/rasterizer.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698