diff options
author | noelallen@chromium.org <noelallen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-06-24 22:26:13 +0000 |
---|---|---|
committer | noelallen@chromium.org <noelallen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-06-24 22:26:13 +0000 |
commit | 2ea96e502f6f84cf50495f98be5d5b2ac204dfec (patch) | |
tree | a18db4aa051c503a47636bde7b851ef36ffec4ad /native_client_sdk | |
parent | e2db10a81a814aa62d616d685b782146d4bb2cd6 (diff) | |
download | chromium_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')
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 |