summaryrefslogtreecommitdiffstats
path: root/native_client_sdk
diff options
context:
space:
mode:
authornoelallen@chromium.org <noelallen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-06-24 22:26:13 +0000
committernoelallen@chromium.org <noelallen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-06-24 22:26:13 +0000
commit2ea96e502f6f84cf50495f98be5d5b2ac204dfec (patch)
treea18db4aa051c503a47636bde7b851ef36ffec4ad /native_client_sdk
parente2db10a81a814aa62d616d685b782146d4bb2cd6 (diff)
downloadchromium_src-2ea96e502f6f84cf50495f98be5d5b2ac204dfec.zip
chromium_src-2ea96e502f6f84cf50495f98be5d5b2ac204dfec.tar.gz
chromium_src-2ea96e502f6f84cf50495f98be5d5b2ac204dfec.tar.bz2
Adds a new example to the NaCl SDK.
Adds 2D Context helpers to PPAPI_SIMPLE. Adds Flocking geese demo which uses the context functions. NOTRY=true R=binji@chromium.org BUG=164959 Review URL: https://chromiumcodereview.appspot.com/17009010 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@208276 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'native_client_sdk')
-rw-r--r--native_client_sdk/src/build_tools/sdk_files.list18
-rw-r--r--native_client_sdk/src/examples/demo/flock/example.dsc26
-rw-r--r--native_client_sdk/src/examples/demo/flock/flock.cc150
-rw-r--r--native_client_sdk/src/examples/demo/flock/frame_counter.cc43
-rw-r--r--native_client_sdk/src/examples/demo/flock/frame_counter.h46
-rw-r--r--native_client_sdk/src/examples/demo/flock/goose.cc204
-rw-r--r--native_client_sdk/src/examples/demo/flock/goose.h129
-rw-r--r--native_client_sdk/src/examples/demo/flock/index.html28
-rw-r--r--native_client_sdk/src/examples/demo/flock/sprite.cc91
-rw-r--r--native_client_sdk/src/examples/demo/flock/sprite.h57
-rw-r--r--native_client_sdk/src/examples/demo/flock/vector2.h81
-rw-r--r--native_client_sdk/src/examples/demo/life/index.html2
-rw-r--r--native_client_sdk/src/libraries/ppapi_simple/library.dsc4
-rw-r--r--native_client_sdk/src/libraries/ppapi_simple/ps_context_2d.cc134
-rw-r--r--native_client_sdk/src/libraries/ppapi_simple/ps_context_2d.h67
-rw-r--r--native_client_sdk/src/libraries/ppapi_simple/ps_event.h6
-rw-r--r--native_client_sdk/src/libraries/ppapi_simple/ps_instance.cc32
-rw-r--r--native_client_sdk/src/libraries/ppapi_simple/ps_instance.h24
-rw-r--r--native_client_sdk/src/libraries/ppapi_simple/ps_interface.cc62
-rw-r--r--native_client_sdk/src/libraries/ppapi_simple/ps_interface.h71
20 files changed, 1249 insertions, 26 deletions
diff --git a/native_client_sdk/src/build_tools/sdk_files.list b/native_client_sdk/src/build_tools/sdk_files.list
index 510a432..4e97097 100644
--- a/native_client_sdk/src/build_tools/sdk_files.list
+++ b/native_client_sdk/src/build_tools/sdk_files.list
@@ -114,6 +114,20 @@ examples/demo/drive/Makefile
examples/demo/drive/manifest.json
[win]examples/demo/make.bat
examples/demo/Makefile
+[win]examples/demo/flock/make.bat
+examples/demo/flock/Makefile
+examples/demo/flock/background.js
+examples/demo/flock/common.js
+examples/demo/flock/flock.cc
+examples/demo/flock/goose.cc
+examples/demo/flock/goose.h
+examples/demo/flock/icon128.png
+examples/demo/flock/images/flock_green.raw
+examples/demo/flock/index.html
+examples/demo/flock/manifest.json
+examples/demo/flock/sprite.cc
+examples/demo/flock/sprite.h
+examples/demo/flock/vector2.h
[win]examples/demo/life/make.bat
examples/demo/life/Makefile
examples/demo/life/background.js
@@ -472,8 +486,10 @@ include/ppapi/cpp/websocket.h
include/ppapi/gles2/gl2ext_ppapi.h
include/ppapi/lib/gl/gles2/gl2ext_ppapi.h
include/ppapi_simple/ps.h
+include/ppapi_simple/ps_context_2d.h
include/ppapi_simple/ps_event.h
include/ppapi_simple/ps_instance.h
+include/ppapi_simple/ps_interface.h
include/ppapi_simple/ps_main.h
include/ppapi/utility/completion_callback_factory.h
include/ppapi/utility/completion_callback_factory_thread_traits.h
@@ -767,8 +783,10 @@ src/ppapi_gles2/Makefile
[win]src/ppapi_simple/make.bat
src/ppapi_simple/Makefile
src/ppapi_simple/ps.cc
+src/ppapi_simple/ps_context_2d.cc
src/ppapi_simple/ps_event.cc
src/ppapi_simple/ps_instance.cc
+src/ppapi_simple/ps_interface.cc
src/ppapi_simple/ps_main.cc
src/ppapi_cpp_private/Makefile
[win]src/ppapi_cpp_private/make.bat
diff --git a/native_client_sdk/src/examples/demo/flock/example.dsc b/native_client_sdk/src/examples/demo/flock/example.dsc
new file mode 100644
index 0000000..50fdeeb
--- /dev/null
+++ b/native_client_sdk/src/examples/demo/flock/example.dsc
@@ -0,0 +1,26 @@
+{
+ 'TOOLS': ['newlib', 'glibc', 'pnacl'],
+ 'TARGETS': [
+ {
+ 'NAME' : 'flock',
+ 'TYPE' : 'main',
+ 'SOURCES' : [
+ 'flock.cc',
+ 'goose.cc',
+ 'goose.h',
+ 'sprite.cc',
+ 'sprite.h',
+ 'vector2.h'
+ ],
+ 'DEPS': ['ppapi_simple', 'nacl_io'],
+ 'LIBS': ['ppapi_cpp', 'ppapi', 'pthread']
+ }
+ ],
+ 'DATA': [
+ 'images/flock_green.raw'
+ ],
+ 'DEST': 'examples/demo',
+ 'NAME': 'flock',
+ 'TITLE': 'Flocking Geese',
+ 'GROUP': 'Demo'
+}
diff --git a/native_client_sdk/src/examples/demo/flock/flock.cc b/native_client_sdk/src/examples/demo/flock/flock.cc
new file mode 100644
index 0000000..ac5f490
--- /dev/null
+++ b/native_client_sdk/src/examples/demo/flock/flock.cc
@@ -0,0 +1,150 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <algorithm>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include "nacl_io/nacl_io.h"
+
+#include "ppapi/c/pp_rect.h"
+#include "ppapi/c/pp_size.h"
+
+#include "ppapi_simple/ps_context_2d.h"
+#include "ppapi_simple/ps_main.h"
+
+#include "goose.h"
+#include "sprite.h"
+#include "vector2.h"
+
+
+namespace {
+ // The goose sprites rotate in increments of 5 degrees.
+const double kGooseHeadingIncrement = (5.0 * M_PI) / 180.0;
+} // namespace
+
+struct ImageFormat {
+ int width;
+ int height;
+ int channels;
+};
+
+Sprite* g_goose_sprite;
+std::vector<Goose> g_geese;
+std::vector<Vector2> g_attractors;
+
+
+void ResetFlock(PSContext2D_t* ctx, size_t count) {
+ Vector2 center(0.5 * ctx->width, 0.5 * ctx->height);
+
+ g_geese.resize(count);
+ for (size_t i = 0; i < count; i++) {
+ double dx = (double) rand() / (double) RAND_MAX;
+ double dy = (double) rand() / (double) RAND_MAX;
+ g_geese[i] = Goose(center, Vector2(dx, dy));
+ }
+}
+
+void Render(PSContext2D_t* ctx) {
+ PSContext2DGetBuffer(ctx);
+ const size_t num_geese = g_geese.size();
+
+ if (NULL == g_goose_sprite) return;
+ if (NULL == ctx->data) return;
+
+ // Clear to WHITE
+ memset(ctx->data, 0xFF, ctx->stride * ctx->height);
+
+ int32_t sprite_side_length = g_goose_sprite->size().height();
+ pp::Rect sprite_src_rect(0, 0, sprite_side_length, sprite_side_length);
+ pp::Rect canvas_bounds(pp::Size(ctx->width, ctx->height));
+
+
+ // Run the simulation for each goose.
+ for (size_t i = 0; i < num_geese; i++) {
+ Goose& goose = g_geese[i];
+
+ // Update position and orientation
+ goose.SimulationTick(g_geese, g_attractors, canvas_bounds);
+ pp::Point dest_point(goose.location().x() - sprite_side_length / 2,
+ goose.location().y() - sprite_side_length / 2);
+
+ // Compute image to use
+ double heading = goose.velocity().Heading();
+ if (heading < 0.0)
+ heading = M_PI * 2.0 + heading;
+
+ int32_t sprite_index =
+ static_cast<int32_t>(heading / kGooseHeadingIncrement);
+
+ sprite_src_rect.set_x(sprite_index * sprite_side_length);
+ g_goose_sprite->CompositeFromRectToPoint(
+ sprite_src_rect,
+ ctx->data, canvas_bounds, 0,
+ dest_point);
+ }
+
+ PSContext2DSwapBuffer(ctx);
+}
+
+/*
+ * Starting point for the module. We do not use main since it would
+ * collide with main in libppapi_cpp.
+ */
+int example_main(int argc, char *argv[]) {
+ ImageFormat fmt;
+ uint32_t* buffer;
+ size_t len;
+
+ PSEventSetFilter(PSE_ALL);
+
+ // Mount the images directory as an HTTP resources
+ mount("/images", "/images", "httpfs", 0, "");
+
+ FILE* fp = fopen("/images/flock_green.raw", "rb");
+ fread(&fmt, sizeof(fmt), 1, fp);
+
+ len = fmt.width * fmt.height * fmt.channels;
+ buffer = new uint32_t[len];
+ fread(buffer, 1, len, fp);
+ fclose(fp);
+
+ g_goose_sprite = new Sprite(buffer, pp::Size(fmt.width, fmt.height), 0);
+
+ PSContext2D_t* ctx = PSContext2DAllocate();
+ ResetFlock(ctx, 50);
+ while (1) {
+ PSEvent* event;
+
+ // Consume all available events
+ while ((event = PSEventTryAcquire()) != NULL) {
+ PSContext2DHandleEvent(ctx, event);
+ PSEventRelease(event);
+ }
+
+ if (ctx->bound) {
+ Render(ctx);
+ } else {
+ // If not bound, wait for an event which may signal a context becoming
+ // available, instead of spinning.
+ event = PSEventWaitAcquire();
+ if (PSContext2DHandleEvent(ctx, event))
+ ResetFlock(ctx, 50);
+ PSEventRelease(event);
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * Register the function to call once the Instance Object is initialized.
+ * see: pappi_simple/ps_main.h
+ */
+PPAPI_SIMPLE_REGISTER_MAIN(example_main);
diff --git a/native_client_sdk/src/examples/demo/flock/frame_counter.cc b/native_client_sdk/src/examples/demo/flock/frame_counter.cc
new file mode 100644
index 0000000..e9e4c54
--- /dev/null
+++ b/native_client_sdk/src/examples/demo/flock/frame_counter.cc
@@ -0,0 +1,43 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <time.h>
+#include <limits>
+
+#include "nacl_app/flock.h"
+
+void FrameCounter::BeginFrame() {
+ struct timeval start_time;
+ gettimeofday(&start_time, NULL);
+ frame_start_ = start_time.tv_sec * kMicroSecondsPerSecond +
+ start_time.tv_usec;
+}
+
+void FrameCounter::EndFrame() {
+ struct timeval end_time;
+ gettimeofday(&end_time, NULL);
+ double frame_end = end_time.tv_sec * kMicroSecondsPerSecond +
+ end_time.tv_usec;
+ double dt = frame_end - frame_start_;
+ if (dt < 0)
+ return;
+ frame_duration_accumulator_ += dt;
+ frame_count_++;
+ if (frame_count_ > kFrameRateRefreshCount ||
+ frame_duration_accumulator_ >= kMicroSecondsPerSecond) {
+ double elapsed_time = frame_duration_accumulator_ /
+ kMicroSecondsPerSecond;
+ if (fabs(elapsed_time) > std::numeric_limits<double>::epsilon()) {
+ frames_per_second_ = frame_count_ / elapsed_time;
+ }
+ frame_duration_accumulator_ = 0;
+ frame_count_ = 0;
+ }
+}
+
+void FrameCounter::Reset() {
+ frames_per_second_ = 0;
+ frame_duration_accumulator_ = 0;
+ frame_count_ = 0;
+}
diff --git a/native_client_sdk/src/examples/demo/flock/frame_counter.h b/native_client_sdk/src/examples/demo/flock/frame_counter.h
new file mode 100644
index 0000000..26a1b66
--- /dev/null
+++ b/native_client_sdk/src/examples/demo/flock/frame_counter.h
@@ -0,0 +1,46 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef FRAME_COUNTER_H_
+#define FRAME_COUNTER_H_
+
+class FrameCounter {
+ public:
+ FrameCounter()
+ : frame_duration_accumulator_(0),
+ frame_count_(0),
+ frames_per_second_(0) {}
+ ~FrameCounter() {}
+
+ // Record the current time, which is used to compute the frame duration
+ // when EndFrame() is called.
+ void BeginFrame();
+
+ // Compute the delta since the last call to BeginFrame() and increment the
+ // frame count. Update the frame rate whenever the prescribed number of
+ // frames have been counted, or at least one second of simulator time has
+ // passed, whichever is less.
+ void EndFrame();
+
+ // Reset the frame counters back to 0.
+ void Reset();
+
+ // The current frame rate. Note that this is 0 for the first second in
+ // the accumulator, and is updated every 100 frames (and at least once
+ // every second of simulation time or so).
+ double frames_per_second() const {
+ return frames_per_second_;
+ }
+
+ private:
+ static const double kMicroSecondsPerSecond = 1000000.0;
+ static const int32_t kFrameRateRefreshCount = 100;
+
+ double frame_duration_accumulator_; // Measured in microseconds.
+ int32_t frame_count_;
+ double frame_start_;
+ double frames_per_second_;
+};
+
+#endif // FRAME_COUNTER_H_
diff --git a/native_client_sdk/src/examples/demo/flock/goose.cc b/native_client_sdk/src/examples/demo/flock/goose.cc
new file mode 100644
index 0000000..f706134
--- /dev/null
+++ b/native_client_sdk/src/examples/demo/flock/goose.cc
@@ -0,0 +1,204 @@
+ // Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "goose.h"
+
+namespace {
+// The maximum speed of a goose. Measured in meters/second.
+const double kMaxSpeed = 2.0;
+
+// The maximum force that can be applied to turn a goose when computing the
+// aligment. Measured in meters/second/second.
+const double kMaxTurningForce = 0.05;
+
+// The neighbour radius of a goose. Only geese within this radius will affect
+// the flocking computations of this goose. Measured in pixels.
+const double kNeighbourRadius = 64.0;
+
+// The minimum distance that a goose can be from this goose. If another goose
+// comes within this distance of this goose, the flocking algorithm tries to
+// move the geese apart. Measured in pixels.
+const double kPersonalSpace = 32.0;
+
+// The distance at which attractors have effect on a goose's direction.
+const double kAttractorRadius = 320.0;
+
+// The goose will try to turn towards geese within this distance (computed
+// during the cohesion phase). Measured in pixels.
+const double kMaxTurningDistance = 100.0;
+
+// The weights used when computing the weighted sum the three flocking
+// components.
+const double kSeparationWeight = 2.0;
+const double kAlignmentWeight = 1.0;
+const double kCohesionWeight = 1.0;
+
+} // namespace
+
+
+Goose::Goose() : location_(0, 0), velocity_(0, 0) {
+}
+
+Goose::Goose(const Vector2& location, const Vector2& velocity)
+ : location_(location),
+ velocity_(velocity) {
+}
+
+void Goose::SimulationTick(const std::vector<Goose>& geese,
+ const std::vector<Vector2>& attractors,
+ const pp::Rect& flock_box) {
+
+ Vector2 acceleration = DesiredVector(geese, attractors);
+ velocity_.Add(acceleration);
+
+ // Limit the velocity to a maximum speed.
+ velocity_.Clamp(kMaxSpeed);
+
+ location_.Add(velocity_);
+
+ // Wrap the goose location to the flock box.
+ if (!flock_box.IsEmpty()) {
+ while (location_.x() < flock_box.x())
+ location_.set_x(location_.x() + flock_box.width());
+
+ while (location_.x() >= flock_box.right())
+ location_.set_x(location_.x() - flock_box.width());
+
+ while (location_.y() < flock_box.y())
+ location_.set_y(location_.y() + flock_box.height());
+
+ while (location_.y() >= flock_box.bottom())
+ location_.set_y(location_.y() - flock_box.height());
+ }
+}
+
+Vector2 Goose::DesiredVector(const std::vector<Goose>& geese,
+ const std::vector<Vector2>& attractors) {
+ // Loop over all the neighbouring geese in the flock, accumulating
+ // the separation mean, the alignment mean and the cohesion mean.
+ int32_t separation_count = 0;
+ Vector2 separation;
+ int32_t align_count = 0;
+ Vector2 alignment;
+ int32_t cohesion_count = 0;
+ Vector2 cohesion;
+
+ for (std::vector<Goose>::const_iterator goose_it = geese.begin();
+ goose_it < geese.end();
+ ++goose_it) {
+ const Goose& goose = *goose_it;
+
+ // Compute the distance from this goose to its neighbour.
+ Vector2 goose_delta = Vector2::Difference(
+ location_, goose.location());
+ double distance = goose_delta.Magnitude();
+
+ separation_count = AccumulateSeparation(
+ distance, goose_delta, &separation, separation_count);
+
+ align_count = AccumulateAlignment(
+ distance, goose, &alignment, align_count);
+ cohesion_count = AccumulateCohesion(
+ distance, goose, &cohesion, cohesion_count);
+ }
+
+ // Compute the means and create a weighted sum. This becomes the goose's new
+ // acceleration.
+ if (separation_count > 0) {
+ separation.Scale(1.0 / static_cast<double>(separation_count));
+ }
+ if (align_count > 0) {
+ alignment.Scale(1.0 / static_cast<double>(align_count));
+ // Limit the effect that alignment has on the final acceleration. The
+ // alignment component can overpower the others if there is a big
+ // difference between this goose's velocity and its neighbours'.
+ alignment.Clamp(kMaxTurningForce);
+ }
+
+ // Compute the effect of the attractors and blend this in with the flock
+ // cohesion component. An attractor has to be within kAttractorRadius to
+ // effect the heading of a goose.
+ for (size_t i = 0; i < attractors.size(); ++i) {
+ Vector2 attractor_direction = Vector2::Difference(
+ attractors[i], location_);
+ double distance = attractor_direction.Magnitude();
+ if (distance < kAttractorRadius) {
+ attractor_direction.Scale(1000); // Each attractor acts like 1000 geese.
+ cohesion.Add(attractor_direction);
+ cohesion_count++;
+ }
+ }
+
+ // If there is a non-0 cohesion component, steer the goose so that it tries
+ // to follow the flock.
+ if (cohesion_count > 0) {
+ cohesion.Scale(1.0 / static_cast<double>(cohesion_count));
+ cohesion = TurnTowardsTarget(cohesion);
+ }
+ // Compute the weighted sum.
+ separation.Scale(kSeparationWeight);
+ alignment.Scale(kAlignmentWeight);
+ cohesion.Scale(kCohesionWeight);
+ Vector2 weighted_sum = cohesion;
+ weighted_sum.Add(alignment);
+ weighted_sum.Add(separation);
+ return weighted_sum;
+}
+
+Vector2 Goose::TurnTowardsTarget(const Vector2& target) {
+ Vector2 desired_direction = Vector2::Difference(target, location_);
+ double distance = desired_direction.Magnitude();
+ Vector2 new_direction;
+ if (distance > 0.0) {
+ desired_direction.Normalize();
+ // If the target is within the turning affinity distance, then make the
+ // desired direction based on distance to the target. Otherwise, base
+ // the desired direction on MAX_SPEED.
+ if (distance < kMaxTurningDistance) {
+ // Some pretty arbitrary dampening.
+ desired_direction.Scale(kMaxSpeed * distance / 100.0);
+ } else {
+ desired_direction.Scale(kMaxSpeed);
+ }
+ new_direction = Vector2::Difference(desired_direction, velocity_);
+ new_direction.Clamp(kMaxTurningForce);
+ }
+ return new_direction;
+}
+
+int32_t Goose::AccumulateSeparation(double distance,
+ const Vector2& goose_delta,
+ Vector2* separation, /* inout */
+ int32_t separation_count) {
+ if (distance > 0.0 && distance < kPersonalSpace) {
+ Vector2 weighted_direction = goose_delta;
+ weighted_direction.Normalize();
+ weighted_direction.Scale(1.0 / distance);
+ separation->Add(weighted_direction);
+ separation_count++;
+ }
+ return separation_count;
+}
+
+int32_t Goose::AccumulateAlignment(double distance,
+ const Goose& goose,
+ Vector2* alignment, /* inout */
+ int32_t align_count) {
+ if (distance > 0.0 && distance < kNeighbourRadius) {
+ alignment->Add(goose.velocity());
+ align_count++;
+ }
+ return align_count;
+}
+
+int32_t Goose::AccumulateCohesion(double distance,
+ const Goose& goose,
+ Vector2* cohesion, /* inout */
+ int32_t cohesion_count) {
+ if (distance > 0.0 && distance < kNeighbourRadius) {
+ cohesion->Add(goose.location());
+ cohesion_count++;
+ }
+ return cohesion_count;
+}
diff --git a/native_client_sdk/src/examples/demo/flock/goose.h b/native_client_sdk/src/examples/demo/flock/goose.h
new file mode 100644
index 0000000..2bd5be0
--- /dev/null
+++ b/native_client_sdk/src/examples/demo/flock/goose.h
@@ -0,0 +1,129 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef GOOSE_H_
+#define GOOSE_H_
+
+#include <vector>
+#include "ppapi/cpp/rect.h"
+
+#include "vector2.h"
+
+// A Goose. Each goose has a location and a velocity. Implements the
+// flocking algortihm described here:
+// http://processingjs.org/learning/topic/flocking with references to
+// http://harry.me/2011/02/17/neat-algorithms---flocking.
+class Goose {
+ public:
+ // Initialize a Goose at location (0, 0) no velocity.
+ Goose();
+
+ // Initialize a Goose at the given location with the specified velocity.
+ Goose(const Vector2& location, const Vector2& velocity);
+
+ // Run one tick of the simulation. Compute a new acceleration based on the
+ // flocking algorithm (see Goose.flock()) and update the goose's location
+ // by integrating acceleration and velocity.
+ // @param geese The list of all the geese in the flock.
+ // @param attractors The list of attractors. Geese have affinity for these
+ // points.
+ // @param flockBox The geese will stay inside of this box. If the flock_box
+ // is empty, the geese don't have boundaries.
+ void SimulationTick(const std::vector<Goose>& geese,
+ const std::vector<Vector2>& attractors,
+ const pp::Rect& flock_box);
+
+ // Implement the flocking algorithm in five steps:
+ // 1. Compute the separation component,
+ // 2. Compute the alignment component,
+ // 3. Compute the cohesion component.
+ // 4. Compute the effect of the attractors and blend this in with the
+ // cohesion component.
+ // 5. Create a weighted sum of the three components and use this as the
+ // new acceleration for the goose.
+ // This is an O(n^2) version of the algorithm. There are ways to speed this
+ // up using spatial coherence techniques, but this version is much simpler.
+ // @param geese The list of all the neighbouring geese (in this
+ // implementation, this is all the geese in the flock).
+ // @param attractors The list of attractors. Geese have affinity for these
+ // points.
+ // @return The acceleration vector for this goose based on the flocking
+ // algorithm.
+ Vector2 DesiredVector(const std::vector<Goose>& geese,
+ const std::vector<Vector2>& attractors);
+
+ // Turn the goose towards a target. The amount of turning force is clamped
+ // to |kMaxTurningForce|.
+ // @param target Turn the goose towards this target.
+ // @return A vector representing the new direction of the goose.
+ Vector2 TurnTowardsTarget(const Vector2& target);
+
+ // Accessors for location and velocoity.
+ Vector2 location() const {
+ return location_;
+ }
+ Vector2 velocity() const {
+ return velocity_;
+ }
+
+ private:
+ // Add a neighbouring goose's contribution to the separation mean. Only
+ // consider geese that have moved inside of this goose's personal space.
+ // Modifies the separation accumulator |separation| in-place.
+ // @param distance The distance from this goose to the neighbouring goose.
+ // @param gooseDirection The direction vector from this goose to the
+ // neighbour.
+ // @param separation The accumulated separation from all the neighbouring
+ // geese.
+ // @param separationCount The current number of geese that have contributed to
+ // the separation component so far.
+ // @return The new count of geese that contribute to the separation component.
+ // If the goose under consideration does not contribute, this value is the
+ // same as |separationCount|.
+ int32_t AccumulateSeparation(double distance,
+ const Vector2& goose_direction,
+ Vector2* separation, /* inout */
+ int32_t separation_count);
+
+ // Add a neighbouring goose's contribution to the alignment mean. Alignment
+ // is the average velocity of the neighbours. Only consider geese that are
+ // within |kNeighbourRadius|. Modifies the alignment accumulator |alignment|
+ // in-place.
+ // @param distance The distance from this goose to the neighbouring goose.
+ // @param goose The neighbouring goose under consideration.
+ // @param alignment The accumulated alignment from all the neighbouring geese.
+ // @param alignCount The current number of geese that have contributed to the
+ // alignment component so far.
+ // @return The new count of geese that contribute to the alignment component.
+ // If the goose under consideration does not contribute, this value is the
+ // same as |alignCount|.
+ int32_t AccumulateAlignment(double distance,
+ const Goose& goose,
+ Vector2* alignment, /* inout */
+ int32_t align_count);
+
+ // Add a neighbouring goose's contribution to the cohesion mean. Cohesion is
+ // based on the average location of the neighbours. The goose attempts to
+ // point to this average location. Only consider geese that are within
+ // |kNeighbourRadius|. Modifies the cohesion accumulator |cohesion| in-place.
+ // @param {!number} distance The distance from this goose to the neighbouring
+ // goose.
+ // @param {!Goose} goose The neighbouring goose under consideration.
+ // @param {!goog.math.Vec2} cohesion The accumulated cohesion from all the
+ // neighbouring geese.
+ // @param {!number} cohesionCount The current number of geese that have
+ // contributed to the cohesion component so far.
+ // @return {!number} The new count of geese that contribute to the cohesion
+ // component. If the goose under consideration does not contribute, this
+ // value is the same as |cohesionCount|.
+ int32_t AccumulateCohesion(double distance,
+ const Goose& goose,
+ Vector2* cohesion, /* inout */
+ int32_t cohesion_count);
+
+ Vector2 location_;
+ Vector2 velocity_;
+};
+
+#endif // GOOSE_H_
diff --git a/native_client_sdk/src/examples/demo/flock/index.html b/native_client_sdk/src/examples/demo/flock/index.html
new file mode 100644
index 0000000..f17faf1
--- /dev/null
+++ b/native_client_sdk/src/examples/demo/flock/index.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+<!--
+Copyright 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<head>
+ <meta http-equiv="Pragma" content="no-cache">
+ <meta http-equiv="Expires" content="-1">
+ <title>{{title}}</title>
+ <script type="text/javascript" src="common.js"></script>
+ <script type="text/javascript" src="example.js"></script>
+</head>
+<body data-width="800" data-height="800" {{attrs}}>
+ <h1>{{title}}</h1>
+ <h2>Status: <code id="statusField">NO-STATUS</code></h2>
+ <p> Simulates the swarming and avoiding flight behavior of a flock of
+ geese. This demo using the ppapi_simple library to automatically handle
+ creation and maintainence of the 2D graphics context, providing a pointer
+ and stride for a 32 bit (RGBA/ARGB) area in which the example draws
+ every frame.
+ </p>
+ <!-- The NaCl plugin will be embedded inside the element with id "listener".
+ See common.js.-->
+ <div id="listener"></div>
+</body>
+</html>
diff --git a/native_client_sdk/src/examples/demo/flock/sprite.cc b/native_client_sdk/src/examples/demo/flock/sprite.cc
new file mode 100644
index 0000000..553fc55
--- /dev/null
+++ b/native_client_sdk/src/examples/demo/flock/sprite.cc
@@ -0,0 +1,91 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <algorithm>
+
+#include "sprite.h"
+
+namespace {
+
+inline uint32_t Blend(uint32_t src1, uint32_t src2) {
+ // Divide both sources by 2, then add them together using a mask
+ // to avoid overflow.
+ src1 = (src1 >> 1) & 0x7F7F7F7F;
+ src2 = (src2 >> 1) & 0x7F7F7F7F;
+ return src1 + src2;
+}
+
+} // namespace
+
+
+Sprite::Sprite(uint32_t* pixel_buffer,
+ const pp::Size& size,
+ int32_t row_bytes) {
+ SetPixelBuffer(pixel_buffer, size, row_bytes);
+}
+
+Sprite::~Sprite() {
+ delete[] pixel_buffer_;
+}
+
+void Sprite::SetPixelBuffer(uint32_t* pixel_buffer,
+ const pp::Size& size,
+ int32_t row_bytes) {
+ pixel_buffer_ = pixel_buffer;
+ pixel_buffer_size_ = size;
+ row_bytes_ = row_bytes ? row_bytes : size.width() * sizeof(uint32_t);
+}
+
+void Sprite::CompositeFromRectToPoint(const pp::Rect& src_rect,
+ uint32_t* dest_pixel_buffer,
+ const pp::Rect& dest_bounds,
+ int32_t dest_row_bytes,
+ const pp::Point& dest_point) const {
+ // Clip the source rect to the source image bounds.
+ pp::Rect src_bounds(pp::Point(), size());
+ pp::Rect src_rect_clipped(src_rect.Intersect(src_bounds));
+ if (src_rect_clipped.IsEmpty())
+ return;
+
+ // Create a clipped rect in the destination coordinate space that contains the
+ // final image.
+ pp::Rect draw_rect(dest_point, src_rect_clipped.size());
+ pp::Rect draw_rect_clipped(dest_bounds.Intersect(draw_rect));
+ if (draw_rect_clipped.IsEmpty())
+ return;
+ // Transform the dest rect to the source image coordinate system.
+ pp::Point src_offset(draw_rect_clipped.point());
+ src_offset -= dest_point;
+ src_rect_clipped.Offset(src_offset);
+ src_rect_clipped.set_size(draw_rect_clipped.size());
+ size_t src_byte_offset = src_rect_clipped.x() * sizeof(uint32_t) +
+ src_rect_clipped.y() * row_bytes_;
+ const uint8_t* src_pixels =
+ reinterpret_cast<const uint8_t*>(pixel_buffer_) + src_byte_offset;
+
+ if (dest_row_bytes == 0)
+ dest_row_bytes = dest_bounds.width() * sizeof(uint32_t);
+ size_t dest_byte_offset = draw_rect_clipped.point().x() * sizeof(uint32_t) +
+ draw_rect_clipped.point().y() * dest_row_bytes;
+ uint8_t* dest_pixels = reinterpret_cast<uint8_t*>(dest_pixel_buffer) +
+ dest_byte_offset;
+
+ for (int32_t y = 0; y < src_rect_clipped.height(); ++y) {
+ const uint32_t* src_scanline =
+ reinterpret_cast<const uint32_t*>(src_pixels);
+ uint32_t* dest_scanline = reinterpret_cast<uint32_t*>(dest_pixels);
+ for (int32_t x = 0; x < src_rect_clipped.width(); ++x) {
+ uint32_t src = *src_scanline++;
+ uint32_t dst = *dest_scanline;
+ *dest_scanline++ = Blend(dst, src);
+ }
+ src_pixels += row_bytes_;
+ dest_pixels += dest_row_bytes;
+ }
+}
+
diff --git a/native_client_sdk/src/examples/demo/flock/sprite.h b/native_client_sdk/src/examples/demo/flock/sprite.h
new file mode 100644
index 0000000..b846768
--- /dev/null
+++ b/native_client_sdk/src/examples/demo/flock/sprite.h
@@ -0,0 +1,57 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SPRITE_H_
+#define SPRITE_H_
+
+#include <vector>
+#include "ppapi/cpp/point.h"
+#include "ppapi/cpp/rect.h"
+#include "ppapi/cpp/size.h"
+
+
+// A Sprite is a simple container of a pixel buffer. It knows how to
+// composite itself to another pixel buffer of the same format.
+class Sprite {
+ public:
+ // Initialize a Sprite to use the attached pixel buffer. The Sprite takes
+ // ownership of the pixel buffer, deleting it in the dtor. The pixel
+ // buffer is assumed to be 32-bit ARGB-8-8-8-8 pixel format, with pre-
+ // multiplied alpha. If |row_bytes| is 0, then the number of bytes per row
+ // is assumed to be size.width() * sizeof(uint32_t).
+ Sprite(uint32_t* pixel_buffer, const pp::Size& size, int32_t stride = 0);
+
+ // Delete the pixel buffer. It is assumed that the pixel buffer was created
+ // using malloc().
+ ~Sprite();
+
+ // Reset the internal pixel buffer to a new one. Deletes the old pixel
+ // buffer. Sprite takes ownership of the new pixel buffer. If |row_bytes|
+ // is 0, then the number of bytes per row is assumed to be size.width() *
+ // sizeof(uint32_t).
+ void SetPixelBuffer(uint32_t* pixel_buffer,
+ const pp::Size& size,
+ int32_t row_bytes);
+
+ // Composite the section of the Sprite contained in |src_rect| into the given
+ // pixel buffer at |dest_point|. Performs an average of the source and
+ // dest pixel, and all necessary clipping.
+ void CompositeFromRectToPoint(const pp::Rect& src_rect,
+ uint32_t* dest_pixel_buffer,
+ const pp::Rect& dest_bounds,
+ int32_t dest_row_bytes,
+ const pp::Point& dest_point) const;
+
+ // Accessors.
+ const pp::Size& size() const {
+ return pixel_buffer_size_;
+ }
+
+ private:
+ uint32_t* pixel_buffer_;
+ pp::Size pixel_buffer_size_;
+ int32_t row_bytes_;
+};
+
+#endif // SPRITE_H_
diff --git a/native_client_sdk/src/examples/demo/flock/vector2.h b/native_client_sdk/src/examples/demo/flock/vector2.h
new file mode 100644
index 0000000..9d68178
--- /dev/null
+++ b/native_client_sdk/src/examples/demo/flock/vector2.h
@@ -0,0 +1,81 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef VECTOR2_H_
+#define VECTOR2_H_
+
+#include <stdlib.h>
+#include <cmath>
+#include <limits>
+
+// A small class that encapsulates a 2D vector. Provides a few simple
+// operations.
+
+class Vector2 {
+ public:
+ Vector2() : x_(0.0), y_(0.0) {}
+ Vector2(double x, double y) : x_(x), y_(y) {}
+ ~Vector2() {}
+
+ // Create a new vector that represents a - b.
+ static Vector2 Difference(const Vector2& a, const Vector2& b) {
+ Vector2 diff(a.x() - b.x(), a.y() - b.y());
+ return diff;
+ }
+
+ // The magnitude of this vector.
+ double Magnitude() const {
+ return sqrt(x_ * x_ + y_ * y_);
+ }
+
+ // Add |vec| to this vector. Works in-place.
+ void Add(const Vector2& vec) {
+ x_ += vec.x();
+ y_ += vec.y();
+ }
+
+ // Normalize this vector in-place. If the vector is degenerate (size 0)
+ // then do nothing.
+ void Normalize() {
+ double mag = Magnitude();
+ if (fabs(mag) < std::numeric_limits<double>::epsilon())
+ return;
+ Scale(1.0 / mag);
+ }
+
+ // Scale the vector in-place by |scale|.
+ void Scale(double scale) {
+ x_ *= scale;
+ y_ *= scale;
+ }
+
+ // Clamp a vector to a maximum magnitude. Works on the vector in-place.
+ // @param max_mag The maximum magnitude of the vector.
+ void Clamp(double max_mag) {
+ double mag = Magnitude();
+ if (mag > max_mag) {
+ Scale(max_mag / mag); // Does Normalize() followed by Scale(max_mag).
+ }
+ }
+
+ // Compute the "heading" of a vector - this is the angle in radians between
+ // the vector and the x-axis.
+ // @return {!number} The "heading" angle in radians.
+ double Heading() const {
+ double angle = atan2(y_, x_);
+ return angle;
+ }
+
+ // Accessors and mutators for the coordinate values.
+ double x() const { return x_; }
+ void set_x(double x) { x_ = x; }
+
+ double y() const { return y_; }
+ void set_y(double y) { y_ = y; }
+
+ double x_;
+ double y_;
+};
+
+#endif // VECTOR2_H_
diff --git a/native_client_sdk/src/examples/demo/life/index.html b/native_client_sdk/src/examples/demo/life/index.html
index 626f532..6a5978fd 100644
--- a/native_client_sdk/src/examples/demo/life/index.html
+++ b/native_client_sdk/src/examples/demo/life/index.html
@@ -14,8 +14,6 @@ found in the LICENSE file.
<body data-width="640" data-height="640" {{attrs}}>
<h1>{{title}}</h1>
<h2>Status: <code id="statusField">NO-STATUS</code></h2>
- <p>
- </p>
<!-- The NaCl plugin will be embedded inside the element with id "listener".
See common.js.-->
<div id="listener"></div>
diff --git a/native_client_sdk/src/libraries/ppapi_simple/library.dsc b/native_client_sdk/src/libraries/ppapi_simple/library.dsc
index 74c215c..841aeed 100644
--- a/native_client_sdk/src/libraries/ppapi_simple/library.dsc
+++ b/native_client_sdk/src/libraries/ppapi_simple/library.dsc
@@ -6,8 +6,10 @@
'TYPE' : 'lib',
'SOURCES' : [
"ps.cc",
+ "ps_context_2d.cc",
"ps_event.cc",
"ps_instance.cc",
+ "ps_interface.cc",
"ps_main.cc",
],
}
@@ -16,8 +18,10 @@
{
'FILES': [
"ps.h",
+ "ps_context_2d.h",
"ps_event.h",
"ps_instance.h",
+ "ps_interface.h",
"ps_main.h",
],
'DEST': 'include/ppapi_simple',
diff --git a/native_client_sdk/src/libraries/ppapi_simple/ps_context_2d.cc b/native_client_sdk/src/libraries/ppapi_simple/ps_context_2d.cc
new file mode 100644
index 0000000..743dabe
--- /dev/null
+++ b/native_client_sdk/src/libraries/ppapi_simple/ps_context_2d.cc
@@ -0,0 +1,134 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.auto
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "ppapi/c/pp_rect.h"
+#include "ppapi/c/pp_resource.h"
+#include "ppapi/c/pp_size.h"
+#include "ppapi/c/ppb_core.h"
+#include "ppapi/c/ppb_graphics_2d.h"
+#include "ppapi/c/ppb_image_data.h"
+#include "ppapi/c/ppb_instance.h"
+#include "ppapi/c/ppb_view.h"
+#include "ppapi/cpp/image_data.h"
+
+#include "ppapi_simple/ps.h"
+#include "ppapi_simple/ps_context_2d.h"
+#include "ppapi_simple/ps_event.h"
+#include "ppapi_simple/ps_instance.h"
+#include "ppapi_simple/ps_interface.h"
+
+PSContext2D_t* PSContext2DAllocate() {
+ PSContext2D_t* ctx = (PSContext2D_t*) malloc(sizeof(PSContext2D_t));
+ memset(ctx, 0, sizeof(PSContext2D_t));
+
+ ctx->format = PSInterfaceImageData()->GetNativeImageDataFormat();
+ return ctx;
+}
+
+void PSContext2DFree(PSContext2D_t* ctx) {
+ if (ctx->graphic_2d) {
+ PSInterfaceCore()->ReleaseResource(ctx->graphic_2d);
+ ctx->graphic_2d = 0;
+ }
+ if (ctx->image) {
+ PSInterfaceCore()->ReleaseResource(ctx->image);
+ ctx->image = 0;
+ }
+ free(ctx);
+}
+
+// Update the 2D context if the message is appropriate, returning non-zero
+// if the event was consumed.
+int PSContext2DHandleEvent(PSContext2D_t* ctx, PSEvent* event) {
+ switch(event->type) {
+ case PSE_INSTANCE_DIDCHANGEVIEW: {
+ struct PP_Rect rect;
+
+ PSInterfaceView()->GetRect(event->as_resource, &rect);
+ PSInterfaceCore()->ReleaseResource(ctx->graphic_2d);
+ ctx->bound = 0;
+ ctx->width = rect.size.width;
+ ctx->height = rect.size.height;
+
+ // Create an opaque graphic context of the specified size.
+ ctx->graphic_2d =
+ PSInterfaceGraphics2D()->Create(PSGetInstanceId(), &rect.size,
+ PP_TRUE);
+
+ // Bind the context to so that draws will be visible.
+ if (ctx->graphic_2d) {
+ ctx->bound =
+ PSInterfaceInstance()->BindGraphics(PSGetInstanceId(),
+ ctx->graphic_2d);
+ }
+
+ // Typically this resource would not be allocated yet, but just in case
+ // throw it away, to force a new allocation when GetBuffer is called.
+ if (ctx->image) {
+ PSInterfaceCore()->ReleaseResource(ctx->image);
+ ctx->image = 0;
+ }
+
+ return 1;
+ }
+ default: break;
+ }
+
+ return 0;
+}
+
+
+// Allocates (if needed) a new image context which will be swapped in when
+// drawing is complete. PSContextGetBuffer and PSContext2DSwapBuffer
+// implemented the suggested image/graphic_2d use specified in the
+// ppb_graphics_2d header.
+int PSContext2DGetBuffer(PSContext2D_t* ctx) {
+ if (!ctx->bound) return 0;
+
+ // Check if we are already holding an image
+ if (ctx->image) return 1;
+
+ PP_Size size;
+ size.width = ctx->width;
+ size.height = ctx->height;
+
+ // Allocate a new image resource with the specified size and format, but
+ // do not ZERO out the buffer first since we will fill it.
+ PP_Resource image =
+ PSInterfaceImageData()->Create(PSGetInstanceId(), ctx->format, &size,
+ PP_FALSE);
+
+ if (0 == image) {
+ PSInstance::GetInstance()->Error("Unable to create 2D image.\n");
+ return 0;
+ }
+
+ // Get the stride
+ struct PP_ImageDataDesc desc;
+ PSInterfaceImageData()->Describe(image, &desc);
+
+ ctx->image = image;
+ ctx->data = static_cast<uint32_t*>(PSInterfaceImageData()->Map(image));
+ ctx->stride = desc.stride;
+ return 1;
+}
+
+int PSContext2DSwapBuffer(PSContext2D_t* ctx) {
+ if (ctx->bound && ctx->image) {
+ PSInterfaceImageData()->Unmap(ctx->image);
+ PSInterfaceGraphics2D()->ReplaceContents(ctx->graphic_2d, ctx->image);
+ PSInterfaceGraphics2D()->Flush(ctx->graphic_2d, PP_BlockUntilComplete());
+ PSInterfaceCore()->ReleaseResource(ctx->image);
+
+ ctx->image = 0;
+ ctx->stride = 0;
+ ctx->data = NULL;
+ return 1;
+ }
+ return 0;
+}
+
diff --git a/native_client_sdk/src/libraries/ppapi_simple/ps_context_2d.h b/native_client_sdk/src/libraries/ppapi_simple/ps_context_2d.h
new file mode 100644
index 0000000..707a53d
--- /dev/null
+++ b/native_client_sdk/src/libraries/ppapi_simple/ps_context_2d.h
@@ -0,0 +1,67 @@
+/* Copyright 2013 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file. */
+
+#ifndef PPAPI_SIMPLE_PS_CONTEXT_2D
+#define PPAPI_SIMPLE_PS_CONTEXT_2D
+
+#include "ppapi/c/pp_resource.h"
+#include "ppapi/c/ppb_graphics_2d.h"
+#include "ppapi/c/ppb_image_data.h"
+
+#include "ppapi_simple/ps_event.h"
+
+#include "sdk_util/macros.h"
+
+EXTERN_C_BEGIN
+
+typedef struct {
+ int bound;
+ int32_t width;
+ int32_t height;
+ uint32_t stride;
+ uint32_t* data;
+ PP_ImageDataFormat format;
+ PP_Resource graphic_2d;
+ PP_Resource image;
+} PSContext2D_t;
+
+
+/*
+ * PSContext2DAllocate
+ *
+ * Allocate or free a 2D context object which the library can use to perform
+ * various PPAPI operations on the developer's behalf, such as processing view
+ * change events, swapping buffers, etc...
+ */
+PSContext2D_t* PSContext2DAllocate();
+void PSContext2DFree(PSContext2D_t* ctx);
+
+/*
+ * PSContext2DHandleEvent
+ *
+ * Updates the context such as allocating, freeing, or sizing graphics and
+ * image resources in response to events.
+ */
+int PSContext2DHandleEvent(PSContext2D_t* ctx, PSEvent* event);
+
+/*
+ * PSContext2DGetBuffer
+ *
+ * Points the data member of the context to the raw pixels of the image for
+ * writing to the screen. The image will become visible after a swap.
+ */
+int PSContext2DGetBuffer(PSContext2D_t* ctx);
+
+/*
+ * PSContext2DSwapBuffer
+ *
+ * Swaps out the currently visible graphics with the data stored in the image
+ * buffer making it visible. The old image resource will no longer be
+ * available after this call.
+ */
+int PSContext2DSwapBuffer(PSContext2D_t* ctx);
+
+EXTERN_C_END
+
+#endif // PPAPI_SIMPLE_PS_CONTEXT_2D
diff --git a/native_client_sdk/src/libraries/ppapi_simple/ps_event.h b/native_client_sdk/src/libraries/ppapi_simple/ps_event.h
index 563832c..b02f54d 100644
--- a/native_client_sdk/src/libraries/ppapi_simple/ps_event.h
+++ b/native_client_sdk/src/libraries/ppapi_simple/ps_event.h
@@ -1,6 +1,6 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
+/* Copyright (c) 2013 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file. */
#ifndef PPAPI_SIMPLE_PS_EVENT_H_
diff --git a/native_client_sdk/src/libraries/ppapi_simple/ps_instance.cc b/native_client_sdk/src/libraries/ppapi_simple/ps_instance.cc
index 84a66ba..0b5c634 100644
--- a/native_client_sdk/src/libraries/ppapi_simple/ps_instance.cc
+++ b/native_client_sdk/src/libraries/ppapi_simple/ps_instance.cc
@@ -31,6 +31,7 @@
#include "ppapi_simple/ps_event.h"
#include "ppapi_simple/ps_instance.h"
+#include "ppapi_simple/ps_interface.h"
#include "ppapi_simple/ps_main.h"
#if defined(WIN32)
@@ -84,6 +85,8 @@ int PSInstance::MainThread(int argc, char *argv[]) {
PSInstance::PSInstance(PP_Instance instance, const char *argv[])
: pp::Instance(instance),
+ pp::MouseLock(this),
+ pp::Graphics3DClient(this),
main_loop_(NULL),
verbosity_(PSV_LOG),
events_enabled_(PSE_NONE) {
@@ -105,15 +108,6 @@ PSInstance::PSInstance(PP_Instance instance, const char *argv[])
PP_INPUTEVENT_CLASS_KEYBOARD |
PP_INPUTEVENT_CLASS_WHEEL |
PP_INPUTEVENT_CLASS_TOUCH);
-
- ppb_core_ = static_cast<const PPB_Core*>(
- pp::Module::Get()->GetBrowserInterface(PPB_CORE_INTERFACE));
-
- ppb_var_ = static_cast<const PPB_Var*>(
- pp::Module::Get()->GetBrowserInterface(PPB_VAR_INTERFACE));
-
- ppb_view_ = static_cast<const PPB_View*>(
- pp::Module::Get()->GetBrowserInterface(PPB_VIEW_INTERFACE));
}
PSInstance::~PSInstance() {}
@@ -177,6 +171,8 @@ bool PSInstance::Init(uint32_t arg,
si->argv_[0] = name;
}
+ PSInterfaceInit();
+
if (ProcessProperties()) {
pthread_t main_thread;
int ret = pthread_create(&main_thread, NULL, MainThreadThunk, si);
@@ -290,7 +286,7 @@ void PSInstance::PostEvent(PSEventType type, PP_Resource resource) {
if (events_enabled_ & type) {
if (resource) {
- ppb_core_->AddRefResource(resource);
+ PSInterfaceCore()->AddRefResource(resource);
}
PSEvent *env = (PSEvent *) malloc(sizeof(PSEvent));
memset(env, 0, sizeof(*env));
@@ -304,7 +300,7 @@ void PSInstance::PostEvent(PSEventType type, const PP_Var& var) {
assert(PSE_INSTANCE_HANDLEMESSAGE == type);
if (events_enabled_ & type) {
- ppb_var_->AddRef(var);
+ PSInterfaceVar()->AddRef(var);
PSEvent *env = (PSEvent *) malloc(sizeof(PSEvent));
memset(env, 0, sizeof(*env));
env->type = type;
@@ -325,12 +321,12 @@ void PSInstance::ReleaseEvent(PSEvent* event) {
if (event) {
switch(event->type) {
case PSE_INSTANCE_HANDLEMESSAGE:
- ppb_var_->Release(event->as_var);
+ PSInterfaceVar()->Release(event->as_var);
break;
case PSE_INSTANCE_HANDLEINPUT:
case PSE_INSTANCE_DIDCHANGEVIEW:
if (event->as_resource) {
- ppb_core_->ReleaseResource(event->as_resource);
+ PSInterfaceCore()->ReleaseResource(event->as_resource);
}
break;
default:
@@ -346,7 +342,6 @@ void PSInstance::HandleMessage(const pp::Var& message) {
}
bool PSInstance::HandleInputEvent(const pp::InputEvent& event) {
- Log("Got Input\n");
PostEvent(PSE_INSTANCE_HANDLEINPUT, event.pp_resource());
return true;
}
@@ -362,3 +357,12 @@ void PSInstance::DidChangeFocus(bool focus) {
PostEvent(PSE_INSTANCE_DIDCHANGEFOCUS, focus ? PP_TRUE : PP_FALSE);
}
+void PSInstance::Graphics3DContextLost() {
+ Log("Graphics3DContextLost\n");
+ PostEvent(PSE_GRAPHICS3D_GRAPHICS3DCONTEXTLOST);
+}
+
+void PSInstance::MouseLockLost() {
+ Log("MouseLockLost\n");
+ PostEvent(PSE_MOUSELOCK_MOUSELOCKLOST);
+}
diff --git a/native_client_sdk/src/libraries/ppapi_simple/ps_instance.h b/native_client_sdk/src/libraries/ppapi_simple/ps_instance.h
index bf9fbe4..55c5192 100644
--- a/native_client_sdk/src/libraries/ppapi_simple/ps_instance.h
+++ b/native_client_sdk/src/libraries/ppapi_simple/ps_instance.h
@@ -1,6 +1,8 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
+/* Copyright (c) 2013 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
#ifndef PPAPI_SIMPLE_PS_INSTANCE_H_
#define PPAPI_SIMPLE_PS_INSTANCE_H_
@@ -14,6 +16,7 @@
#include "ppapi/c/ppb_view.h"
#include "ppapi/cpp/fullscreen.h"
+#include "ppapi/cpp/graphics_3d_client.h"
#include "ppapi/cpp/instance.h"
#include "ppapi/cpp/message_loop.h"
#include "ppapi/cpp/mouse_lock.h"
@@ -28,7 +31,9 @@
typedef std::map<std::string, std::string> PropertyMap_t;
-class PSInstance : public pp::Instance {
+// The basic instance class which also inherits the MouseLock and
+// Graphics3DClient interfaces.
+class PSInstance : public pp::Instance, pp::MouseLock, pp::Graphics3DClient {
public:
enum Verbosity {
PSV_SILENT,
@@ -95,6 +100,12 @@ class PSInstance : public pp::Instance {
// and can later be processed on a sperate processing thread.
virtual bool HandleInputEvent(const pp::InputEvent& event);
+ // Called by the browser when the 3D context is lost.
+ virtual void Graphics3DContextLost();
+
+ // Called by the browser when the mouselock is lost.
+ virtual void MouseLockLost();
+
// Called by Init to processes default and embed tag arguments prior to
// launching the 'ppapi_main' thread.
virtual bool ProcessProperties();
@@ -112,9 +123,8 @@ class PSInstance : public pp::Instance {
PSMainFunc_t main_cb_;
- const PPB_Core* ppb_core_;
- const PPB_Var* ppb_var_;
- const PPB_View* ppb_view_;
+ friend class PSGraphics3DClient;
+ friend class PSMouseLock;
};
#endif // PPAPI_MAIN_PS_INSTANCE_H_
diff --git a/native_client_sdk/src/libraries/ppapi_simple/ps_interface.cc b/native_client_sdk/src/libraries/ppapi_simple/ps_interface.cc
new file mode 100644
index 0000000..da97ed3
--- /dev/null
+++ b/native_client_sdk/src/libraries/ppapi_simple/ps_interface.cc
@@ -0,0 +1,62 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi_simple/ps.h"
+#include "ppapi_simple/ps_interface.h"
+
+#define DEFINE_INTERFACE_FUNC(Name) \
+ static const PPB_##Name* s_##Name; \
+ const PPB_##Name* PSInterface##Name() { return s_##Name; }
+
+DEFINE_INTERFACE_FUNC(Audio)
+DEFINE_INTERFACE_FUNC(AudioConfig)
+DEFINE_INTERFACE_FUNC(Console)
+DEFINE_INTERFACE_FUNC(Core)
+DEFINE_INTERFACE_FUNC(FileIO)
+DEFINE_INTERFACE_FUNC(FileRef)
+DEFINE_INTERFACE_FUNC(FileSystem)
+DEFINE_INTERFACE_FUNC(Fullscreen)
+DEFINE_INTERFACE_FUNC(Gamepad)
+DEFINE_INTERFACE_FUNC(Graphics2D)
+DEFINE_INTERFACE_FUNC(Graphics3D)
+DEFINE_INTERFACE_FUNC(ImageData)
+DEFINE_INTERFACE_FUNC(Instance)
+DEFINE_INTERFACE_FUNC(MessageLoop)
+DEFINE_INTERFACE_FUNC(MouseCursor)
+DEFINE_INTERFACE_FUNC(URLLoader)
+DEFINE_INTERFACE_FUNC(URLRequestInfo)
+DEFINE_INTERFACE_FUNC(URLResponseInfo)
+DEFINE_INTERFACE_FUNC(Var)
+DEFINE_INTERFACE_FUNC(VarArrayBuffer)
+DEFINE_INTERFACE_FUNC(View)
+DEFINE_INTERFACE_FUNC(WebSocket)
+
+
+#define REQUEST_INTERFACE(x, y) \
+ s_##x = static_cast<const PPB_##x*>(PSGetInterface(PPB_ ## y ##_INTERFACE));
+
+void PSInterfaceInit() {
+ REQUEST_INTERFACE(Audio, AUDIO)
+ REQUEST_INTERFACE(AudioConfig, AUDIO_CONFIG)
+ REQUEST_INTERFACE(Console, CONSOLE)
+ REQUEST_INTERFACE(Core, CORE)
+ REQUEST_INTERFACE(FileIO, FILEIO)
+ REQUEST_INTERFACE(FileRef, FILEREF)
+ REQUEST_INTERFACE(FileSystem, FILESYSTEM)
+ REQUEST_INTERFACE(Fullscreen, FULLSCREEN)
+ REQUEST_INTERFACE(Gamepad, GAMEPAD)
+ REQUEST_INTERFACE(Graphics2D, GRAPHICS_2D)
+ REQUEST_INTERFACE(Graphics3D, GRAPHICS_3D)
+ REQUEST_INTERFACE(ImageData, IMAGEDATA)
+ REQUEST_INTERFACE(Instance, INSTANCE)
+ REQUEST_INTERFACE(MessageLoop, MESSAGELOOP)
+ REQUEST_INTERFACE(MouseCursor, MOUSECURSOR)
+ REQUEST_INTERFACE(URLLoader, URLLOADER)
+ REQUEST_INTERFACE(URLRequestInfo, URLREQUESTINFO)
+ REQUEST_INTERFACE(URLResponseInfo, URLRESPONSEINFO)
+ REQUEST_INTERFACE(Var, VAR)
+ REQUEST_INTERFACE(VarArrayBuffer, VAR_ARRAY_BUFFER)
+ REQUEST_INTERFACE(View, VIEW)
+ REQUEST_INTERFACE(WebSocket, WEBSOCKET)
+} \ No newline at end of file
diff --git a/native_client_sdk/src/libraries/ppapi_simple/ps_interface.h b/native_client_sdk/src/libraries/ppapi_simple/ps_interface.h
new file mode 100644
index 0000000..16ecdc0
--- /dev/null
+++ b/native_client_sdk/src/libraries/ppapi_simple/ps_interface.h
@@ -0,0 +1,71 @@
+/* Copyright 2013 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file. */
+
+
+#ifndef PPAPI_SIMPLE_PS_INTERFACE_H_
+#define PPAPI_SIMPLE_PS_INTERFACE_H_
+
+#include "ppapi/c/pp_bool.h"
+#include "ppapi/c/pp_resource.h"
+#include "ppapi/c/pp_var.h"
+
+
+#include "ppapi/c/ppb_audio.h"
+#include "ppapi/c/ppb_audio_config.h"
+#include "ppapi/c/ppb_console.h"
+#include "ppapi/c/ppb_core.h"
+#include "ppapi/c/ppb_file_io.h"
+#include "ppapi/c/ppb_file_ref.h"
+#include "ppapi/c/ppb_file_system.h"
+#include "ppapi/c/ppb_fullscreen.h"
+#include "ppapi/c/ppb_gamepad.h"
+#include "ppapi/c/ppb_graphics_2d.h"
+#include "ppapi/c/ppb_graphics_3d.h"
+#include "ppapi/c/ppb_image_data.h"
+#include "ppapi/c/ppb_instance.h"
+#include "ppapi/c/ppb_message_loop.h"
+#include "ppapi/c/ppb_messaging.h"
+#include "ppapi/c/ppb_mouse_cursor.h"
+#include "ppapi/c/ppb_mouse_lock.h"
+#include "ppapi/c/ppb_url_loader.h"
+#include "ppapi/c/ppb_url_request_info.h"
+#include "ppapi/c/ppb_url_response_info.h"
+#include "ppapi/c/ppb_var.h"
+#include "ppapi/c/ppb_var_array_buffer.h"
+#include "ppapi/c/ppb_view.h"
+#include "ppapi/c/ppb_websocket.h"
+
+#include "sdk_util/macros.h"
+
+EXTERN_C_BEGIN
+
+const PPB_Audio* PSInterfaceAudio();
+const PPB_AudioConfig* PSInterfaceAudioConfig();
+const PPB_Console* PSInterfaceConsole();
+const PPB_Core* PSInterfaceCore();
+const PPB_FileIO* PSInterfaceFileIO();
+const PPB_FileRef* PSInterfaceFileRef();
+const PPB_FileSystem* PSInterfaceFileSystem();
+const PPB_Fullscreen* PSInterfaceFullscreen();
+const PPB_Gamepad* PSInterfaceGamepad();
+const PPB_Graphics2D* PSInterfaceGraphics2D();
+const PPB_Graphics3D* PSInterfaceGraphics3D();
+const PPB_ImageData* PSInterfaceImageData();
+const PPB_Instance* PSInterfaceInstance();
+const PPB_MessageLoop* PSInterfaceMessageLoop();
+const PPB_MouseCursor* PSInterfaceMouseCursor();
+const PPB_URLLoader* PSInterfaceURLLoader();
+const PPB_URLRequestInfo* PSInterfaceURLRequestInfo();
+const PPB_URLResponseInfo* PSInterfaceURLResponseInfo();
+const PPB_Var* PSInterfaceVar();
+const PPB_VarArrayBuffer* PSInterfaceVarArrayBuffer();
+const PPB_View* PSInterfaceView();
+const PPB_WebSocket* PSInterfaceWebSocket();
+
+
+/* Initializes the Interface module which fetches the above interfaces. */
+void PSInterfaceInit();
+
+EXTERN_C_END
+#endif /* PPAPI_SIMPLE_PS_INTERFACE_H */ \ No newline at end of file