1868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved.
2868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// found in the LICENSE file.
4868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
5868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include <assert.h>
6868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include <math.h>
73240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#include <ppapi/c/ppb_input_event.h>
8868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include <ppapi/cpp/input_event.h>
9868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include <ppapi/cpp/var.h>
103240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#include <ppapi/cpp/var_array.h>
113240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#include <ppapi/cpp/var_array_buffer.h>
12eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include <ppapi/cpp/var_dictionary.h>
13868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include <pthread.h>
14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include <stdio.h>
15868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include <stdlib.h>
16868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include <string.h>
17868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include <sys/time.h>
18868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include <unistd.h>
19868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
20868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include <algorithm>
21868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include <string>
22868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
233240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#include "ppapi_simple/ps.h"
243240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#include "ppapi_simple/ps_context_2d.h"
253240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#include "ppapi_simple/ps_event.h"
263240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#include "ppapi_simple/ps_interface.h"
273240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#include "ppapi_simple/ps_main.h"
28868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "sdk_util/thread_pool.h"
29868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
30ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochusing namespace sdk_util;  // For sdk_util::ThreadPool
31ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
32868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Global properties used to setup Voronoi demo.
33868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)namespace {
34868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)const int kMinRectSize = 4;
35868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)const int kStartRecurseSize = 32;  // must be power-of-two
36868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)const float kHugeZ = 1.0e38f;
37868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)const float kPI = M_PI;
38868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)const float kTwoPI = kPI * 2.0f;
39868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)const int kFramesToBenchmark = 100;
40868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)const unsigned int kRandomStartSeed = 0xC0DE533D;
41868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)const int kMaxPointCount = 1024;
424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)const int kStartPointCount = 48;
433240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochconst int kDefaultNumRegions = 256;
44868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
45868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)unsigned int g_rand_state = kRandomStartSeed;
46868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
47868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// random number helper
48868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)inline unsigned char rand255() {
49868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return static_cast<unsigned char>(rand_r(&g_rand_state) & 255);
50868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
51868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
52868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// random number helper
53868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)inline float frand() {
54868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return (static_cast<float>(rand_r(&g_rand_state)) /
55868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      static_cast<float>(RAND_MAX));
56868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
57868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
58868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// reset random seed
59868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)inline void rand_reset(unsigned int seed) {
60868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  g_rand_state = seed;
61868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
62868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
6358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#ifndef NDEBUG
64868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// returns true if input is power of two.
6558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// only used in assertions.
66868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)inline bool is_pow2(int x) {
67868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return (x & (x - 1)) == 0;
68868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
6958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#endif
70868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
71868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)inline double getseconds() {
72868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const double usec_to_sec = 0.000001;
73868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  timeval tv;
74868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (0 == gettimeofday(&tv, NULL))
75868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return tv.tv_sec + tv.tv_usec * usec_to_sec;
76868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return 0.0;
77868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
78868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// BGRA helper function, for constructing a pixel for a BGRA buffer.
803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)inline uint32_t MakeBGRA(uint32_t b, uint32_t g, uint32_t r, uint32_t a) {
81868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return (((a) << 24) | ((r) << 16) | ((g) << 8) | (b));
82868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
83868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}  // namespace
84868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
85868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Vec2, simple 2D vector
86868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)struct Vec2 {
87868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  float x, y;
88868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Vec2() {}
89868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Vec2(float px, float py) {
90868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    x = px;
91868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    y = py;
92868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
93868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  void Set(float px, float py) {
94868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    x = px;
95868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    y = py;
96868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
97868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)};
98868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
99868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// The main object that runs Voronoi simulation.
1003240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochclass Voronoi {
101868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) public:
1023240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  Voronoi();
103868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  virtual ~Voronoi();
1043240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // Runs a tick of the simulations, update 2D output.
1053240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  void Update();
1063240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // Handle event from user, or message from JS.
1073240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  void HandleEvent(PSEvent* ps_event);
108868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
109868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) private:
110868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Methods prefixed with 'w' are run on worker threads.
1113240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  uint32_t* wGetAddr(int x, int y);
112868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int wCell(float x, float y);
113868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  inline void wFillSpan(uint32_t *pixels, uint32_t color, int width);
114868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  void wRenderTile(int x, int y, int w, int h);
115868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  void wProcessTile(int x, int y, int w, int h);
116868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  void wSubdivide(int x, int y, int w, int h);
117868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  void wMakeRect(int region, int *x, int *y, int *w, int *h);
118868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool wTestRect(int *m, int x, int y, int w, int h);
119868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  void wFillRect(int x, int y, int w, int h, uint32_t color);
120868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  void wRenderRect(int x0, int y0, int x1, int y1);
121868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  void wRenderRegion(int region);
122868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  static void wRenderRegionEntry(int region, void *thiz);
123868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
124868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // These methods are only called by the main thread.
125868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  void Reset();
126868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  void UpdateSim();
127868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  void RenderDot(float x, float y, uint32_t color1, uint32_t color2);
128868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  void SuperimposePositions();
129868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  void Render();
130868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  void Draw();
131868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  void StartBenchmark();
132868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  void EndBenchmark();
133eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Helper to post small update messages to JS.
134eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  void PostUpdateMessage(const char* message_name, double value);
135868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1363240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  PSContext2D_t* ps_context_;
137868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Vec2 positions_[kMaxPointCount];
138868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Vec2 screen_positions_[kMaxPointCount];
139868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Vec2 velocities_[kMaxPointCount];
140868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  uint32_t colors_[kMaxPointCount];
141868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  float ang_;
142868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const int num_regions_;
1433240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  int num_threads_;
1443240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  int point_count_;
145868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool draw_points_;
146868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool draw_interiors_;
147868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ThreadPool* workers_;
148868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int benchmark_frame_counter_;
149868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool benchmarking_;
150868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  double benchmark_start_time_;
151868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  double benchmark_end_time_;
152868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)};
153868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
154868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
155868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void Voronoi::Reset() {
156868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  rand_reset(kRandomStartSeed);
157868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ang_ = 0.0f;
158868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  for (int i = 0; i < kMaxPointCount; i++) {
159868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // random initial start position
160868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const float x = frand();
161868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const float y = frand();
162868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    positions_[i].Set(x, y);
163868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // random directional velocity ( -1..1, -1..1 )
164868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const float speed = 0.0005f;
165868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const float u = (frand() * 2.0f - 1.0f) * speed;
166868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const float v = (frand() * 2.0f - 1.0f) * speed;
167868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    velocities_[i].Set(u, v);
168868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // 'unique' color (well... unique enough for our purposes)
1693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    colors_[i] = MakeBGRA(rand255(), rand255(), rand255(), 255);
170868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
171868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
172868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1733240926e260ce088908e02ac07a6cf7b0c0cbf44Ben MurdochVoronoi::Voronoi() : num_regions_(kDefaultNumRegions), num_threads_(0),
1743240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    point_count_(kStartPointCount), draw_points_(true), draw_interiors_(true),
1753240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    benchmark_frame_counter_(0), benchmarking_(false)  {
176868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Reset();
177868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // By default, render from the dispatch thread.
178868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  workers_ = new ThreadPool(num_threads_);
1793240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  PSEventSetFilter(PSE_ALL);
1803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  ps_context_ = PSContext2DAllocate(PP_IMAGEDATAFORMAT_BGRA_PREMUL);
181868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
182868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
183868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)Voronoi::~Voronoi() {
184868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  delete workers_;
1853240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  PSContext2DFree(ps_context_);
1863240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch}
1873240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
1883240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochinline uint32_t* Voronoi::wGetAddr(int x, int y) {
1893240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  return ps_context_->data + x + y * ps_context_->stride / sizeof(uint32_t);
190868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
191868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
192868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// This is the core of the Voronoi calculation.  At a given point on the
193868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// screen, iterate through all voronoi positions and render them as 3D cones.
194868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// We're looking for the voronoi cell that generates the closest z value.
195868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// (not really cones - since it is all relative, we avoid doing the
196868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// expensive sqrt and test against z*z instead)
197868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// If multithreading, this function is only called by the worker threads.
198868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)int Voronoi::wCell(float x, float y) {
199868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int closest_cell = 0;
200868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  float zz = kHugeZ;
201868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Vec2* pos = screen_positions_;
202868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  for (int i = 0; i < point_count_; ++i) {
203868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // measured 5.18 cycles per iteration on a core2
204868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    float dx = x - pos[i].x;
205868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    float dy = y - pos[i].y;
206868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    float dd = (dx * dx + dy * dy);
207868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (dd < zz) {
208868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      zz = dd;
209868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      closest_cell = i;
210868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
211868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
212868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return closest_cell;
213868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
214868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
215868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Given a region r, derive a non-overlapping rectangle for a thread to
216868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// work on.
217868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// If multithreading, this function is only called by the worker threads.
218868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void Voronoi::wMakeRect(int r, int* x, int* y, int* w, int* h) {
219868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const int parts = 16;
220868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  assert(parts * parts == num_regions_);
2213240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  *w = ps_context_->width / parts;
2223240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  *h = ps_context_->height / parts;
223868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  *x = *w * (r % parts);
224868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  *y = *h * ((r / parts) % parts);
225868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
226868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
227868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Test 4 corners of a rectangle to see if they all belong to the same
228868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// voronoi cell.  Each test is expensive so bail asap.  Returns true
229868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// if all 4 corners match.
230868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// If multithreading, this function is only called by the worker threads.
231868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)bool Voronoi::wTestRect(int* m, int x, int y, int w, int h) {
232868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // each test is expensive, so exit ASAP
233868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const int m0 = wCell(x, y);
234868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const int m1 = wCell(x + w - 1, y);
235868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (m0 != m1) return false;
236868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const int m2 = wCell(x, y + h - 1);
237868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (m0 != m2) return false;
238868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const int m3 = wCell(x + w - 1, y + h - 1);
239868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (m0 != m3) return false;
240868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // all 4 corners belong to the same cell
241868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  *m = m0;
242868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return true;
243868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
244868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
245868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Quickly fill a span of pixels with a solid color.  Assumes
246868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// span width is divisible by 4.
247868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// If multithreading, this function is only called by the worker threads.
248868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)inline void Voronoi::wFillSpan(uint32_t* pixels, uint32_t color, int width) {
249868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!draw_interiors_) {
2503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const uint32_t gray = MakeBGRA(128, 128, 128, 255);
251868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    color = gray;
252868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
253868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  for (int i = 0; i < width; i += 4) {
254868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    *pixels++ = color;
255868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    *pixels++ = color;
256868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    *pixels++ = color;
257868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    *pixels++ = color;
258868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
259868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
260868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
261868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Quickly fill a rectangle with a solid color.  Assumes
262868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// the width w parameter is evenly divisible by 4.
263868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// If multithreading, this function is only called by the worker threads.
264868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void Voronoi::wFillRect(int x, int y, int w, int h, uint32_t color) {
2653240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  const uint32_t stride_in_pixels = ps_context_->stride / sizeof(uint32_t);
2663240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  uint32_t* pixels = wGetAddr(x, y);
267868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  for (int j = 0; j < h; j++) {
268868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    wFillSpan(pixels, color, w);
2693240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    pixels += stride_in_pixels;
270868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
271868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
272868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
273868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// When recursive subdivision reaches a certain minimum without finding a
274868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// rectangle that has four matching corners belonging to the same voronoi
275868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// cell, this function will break the retangular 'tile' into smaller scanlines
276868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)//  and look for opportunities to quick fill at the scanline level.  If the
277868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// scanline can't be quick filled, it will slow down even further and compute
278868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// voronoi membership per pixel.
279868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void Voronoi::wRenderTile(int x, int y, int w, int h) {
280868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // rip through a tile
2813240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  const uint32_t stride_in_pixels = ps_context_->stride / sizeof(uint32_t);
2823240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  uint32_t* pixels = wGetAddr(x, y);
283868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  for (int j = 0; j < h; j++) {
284868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // get start and end cell values
285868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int ms = wCell(x + 0, y + j);
286868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int me = wCell(x + w - 1, y + j);
287868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // if the end points are the same, quick fill the span
288868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (ms == me) {
289868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      wFillSpan(pixels, colors_[ms], w);
290868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    } else {
291868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // else compute each pixel in the span... this is the slow part!
292868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      uint32_t* p = pixels;
293868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      *p++ = colors_[ms];
294868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      for (int i = 1; i < (w - 1); i++) {
295868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        int m = wCell(x + i, y + j);
296868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        *p++ = colors_[m];
297868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      }
298868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      *p++ = colors_[me];
299868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
3003240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    pixels += stride_in_pixels;
301868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
302868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
303868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
304868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Take a rectangular region and do one of -
305868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)//   If all four corners below to the same voronoi cell, stop recursion and
306868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// quick fill the rectangle.
307868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)//   If the minimum rectangle size has been reached, break out of recursion
308868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// and process the rectangle.  This small rectangle is called a tile.
309868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)//   Otherwise, keep recursively subdividing the rectangle into 4 equally
310868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// sized smaller rectangles.
311868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Note: at the moment, these will always be squares, not rectangles.
312868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// If multithreading, this function is only called by the worker threads.
313868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void Voronoi::wSubdivide(int x, int y, int w, int h) {
314868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int m;
315868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // if all 4 corners are equal, quick fill interior
316868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (wTestRect(&m, x, y, w, h)) {
317868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    wFillRect(x, y, w, h, colors_[m]);
318868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  } else {
319868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // did we reach the minimum rectangle size?
320868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if ((w <= kMinRectSize) || (h <= kMinRectSize)) {
321868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      wRenderTile(x, y, w, h);
322868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    } else {
323868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // else recurse into smaller rectangles
324868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      const int half_w = w / 2;
325868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      const int half_h = h / 2;
326868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      wSubdivide(x, y, half_w, half_h);
327868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      wSubdivide(x + half_w, y, half_w, half_h);
328868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      wSubdivide(x, y + half_h, half_w, half_h);
329868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      wSubdivide(x + half_w, y + half_h, half_w, half_h);
330868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
331868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
332868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
333868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
334868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// This function cuts up the rectangle into power of 2 sized squares.  It
335868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// assumes the input rectangle w & h are evenly divisible by
336868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// kStartRecurseSize.
337868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// If multithreading, this function is only called by the worker threads.
338868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void Voronoi::wRenderRect(int x, int y, int w, int h) {
339868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  for (int iy = y; iy < (y + h); iy += kStartRecurseSize) {
340868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    for (int ix = x; ix < (x + w); ix += kStartRecurseSize) {
341868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      wSubdivide(ix, iy, kStartRecurseSize, kStartRecurseSize);
342868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
343868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
344868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
345868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
346868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// If multithreading, this function is only called by the worker threads.
347868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void Voronoi::wRenderRegion(int region) {
348868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // convert region # into x0, y0, x1, y1 rectangle
349868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int x, y, w, h;
350868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  wMakeRect(region, &x, &y, &w, &h);
351868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // render this rectangle
352868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  wRenderRect(x, y, w, h);
353868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
354868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
355868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Entry point for worker thread.  Can't pass a member function around, so we
356868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// have to do this little round-about.
357868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void Voronoi::wRenderRegionEntry(int region, void* thiz) {
358868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  static_cast<Voronoi*>(thiz)->wRenderRegion(region);
359868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
360868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
361868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Function Voronoi::UpdateSim()
362868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Run a simple sim to move the voronoi positions.  This update loop
363868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// is run once per frame.  Called from the main thread only, and only
364868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// when the worker threads are idle.
365868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void Voronoi::UpdateSim() {
366868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ang_ += 0.002f;
367868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (ang_ > kTwoPI) {
368868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    ang_ = ang_ - kTwoPI;
369868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
370868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  float z = cosf(ang_) * 3.0f;
371868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // push the points around on the screen for animation
372868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  for (int j = 0; j < kMaxPointCount; j++) {
373868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    positions_[j].x += (velocities_[j].x) * z;
374868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    positions_[j].y += (velocities_[j].y) * z;
3753240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    screen_positions_[j].x = positions_[j].x * ps_context_->width;
3763240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    screen_positions_[j].y = positions_[j].y * ps_context_->height;
377868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
378868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
379868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
380868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Renders a small diamond shaped dot at x, y clipped against the window
381868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void Voronoi::RenderDot(float x, float y, uint32_t color1, uint32_t color2) {
382868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const int ix = static_cast<int>(x);
383868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const int iy = static_cast<int>(y);
3843240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  const uint32_t stride_in_pixels = ps_context_->stride / sizeof(uint32_t);
385868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // clip it against window
386868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (ix < 1) return;
3873240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  if (ix >= (ps_context_->width - 1)) return;
388868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (iy < 1) return;
3893240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  if (iy >= (ps_context_->height - 1)) return;
3903240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  uint32_t* pixel = wGetAddr(ix, iy);
391868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // render dot as a small diamond
392868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  *pixel = color1;
393868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  *(pixel - 1) = color2;
394868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  *(pixel + 1) = color2;
3953240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  *(pixel - stride_in_pixels) = color2;
3963240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  *(pixel + stride_in_pixels) = color2;
397868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
398868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
399868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Superimposes dots on the positions.
400868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void Voronoi::SuperimposePositions() {
4013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  const uint32_t white = MakeBGRA(255, 255, 255, 255);
4023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  const uint32_t gray = MakeBGRA(192, 192, 192, 255);
403868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  for (int i = 0; i < point_count_; i++) {
404868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    RenderDot(
405868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        screen_positions_[i].x, screen_positions_[i].y, white, gray);
406868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
407868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
408868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
409868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Renders the Voronoi diagram, dispatching the work to multiple threads.
410868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void Voronoi::Render() {
411868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  workers_->Dispatch(num_regions_, wRenderRegionEntry, this);
412868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (draw_points_)
413868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    SuperimposePositions();
414868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
415868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
416868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void Voronoi::StartBenchmark() {
417868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Reset();
418868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  printf("Benchmark started...\n");
419868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  benchmark_frame_counter_ = kFramesToBenchmark;
420868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  benchmarking_ = true;
421868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  benchmark_start_time_ = getseconds();
422868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
423868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
424868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void Voronoi::EndBenchmark() {
425868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  benchmark_end_time_ = getseconds();
426868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  printf("Benchmark ended... time: %2.5f\n",
427868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      benchmark_end_time_ - benchmark_start_time_);
428868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  benchmarking_ = false;
429868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  benchmark_frame_counter_ = 0;
430eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  double result = benchmark_end_time_ - benchmark_start_time_;
431eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  PostUpdateMessage("benchmark_result", result);
432868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
433868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
4343240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch// Handle input events from the user and messages from JS.
4353240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochvoid Voronoi::HandleEvent(PSEvent* ps_event) {
4363240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // Give the 2D context a chance to process the event.
4373240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  if (0 != PSContext2DHandleEvent(ps_context_, ps_event))
4383240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    return;
4393240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  if (ps_event->type == PSE_INSTANCE_HANDLEINPUT) {
4403240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    // Convert Pepper Simple event to a PPAPI C++ event
4413240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    pp::InputEvent event(ps_event->as_resource);
4423240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    switch (event.GetType()) {
4433240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      case PP_INPUTEVENT_TYPE_KEYDOWN: {
4443240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch        pp::KeyboardInputEvent key = pp::KeyboardInputEvent(event);
4453240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch        uint32_t key_code = key.GetKeyCode();
4463240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch        if (key_code == 84)  // 't' key
4473240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch          if (!benchmarking_)
4483240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch            StartBenchmark();
4493240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch        break;
4503240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      }
4514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      case PP_INPUTEVENT_TYPE_TOUCHSTART:
4524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      case PP_INPUTEVENT_TYPE_TOUCHMOVE: {
4534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        pp::TouchInputEvent touches = pp::TouchInputEvent(event);
4544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        uint32_t count = touches.GetTouchCount(PP_TOUCHLIST_TYPE_TOUCHES);
4554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        // Touch points 0..n directly set position of points 0..n in
4564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        // Voronoi diagram.
4574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        for (uint32_t i = 0; i < count; i++) {
4584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          pp::TouchPoint touch =
4594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)              touches.GetTouchByIndex(PP_TOUCHLIST_TYPE_TOUCHES, i);
4604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          pp::FloatPoint point = touch.position();
4614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          positions_[i].Set(point.x() / ps_context_->width,
4624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            point.y() / ps_context_->height);
4634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        }
4644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        break;
4654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      }
4663240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      default:
4673240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch        break;
468868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
4693240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  } else if (ps_event->type == PSE_INSTANCE_HANDLEMESSAGE) {
4703240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    // Convert Pepper Simple message to PPAPI C++ var
4713240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    pp::Var var(ps_event->as_var);
4723240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    if (var.is_dictionary()) {
4733240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      pp::VarDictionary dictionary(var);
4743240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      std::string message = dictionary.Get("message").AsString();
4753240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      if (message == "run_benchmark" && !benchmarking_)
4763240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch       StartBenchmark();
4773240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      else if (message == "draw_points")
4783240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch        draw_points_ = dictionary.Get("value").AsBool();
4793240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      else if (message == "draw_interiors")
4803240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch        draw_interiors_ = dictionary.Get("value").AsBool();
4813240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      else if (message == "set_points") {
4823240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch        int num_points = dictionary.Get("value").AsInt();
4833240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch        point_count_ = std::min(kMaxPointCount, std::max(0, num_points));
4843240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      } else if (message == "set_threads") {
4853240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch        int thread_count = dictionary.Get("value").AsInt();
4863240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch        delete workers_;
4873240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch        workers_ = new ThreadPool(thread_count);
4883240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      }
489868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
490868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
491868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
492868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
493eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// PostUpdateMessage() helper function for sendimg small messages to JS.
494eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid Voronoi::PostUpdateMessage(const char* message_name, double value) {
495eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  pp::VarDictionary message;
496eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  message.Set("message", message_name);
497eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  message.Set("value", value);
4983240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  PSInterfaceMessaging()->PostMessage(PSGetInstanceId(), message.pp_var());
499868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
500868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
501868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void Voronoi::Update() {
5023240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  PSContext2DGetBuffer(ps_context_);
5033240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  if (NULL == ps_context_->data)
5043240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    return;
5053240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  assert(is_pow2(ps_context_->width));
5063240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  assert(is_pow2(ps_context_->height));
5073240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
5083240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // When benchmarking is running, don't update display via
5093240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // PSContext2DSwapBuffer() - vsync is enabled by default, and will throttle
5103240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // the benchmark results.
511868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  do {
512868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    UpdateSim();
513868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    Render();
514868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!benchmarking_) break;
515868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    --benchmark_frame_counter_;
516868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  } while (benchmark_frame_counter_ > 0);
517868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (benchmarking_)
518868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    EndBenchmark();
519868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
5203240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  PSContext2DSwapBuffer(ps_context_);
521868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
522868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
5233240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch// Starting point for the module.  We do not use main since it would
5243240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch// collide with main in libppapi_cpp.
5253240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochint example_main(int argc, char* argv[]) {
5263240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  Voronoi voronoi;
5273240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  while (true) {
5283240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    PSEvent* ps_event;
5293240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    // Consume all available events.
5303240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    while ((ps_event = PSEventTryAcquire()) != NULL) {
5313240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      voronoi.HandleEvent(ps_event);
5323240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      PSEventRelease(ps_event);
5333240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    }
5343240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    // Do simulation, render and present.
5353240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    voronoi.Update();
536868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
537868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
5383240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  return 0;
539868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
540868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
5413240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch// Register the function to call once the Instance Object is initialized.
5423240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch// see: pappi_simple/ps_main.h
5433240926e260ce088908e02ac07a6cf7b0c0cbf44Ben MurdochPPAPI_SIMPLE_REGISTER_MAIN(example_main);
544