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)
6868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include <assert.h>
74e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include <math.h>
8868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include <stdio.h>
9868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include <stdlib.h>
10868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include <string.h>
11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "ppapi/c/pp_resource.h"
13868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "ppapi/c/ppb_core.h"
14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "ppapi/c/ppb_fullscreen.h"
15868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "ppapi/c/ppb_graphics_2d.h"
16868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "ppapi/c/ppb_image_data.h"
17868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "ppapi/c/ppb_input_event.h"
18868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "ppapi/c/ppb_instance.h"
19868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "ppapi/c/ppb_view.h"
20868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
21868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "ppapi_simple/ps_event.h"
22868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "ppapi_simple/ps_main.h"
23868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
24868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)PPB_Core* g_pCore;
25868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)PPB_Fullscreen* g_pFullscreen;
26868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)PPB_Graphics2D* g_pGraphics2D;
27868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)PPB_ImageData* g_pImageData;
28868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)PPB_Instance* g_pInstance;
29868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)PPB_View* g_pView;
30868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)PPB_InputEvent* g_pInputEvent;
31868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)PPB_KeyboardInputEvent* g_pKeyboardInput;
32868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)PPB_MouseInputEvent* g_pMouseInput;
33868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)PPB_TouchInputEvent* g_pTouchInput;
34868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
35868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)struct {
36868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  PP_Resource ctx;
37868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  struct PP_Size size;
38868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int bound;
39868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  uint8_t* cell_in;
40868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  uint8_t* cell_out;
41868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} g_Context;
42868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
43868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
44868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)const unsigned int kInitialRandSeed = 0xC0DE533D;
45868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)/* BGRA helper macro, for constructing a pixel for a BGRA buffer. */
473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#define MakeBGRA(b, g, r, a)  \
48868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  (((a) << 24) | ((r) << 16) | ((g) << 8) | (b))
49868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
50868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
51868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)/*
52cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Convert a count value into a live (green) or dead color value.
53868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) */
54868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)const uint32_t kNeighborColors[] = {
55cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    MakeBGRA(0x00, 0x00, 0x00, 0xFF),
56cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    MakeBGRA(0x00, 0x00, 0x00, 0xFF),
57cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    MakeBGRA(0x00, 0x00, 0x00, 0xFF),
58cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    MakeBGRA(0x00, 0x00, 0x00, 0xFF),
59cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    MakeBGRA(0x00, 0x00, 0x00, 0xFF),
60cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    MakeBGRA(0x00, 0xFF, 0x00, 0xFF),
61cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    MakeBGRA(0x00, 0xFF, 0x00, 0xFF),
62cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    MakeBGRA(0x00, 0xFF, 0x00, 0xFF),
63cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    MakeBGRA(0x00, 0x00, 0x00, 0xFF),
64cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    MakeBGRA(0x00, 0x00, 0x00, 0xFF),
65cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    MakeBGRA(0x00, 0x00, 0x00, 0xFF),
66cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    MakeBGRA(0x00, 0x00, 0x00, 0xFF),
67cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    MakeBGRA(0x00, 0x00, 0x00, 0xFF),
68cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    MakeBGRA(0x00, 0x00, 0x00, 0xFF),
69cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    MakeBGRA(0x00, 0x00, 0x00, 0xFF),
70cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    MakeBGRA(0x00, 0x00, 0x00, 0xFF),
71cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    MakeBGRA(0x00, 0x00, 0x00, 0xFF),
72cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    MakeBGRA(0x00, 0x00, 0x00, 0xFF),
73868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)};
74868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
75868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)/*
76868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) * These represent the new health value of a cell based on its neighboring
77868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) * values.  The health is binary: either alive or dead.
78868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) */
79868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)const uint8_t kIsAlive[] = {
80cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      0, 0, 0, 0, 0, 1, 1, 1, 0,
81cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      0, 0, 0, 0, 0, 0, 0, 0, 0
82868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)};
83868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
84868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void UpdateContext(uint32_t width, uint32_t height) {
85868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (width != g_Context.size.width || height != g_Context.size.height) {
86868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    size_t size = width * height;
87868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    size_t index;
88868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
89868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    free(g_Context.cell_in);
90868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    free(g_Context.cell_out);
91868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
92868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    /* Create a new context */
93868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    g_Context.cell_in = (uint8_t*) malloc(size);
94868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    g_Context.cell_out = (uint8_t*) malloc(size);
95868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
96868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    memset(g_Context.cell_out, 0, size);
97868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    for (index = 0; index < size; index++) {
98868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      g_Context.cell_in[index] = rand() & 1;
99868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
100868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
101868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
102868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  /* Recreate the graphics context on a view change */
103868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  g_pCore->ReleaseResource(g_Context.ctx);
104868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  g_Context.size.width = width;
105868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  g_Context.size.height = height;
106868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  g_Context.ctx =
107868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      g_pGraphics2D->Create(PSGetInstanceId(), &g_Context.size, PP_TRUE);
108868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  g_Context.bound =
109868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      g_pInstance->BindGraphics(PSGetInstanceId(), g_Context.ctx);
110868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
111868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
112868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void DrawCell(int32_t x, int32_t y) {
113868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int32_t width = g_Context.size.width;
114868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int32_t height = g_Context.size.height;
115868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
116868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!g_Context.cell_in) return;
117868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
118868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (x > 0 && x < width - 1 && y > 0 && y < height - 1) {
119868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    g_Context.cell_in[x - 1 + y * width] = 1;
120868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    g_Context.cell_in[x + 1 + y * width] = 1;
121868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    g_Context.cell_in[x + (y - 1) * width] = 1;
122868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    g_Context.cell_in[x + (y + 1) * width] = 1;
123868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
124868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
125868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void ProcessTouchEvent(PSEvent* event) {
1274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  uint32_t count = g_pTouchInput->GetTouchCount(event->as_resource,
1284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      PP_TOUCHLIST_TYPE_TOUCHES);
1294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  uint32_t i, j;
1304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  for (i = 0; i < count; i++) {
1314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    struct PP_TouchPoint touch = g_pTouchInput->GetTouchByIndex(
1324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        event->as_resource, PP_TOUCHLIST_TYPE_TOUCHES, i);
1334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    int radius = (int)touch.radius.x;
1344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    int x = (int)touch.position.x;
1354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    int y = (int)touch.position.y;
1364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    /* num = 1/100th the area of touch point */
1374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    int num = (int)(M_PI * radius * radius / 100.0f);
1384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    for (j = 0; j < num; j++) {
1394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      int dx = rand() % (radius * 2) - radius;
1404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      int dy = rand() % (radius * 2) - radius;
1414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      /* only plot random cells within the touch area */
1424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      if (dx * dx + dy * dy <= radius * radius)
1434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        DrawCell(x + dx, y + dy);
1444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    }
1454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
1464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
147868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
148868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void ProcessEvent(PSEvent* event) {
149868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  switch(event->type) {
150868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    /* If the view updates, build a new Graphics 2D Context */
151868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    case PSE_INSTANCE_DIDCHANGEVIEW: {
152868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      struct PP_Rect rect;
153868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
154868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      g_pView->GetRect(event->as_resource, &rect);
155868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      UpdateContext(rect.size.width, rect.size.height);
156868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      break;
157868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
158868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
159868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    case PSE_INSTANCE_HANDLEINPUT: {
160868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      PP_InputEvent_Type type = g_pInputEvent->GetType(event->as_resource);
161868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      PP_InputEvent_Modifier modifiers =
162868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          g_pInputEvent->GetModifiers(event->as_resource);
163868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
164868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      switch(type) {
1654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        case PP_INPUTEVENT_TYPE_MOUSEDOWN:
1664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        case PP_INPUTEVENT_TYPE_MOUSEMOVE: {
167868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          struct PP_Point location =
168868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)              g_pMouseInput->GetPosition(event->as_resource);
1694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          /* If the button is down, draw */
1704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          if (modifiers & PP_INPUTEVENT_MODIFIER_LEFTBUTTONDOWN) {
1714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            DrawCell(location.x, location.y);
1724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          }
173868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          break;
174868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        }
175868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        case PP_INPUTEVENT_TYPE_TOUCHSTART:
1774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        case PP_INPUTEVENT_TYPE_TOUCHMOVE:
1784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          ProcessTouchEvent(event);
179868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          break;
180868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
181868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        case PP_INPUTEVENT_TYPE_KEYDOWN: {
182868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          PP_Bool fullscreen = g_pFullscreen->IsFullscreen(PSGetInstanceId());
183868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          g_pFullscreen->SetFullscreen(PSGetInstanceId(),
184868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                       fullscreen ? PP_FALSE : PP_TRUE);
185868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          break;
186868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        }
1874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
188868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        default:
189868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          break;
190868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      }
191868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      /* case PSE_INSTANCE_HANDLEINPUT */
192868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      break;
193868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
194868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
195868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    default:
196868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      break;
197868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
198868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
199868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
200868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
201868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void Stir(uint32_t width, uint32_t height) {
202868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int i;
203868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (g_Context.cell_in == NULL || g_Context.cell_out == NULL)
204868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
205868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
206868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  for (i = 0; i < width; ++i) {
207868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    g_Context.cell_in[i] = rand() & 1;
208868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    g_Context.cell_in[i + (height - 1) * width] = rand() & 1;
209868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
210868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  for (i = 0; i < height; ++i) {
211868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    g_Context.cell_in[i * width] = rand() & 1;
212868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    g_Context.cell_in[i * width + (width - 1)] = rand() & 1;
213868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
214868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
215868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
216868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void Render() {
217868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  struct PP_Size* psize = &g_Context.size;
21868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  PP_ImageDataFormat format = PP_IMAGEDATAFORMAT_BGRA_PREMUL;
219868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
220868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  /*
221868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)   * Create a buffer to draw into.  Since we are waiting until the next flush
222868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)   * chrome has an opportunity to cache this buffer see ppb_graphics_2d.h.
223868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)   */
224868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  PP_Resource image =
225868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      g_pImageData->Create(PSGetInstanceId(), format, psize, PP_FALSE);
226868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  uint8_t* pixels = g_pImageData->Map(image);
227868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
228868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  struct PP_ImageDataDesc desc;
229868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  uint8_t* cell_temp;
230868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  uint32_t x, y;
231868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
232868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  /* If we somehow have not allocated these pointers yet, skip this frame. */
233868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!g_Context.cell_in || !g_Context.cell_out) return;
234868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
235868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  /* Get the stride. */
236868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  g_pImageData->Describe(image, &desc);
237868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
238868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  /* Stir up the edges to prevent the simulation from reaching steady state. */
239868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Stir(desc.size.width, desc.size.height);
240868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
241868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  /* Do neighbor summation; apply rules, output pixel color. */
242868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  for (y = 1; y < desc.size.height - 1; ++y) {
243868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    uint8_t *src0 = (g_Context.cell_in + (y - 1) * desc.size.width) + 1;
244868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    uint8_t *src1 = src0 + desc.size.width;
245868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    uint8_t *src2 = src1 + desc.size.width;
246868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int count;
247868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    uint32_t color;
248868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    uint8_t *dst = (g_Context.cell_out + y * desc.size.width) + 1;
249868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    uint32_t *pixel_line =  (uint32_t*) (pixels + y * desc.stride);
250868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
251868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    for (x = 1; x < (desc.size.width - 1); ++x) {
252cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      /* Jitter and sum neighbors. */
253cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      count = src0[-1] + src0[0] + src0[1] +
254cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)              src1[-1] +         + src1[1] +
255cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)              src2[-1] + src2[0] + src2[1];
256cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      /* Include center cell. */
257cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      count = count + count + src1[0];
258cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      /* Use table lookup indexed by count to determine pixel & alive state. */
259868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      color = kNeighborColors[count];
260868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      *pixel_line++ = color;
261868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      *dst++ = kIsAlive[count];
262868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      ++src0;
263868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      ++src1;
264868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      ++src2;
265868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
266868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
267868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
268868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  cell_temp = g_Context.cell_in;
269868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  g_Context.cell_in = g_Context.cell_out;
270868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  g_Context.cell_out = cell_temp;
271868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
272868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  /* Unmap the range, we no longer need it. */
273868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  g_pImageData->Unmap(image);
274868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
275868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  /* Replace the contexts, and block until it's on the screen. */
276868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  g_pGraphics2D->ReplaceContents(g_Context.ctx, image);
277868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  g_pGraphics2D->Flush(g_Context.ctx, PP_BlockUntilComplete());
278868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
279868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  /* Release the image data, we no longer need it. */
280868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  g_pCore->ReleaseResource(image);
281868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
282868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
283868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)/*
284868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) * Starting point for the module.  We do not use main since it would
285868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) * collide with main in libppapi_cpp.
286868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) */
2877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)int example_main(int argc, char *argv[]) {
288868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  fprintf(stdout,"Started main.\n");
289868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  g_pCore = (PPB_Core*)PSGetInterface(PPB_CORE_INTERFACE);
290868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  g_pFullscreen = (PPB_Fullscreen*)PSGetInterface(PPB_FULLSCREEN_INTERFACE);
291868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  g_pGraphics2D = (PPB_Graphics2D*)PSGetInterface(PPB_GRAPHICS_2D_INTERFACE);
292868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  g_pInstance = (PPB_Instance*)PSGetInterface(PPB_INSTANCE_INTERFACE);
293868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  g_pImageData = (PPB_ImageData*)PSGetInterface(PPB_IMAGEDATA_INTERFACE);
294868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  g_pView = (PPB_View*)PSGetInterface(PPB_VIEW_INTERFACE);
295868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
296868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  g_pInputEvent =
297868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      (PPB_InputEvent*) PSGetInterface(PPB_INPUT_EVENT_INTERFACE);
298868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  g_pKeyboardInput = (PPB_KeyboardInputEvent*)
299868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      PSGetInterface(PPB_KEYBOARD_INPUT_EVENT_INTERFACE);
300868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  g_pMouseInput =
301868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      (PPB_MouseInputEvent*) PSGetInterface(PPB_MOUSE_INPUT_EVENT_INTERFACE);
302868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  g_pTouchInput =
303868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      (PPB_TouchInputEvent*) PSGetInterface(PPB_TOUCH_INPUT_EVENT_INTERFACE);
304868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
305868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  PSEventSetFilter(PSE_ALL);
306868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  while (1) {
307868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    /* Process all waiting events without blocking */
308868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    PSEvent* event;
309868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    while ((event = PSEventTryAcquire()) != NULL) {
310868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      ProcessEvent(event);
311868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      PSEventRelease(event);
312868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
313868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
314868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    /* Render a frame, blocking until complete. */
315868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (g_Context.bound) {
316868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      Render();
317868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
318868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
319868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return 0;
320868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
321868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
322868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)/*
323868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) * Register the function to call once the Instance Object is initialized.
324868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) * see: pappi_simple/ps_main.h
325868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) */
326868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)PPAPI_SIMPLE_REGISTER_MAIN(example_main);
327