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

Side by Side Diff: experimental/flocking_geese/nacl_app/flocking_geese_app.cc

Issue 10928195: First round of dead file removal (Closed) Base URL: https://github.com/samclegg/nativeclient-sdk.git@master
Patch Set: Created 8 years, 3 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
(Empty)
1 // Copyright (c) 2011 The Native Client 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 "flocking_geese_app.h"
6
7 #include <algorithm>
8 #include <sstream>
9 #include <string>
10 #include "nacl_app/scoped_pixel_lock.h"
11 #include "ppapi/c/pp_errors.h"
12 #include "ppapi/cpp/completion_callback.h"
13 #include "ppapi/cpp/module.h"
14 #include "threading/scoped_mutex_lock.h"
15 #include "url_io/url_request.h"
16 #include "url_io/web_resource_loader.h"
17
18 namespace {
19 // Input method and parameter Ids. These correspond to C++ calls.
20 const char* const kResetFlockMethodId = "resetFlock";
21 const char* const kRunSimulationMethodId = "runSimulation";
22 const char* const kPauseSimulationMethodId = "pauseSimulation";
23 const char* const kSetAttractorLocMethodId = "setAttractorLocation";
24
25 // Output method and parameter Ids. These correspond to methods in the
26 // browser.
27 const char* const kSetSimulationInfoMethodId = "setSimulationInfo";
28 const char* const kFrameRateParamId = "frameRate";
29
30 const int kSimulationTickInterval = 10; // Measured in msec.
31 const uint32_t kBackgroundColor = 0xFFFFFFFF; // Opaque white.
32
33 // Return the value of parameter named |param_name| from |parameters|. If
34 // |param_name| doesn't exist, then return an empty string.
35 std::string GetParameterNamed(
36 const std::string& param_name,
37 const scripting::MethodParameter& parameters) {
38 scripting::MethodParameter::const_iterator i =
39 parameters.find(param_name);
40 if (i == parameters.end()) {
41 return "";
42 }
43 return i->second;
44 }
45
46 // Return the int32_t equivalent of |str|. All the usual C++ rounding rules
47 // apply.
48 int32_t StringAsInt32(const std::string& str) {
49 std::istringstream cvt_stream(str);
50 double double_val;
51 cvt_stream >> double_val;
52 return static_cast<int32_t>(double_val);
53 }
54
55 // Called from the browser when the delay time has elapsed. This routine
56 // runs a simulation update, then reschedules itself to run the next
57 // simulation tick.
58 void SimulationTickCallback(void* data, int32_t result) {
59 flocking_geese::FlockingGeeseApp* geese_app =
60 static_cast<flocking_geese::FlockingGeeseApp*>(data);
61 // Flush the graphics so far and post the current frame rate.
62 geese_app->PostSimulationInfo();
63 geese_app->Update();
64 if (geese_app->is_running()) {
65 pp::Module::Get()->core()->CallOnMainThread(
66 kSimulationTickInterval,
67 pp::CompletionCallback(&SimulationTickCallback, data),
68 PP_OK);
69 }
70 }
71
72 // Called from the browser when the 2D graphics have been flushed out to the
73 // device.
74 void FlushCallback(void* data, int32_t result) {
75 static_cast<flocking_geese::FlockingGeeseApp*>(data)->
76 set_flush_pending(false);
77 }
78 } // namespace
79
80 using scripting::ScriptingBridge;
81
82 namespace flocking_geese {
83
84 FlockingGeeseApp::FlockingGeeseApp(PP_Instance instance)
85 : pp::Instance(instance),
86 graphics_2d_context_(NULL),
87 flush_pending_(false),
88 view_changed_size_(true) {
89 }
90
91 FlockingGeeseApp::~FlockingGeeseApp() {
92 flock_simulation_.set_is_simulation_running(false);
93 DestroyContext();
94 }
95
96 bool FlockingGeeseApp::Init(uint32_t /* argc */,
97 const char* /* argn */[],
98 const char* /* argv */[]) {
99 // Add all the methods to the scripting bridge.
100 ScriptingBridge::SharedMethodCallbackExecutor
101 reset_flock_method(new scripting::MethodCallback<FlockingGeeseApp>(
102 this, &FlockingGeeseApp::ResetFlock));
103 scripting_bridge_.AddMethodNamed(kResetFlockMethodId, reset_flock_method);
104
105 ScriptingBridge::SharedMethodCallbackExecutor
106 run_sim_method(new scripting::MethodCallback<FlockingGeeseApp>(
107 this, &FlockingGeeseApp::RunSimulation));
108 scripting_bridge_.AddMethodNamed(kRunSimulationMethodId, run_sim_method);
109
110 ScriptingBridge::SharedMethodCallbackExecutor
111 pause_sim_method(new scripting::MethodCallback<FlockingGeeseApp>(
112 this, &FlockingGeeseApp::PauseSimulation));
113 scripting_bridge_.AddMethodNamed(kPauseSimulationMethodId, pause_sim_method);
114
115 ScriptingBridge::SharedMethodCallbackExecutor
116 set_attractor_method(new scripting::MethodCallback<FlockingGeeseApp>(
117 this, &FlockingGeeseApp::SetAttractorLocation));
118 scripting_bridge_.AddMethodNamed(kSetAttractorLocMethodId,
119 set_attractor_method);
120
121 // Load the goose sprite. |sprite_loader| is deleted by its delegate when
122 // the download is complete (or gets an error). The PNG data is checked for
123 // validity at each Update(); when the PNG data has all arrived, the sprite
124 // can be used for drawing.
125 url_io::WebResourceLoader* sprite_loader =
126 new url_io::WebResourceLoader(this, &png_loader_);
127 url_io::URLRequest request("images/Flock32_Green.png");
128 sprite_loader->LoadURL(request);
129
130 flock_simulation_.StartSimulation();
131 return true;
132 }
133
134 void FlockingGeeseApp::DidChangeView(const pp::Rect& position,
135 const pp::Rect& /* clip */) {
136 if (position.size().width() == width() &&
137 position.size().height() == height())
138 return; // Size didn't change, no need to update anything.
139 // Indicate that all the buffers need to be resized at the next Update()
140 // call.
141 view_changed_size_ = true;
142 view_size_ = position.size();
143 // Make sure the buffers get changed if the simulation isn't running.
144 if (!is_running())
145 Update();
146 }
147
148 void FlockingGeeseApp::HandleMessage(const pp::Var& var_message) {
149 if (!var_message.is_string())
150 return;
151 scripting_bridge_.InvokeMethod(var_message.AsString());
152 }
153
154 void FlockingGeeseApp::ResetFlock(
155 const scripting::ScriptingBridge& bridge,
156 const scripting::MethodParameter& parameters) {
157 std::string flock_size_str = GetParameterNamed("size", parameters);
158 if (flock_size_str.length()) {
159 Flock::SimulationMode sim_mode = flock_simulation_.simulation_mode();
160 flock_simulation_.set_simulation_mode(flocking_geese::Flock::kPaused);
161 size_t flock_size = static_cast<size_t>(StringAsInt32(flock_size_str));
162 Vector2 initialLocation(view_size_.width(), view_size_.height());
163 initialLocation.Scale(0.5);
164 flock_simulation_.ResetFlock(flock_size, initialLocation);
165 flock_simulation_.set_simulation_mode(sim_mode);
166 }
167 }
168
169 void FlockingGeeseApp::RunSimulation(
170 const scripting::ScriptingBridge& bridge,
171 const scripting::MethodParameter& parameters) {
172 flock_simulation_.set_simulation_mode(flocking_geese::Flock::kRunning);
173 // Schedule a simulation tick to get things going.
174 pp::Module::Get()->core()->CallOnMainThread(
175 kSimulationTickInterval,
176 pp::CompletionCallback(&SimulationTickCallback, this),
177 PP_OK);
178 }
179
180 void FlockingGeeseApp::PauseSimulation(
181 const scripting::ScriptingBridge& bridge,
182 const scripting::MethodParameter& parameters) {
183 flock_simulation_.set_simulation_mode(flocking_geese::Flock::kPaused);
184 }
185
186 void FlockingGeeseApp::SetAttractorLocation(
187 const scripting::ScriptingBridge& bridge,
188 const scripting::MethodParameter& parameters) {
189 std::string loc_x_str = GetParameterNamed("x", parameters);
190 std::string loc_y_str = GetParameterNamed("y", parameters);
191 if (loc_x_str.length() && loc_y_str.length()) {
192 Vector2 attractor_loc(StringAsInt32(loc_x_str), StringAsInt32(loc_y_str));
193 flock_simulation_.SetAttractorAtIndex(attractor_loc, 0);
194 }
195 }
196
197 void FlockingGeeseApp::PostSimulationInfo() {
198 double frame_rate = flock_simulation_.FrameRate();
199 std::ostringstream method_invocation(std::ostringstream::out);
200 method_invocation << kSetSimulationInfoMethodId << " ";
201 method_invocation << kFrameRateParamId << ":" << frame_rate;
202 pp::Var var_message(method_invocation.str());
203 PostMessage(var_message);
204 }
205
206 void FlockingGeeseApp::Update() {
207 if (flush_pending())
208 return; // Don't attempt to flush if one is pending.
209
210 // See if the goose sprite is ready to be used.
211 if (png_loader_.is_valid() && !flock_simulation_.has_goose_sprite()) {
212 pp::Size pixel_buffer_size = png_loader_.png_image_size();
213 uint32_t* pixel_buffer =
214 static_cast<uint32_t*>(malloc(pixel_buffer_size.width() *
215 pixel_buffer_size.height() *
216 sizeof(uint32_t)));
217 png_loader_.FillPixelBuffer(pixel_buffer);
218 flock_simulation_.set_goose_sprite(
219 new Sprite(pixel_buffer, png_loader_.png_image_size(), 0));
220 }
221
222 if (view_changed_size_) {
223 // Delete the old pixel buffer and create a new one.
224 // Pause the simulation before changing all the buffer sizes.
225 Flock::SimulationMode sim_mode = flock_simulation_.simulation_mode();
226 flock_simulation_.set_simulation_mode(flocking_geese::Flock::kPaused);
227 // Create a new device context with the new size.
228 // Note: DestroyContext() releases the simulation's copy of the shared
229 // pixel buffer. *This has to happen before the reset() below!* If the
230 // simulation's copy of hte shared pointer is released last, then the
231 // underlying ImageData is released off the main thread, which is not
232 // supported in Pepper.
233 DestroyContext();
234 CreateContext(view_size_);
235 threading::ScopedMutexLock scoped_mutex(
236 flock_simulation_.simulation_mutex());
237 if (!scoped_mutex.is_valid())
238 // This potentially leaves the simulation in a paused state, but getting
239 // here means something is very wrong and the simulation probably can't
240 // run anyways.
241 return;
242 if (graphics_2d_context_ != NULL) {
243 shared_pixel_buffer_.reset(
244 new LockingImageData(this,
245 PP_IMAGEDATAFORMAT_BGRA_PREMUL,
246 graphics_2d_context_->size(),
247 false));
248 set_flush_pending(false);
249 // Ok to get a non-locked version because the simulation is guraranteed
250 // to be paused here.
251 uint32_t* pixels = shared_pixel_buffer_->PixelBufferNoLock();
252 if (pixels) {
253 const size_t size = width() * height();
254 std::fill(pixels, pixels + size, kBackgroundColor);
255 }
256 flock_simulation_.Resize(pp::Size(width(), height()));
257 flock_simulation_.set_pixel_buffer(shared_pixel_buffer_);
258 flock_simulation_.set_simulation_mode(sim_mode);
259 }
260 view_changed_size_ = false;
261 }
262 flock_simulation_.Render();
263 FlushPixelBuffer();
264 }
265
266 void FlockingGeeseApp::CreateContext(const pp::Size& size) {
267 if (IsContextValid())
268 return;
269 graphics_2d_context_ = new pp::Graphics2D(this, size, false);
270 if (!BindGraphics(*graphics_2d_context_)) {
271 PostMessage("Couldn't bind the device context");
272 }
273 }
274
275 void FlockingGeeseApp::DestroyContext() {
276 threading::ScopedMutexLock scoped_mutex(flock_simulation_.simulation_mutex());
277 if (!scoped_mutex.is_valid()) {
278 return;
279 }
280 ScopedPixelLock scoped_pixel_lock(shared_pixel_buffer_);
281 shared_pixel_buffer_.reset();
282 flock_simulation_.set_pixel_buffer(shared_pixel_buffer_);
283 if (!IsContextValid())
284 return;
285 delete graphics_2d_context_;
286 graphics_2d_context_ = NULL;
287 }
288
289 void FlockingGeeseApp::FlushPixelBuffer() {
290 if (!IsContextValid() || shared_pixel_buffer_ == NULL)
291 return;
292 set_flush_pending(true);
293 graphics_2d_context_->PaintImageData(*shared_pixel_buffer_, pp::Point());
294 graphics_2d_context_->Flush(pp::CompletionCallback(&FlushCallback, this));
295 }
296 } // namespace flocking_geese
297
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698