Don't show supervised user as "already on this device" while they're being imported.
[chromium-blink-merge.git] / native_client_sdk / src / examples / demo / life / life.c
blob6bd28b543cff1c572e973ba6fdebf66b46d4c285
1 /* Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 * Use of this source code is governed by a BSD-style license that can be
3 * found in the LICENSE file.
4 */
6 #include <assert.h>
7 #include <math.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
12 #include "ppapi/c/pp_resource.h"
13 #include "ppapi/c/ppb_core.h"
14 #include "ppapi/c/ppb_fullscreen.h"
15 #include "ppapi/c/ppb_graphics_2d.h"
16 #include "ppapi/c/ppb_image_data.h"
17 #include "ppapi/c/ppb_input_event.h"
18 #include "ppapi/c/ppb_instance.h"
19 #include "ppapi/c/ppb_view.h"
21 #include "ppapi_simple/ps_event.h"
22 #include "ppapi_simple/ps_main.h"
24 PPB_Core* g_pCore;
25 PPB_Fullscreen* g_pFullscreen;
26 PPB_Graphics2D* g_pGraphics2D;
27 PPB_ImageData* g_pImageData;
28 PPB_Instance* g_pInstance;
29 PPB_View* g_pView;
30 PPB_InputEvent* g_pInputEvent;
31 PPB_KeyboardInputEvent* g_pKeyboardInput;
32 PPB_MouseInputEvent* g_pMouseInput;
33 PPB_TouchInputEvent* g_pTouchInput;
35 struct {
36 PP_Resource ctx;
37 struct PP_Size size;
38 int bound;
39 uint8_t* cell_in;
40 uint8_t* cell_out;
41 } g_Context;
44 const unsigned int kInitialRandSeed = 0xC0DE533D;
46 /* BGRA helper macro, for constructing a pixel for a BGRA buffer. */
47 #define MakeBGRA(b, g, r, a) \
48 (((a) << 24) | ((r) << 16) | ((g) << 8) | (b))
52 * Convert a count value into a live (green) or dead color value.
54 const uint32_t kNeighborColors[] = {
55 MakeBGRA(0x00, 0x00, 0x00, 0xFF),
56 MakeBGRA(0x00, 0x00, 0x00, 0xFF),
57 MakeBGRA(0x00, 0x00, 0x00, 0xFF),
58 MakeBGRA(0x00, 0x00, 0x00, 0xFF),
59 MakeBGRA(0x00, 0x00, 0x00, 0xFF),
60 MakeBGRA(0x00, 0xFF, 0x00, 0xFF),
61 MakeBGRA(0x00, 0xFF, 0x00, 0xFF),
62 MakeBGRA(0x00, 0xFF, 0x00, 0xFF),
63 MakeBGRA(0x00, 0x00, 0x00, 0xFF),
64 MakeBGRA(0x00, 0x00, 0x00, 0xFF),
65 MakeBGRA(0x00, 0x00, 0x00, 0xFF),
66 MakeBGRA(0x00, 0x00, 0x00, 0xFF),
67 MakeBGRA(0x00, 0x00, 0x00, 0xFF),
68 MakeBGRA(0x00, 0x00, 0x00, 0xFF),
69 MakeBGRA(0x00, 0x00, 0x00, 0xFF),
70 MakeBGRA(0x00, 0x00, 0x00, 0xFF),
71 MakeBGRA(0x00, 0x00, 0x00, 0xFF),
72 MakeBGRA(0x00, 0x00, 0x00, 0xFF),
76 * These represent the new health value of a cell based on its neighboring
77 * values. The health is binary: either alive or dead.
79 const uint8_t kIsAlive[] = {
80 0, 0, 0, 0, 0, 1, 1, 1, 0,
81 0, 0, 0, 0, 0, 0, 0, 0, 0
84 void UpdateContext(uint32_t width, uint32_t height) {
85 if (width != g_Context.size.width || height != g_Context.size.height) {
86 size_t size = width * height;
87 size_t index;
89 free(g_Context.cell_in);
90 free(g_Context.cell_out);
92 /* Create a new context */
93 g_Context.cell_in = (uint8_t*) malloc(size);
94 g_Context.cell_out = (uint8_t*) malloc(size);
96 memset(g_Context.cell_out, 0, size);
97 for (index = 0; index < size; index++) {
98 g_Context.cell_in[index] = rand() & 1;
102 /* Recreate the graphics context on a view change */
103 g_pCore->ReleaseResource(g_Context.ctx);
104 g_Context.size.width = width;
105 g_Context.size.height = height;
106 g_Context.ctx =
107 g_pGraphics2D->Create(PSGetInstanceId(), &g_Context.size, PP_TRUE);
108 g_Context.bound =
109 g_pInstance->BindGraphics(PSGetInstanceId(), g_Context.ctx);
112 void DrawCell(int32_t x, int32_t y) {
113 int32_t width = g_Context.size.width;
114 int32_t height = g_Context.size.height;
116 if (!g_Context.cell_in) return;
118 if (x > 0 && x < width - 1 && y > 0 && y < height - 1) {
119 g_Context.cell_in[x - 1 + y * width] = 1;
120 g_Context.cell_in[x + 1 + y * width] = 1;
121 g_Context.cell_in[x + (y - 1) * width] = 1;
122 g_Context.cell_in[x + (y + 1) * width] = 1;
126 void ProcessTouchEvent(PSEvent* event) {
127 uint32_t count = g_pTouchInput->GetTouchCount(event->as_resource,
128 PP_TOUCHLIST_TYPE_TOUCHES);
129 uint32_t i, j;
130 for (i = 0; i < count; i++) {
131 struct PP_TouchPoint touch = g_pTouchInput->GetTouchByIndex(
132 event->as_resource, PP_TOUCHLIST_TYPE_TOUCHES, i);
133 int radius = (int)touch.radius.x;
134 int x = (int)touch.position.x;
135 int y = (int)touch.position.y;
136 /* num = 1/100th the area of touch point */
137 int num = (int)(M_PI * radius * radius / 100.0f);
138 for (j = 0; j < num; j++) {
139 int dx = rand() % (radius * 2) - radius;
140 int dy = rand() % (radius * 2) - radius;
141 /* only plot random cells within the touch area */
142 if (dx * dx + dy * dy <= radius * radius)
143 DrawCell(x + dx, y + dy);
148 void ProcessEvent(PSEvent* event) {
149 switch(event->type) {
150 /* If the view updates, build a new Graphics 2D Context */
151 case PSE_INSTANCE_DIDCHANGEVIEW: {
152 struct PP_Rect rect;
154 g_pView->GetRect(event->as_resource, &rect);
155 UpdateContext(rect.size.width, rect.size.height);
156 break;
159 case PSE_INSTANCE_HANDLEINPUT: {
160 PP_InputEvent_Type type = g_pInputEvent->GetType(event->as_resource);
161 PP_InputEvent_Modifier modifiers =
162 g_pInputEvent->GetModifiers(event->as_resource);
164 switch(type) {
165 case PP_INPUTEVENT_TYPE_MOUSEDOWN:
166 case PP_INPUTEVENT_TYPE_MOUSEMOVE: {
167 struct PP_Point location =
168 g_pMouseInput->GetPosition(event->as_resource);
169 /* If the button is down, draw */
170 if (modifiers & PP_INPUTEVENT_MODIFIER_LEFTBUTTONDOWN) {
171 DrawCell(location.x, location.y);
173 break;
176 case PP_INPUTEVENT_TYPE_TOUCHSTART:
177 case PP_INPUTEVENT_TYPE_TOUCHMOVE:
178 ProcessTouchEvent(event);
179 break;
181 case PP_INPUTEVENT_TYPE_KEYDOWN: {
182 PP_Bool fullscreen = g_pFullscreen->IsFullscreen(PSGetInstanceId());
183 g_pFullscreen->SetFullscreen(PSGetInstanceId(),
184 fullscreen ? PP_FALSE : PP_TRUE);
185 break;
188 default:
189 break;
191 /* case PSE_INSTANCE_HANDLEINPUT */
192 break;
195 default:
196 break;
201 void Stir(uint32_t width, uint32_t height) {
202 int i;
203 if (g_Context.cell_in == NULL || g_Context.cell_out == NULL)
204 return;
206 for (i = 0; i < width; ++i) {
207 g_Context.cell_in[i] = rand() & 1;
208 g_Context.cell_in[i + (height - 1) * width] = rand() & 1;
210 for (i = 0; i < height; ++i) {
211 g_Context.cell_in[i * width] = rand() & 1;
212 g_Context.cell_in[i * width + (width - 1)] = rand() & 1;
216 void Render() {
217 struct PP_Size* psize = &g_Context.size;
218 PP_ImageDataFormat format = PP_IMAGEDATAFORMAT_BGRA_PREMUL;
221 * Create a buffer to draw into. Since we are waiting until the next flush
222 * chrome has an opportunity to cache this buffer see ppb_graphics_2d.h.
224 PP_Resource image =
225 g_pImageData->Create(PSGetInstanceId(), format, psize, PP_FALSE);
226 uint8_t* pixels = g_pImageData->Map(image);
228 struct PP_ImageDataDesc desc;
229 uint8_t* cell_temp;
230 uint32_t x, y;
232 /* If we somehow have not allocated these pointers yet, skip this frame. */
233 if (!g_Context.cell_in || !g_Context.cell_out) return;
235 /* Get the stride. */
236 g_pImageData->Describe(image, &desc);
238 /* Stir up the edges to prevent the simulation from reaching steady state. */
239 Stir(desc.size.width, desc.size.height);
241 /* Do neighbor summation; apply rules, output pixel color. */
242 for (y = 1; y < desc.size.height - 1; ++y) {
243 uint8_t *src0 = (g_Context.cell_in + (y - 1) * desc.size.width) + 1;
244 uint8_t *src1 = src0 + desc.size.width;
245 uint8_t *src2 = src1 + desc.size.width;
246 int count;
247 uint32_t color;
248 uint8_t *dst = (g_Context.cell_out + y * desc.size.width) + 1;
249 uint32_t *pixel_line = (uint32_t*) (pixels + y * desc.stride);
251 for (x = 1; x < (desc.size.width - 1); ++x) {
252 /* Jitter and sum neighbors. */
253 count = src0[-1] + src0[0] + src0[1] +
254 src1[-1] + + src1[1] +
255 src2[-1] + src2[0] + src2[1];
256 /* Include center cell. */
257 count = count + count + src1[0];
258 /* Use table lookup indexed by count to determine pixel & alive state. */
259 color = kNeighborColors[count];
260 *pixel_line++ = color;
261 *dst++ = kIsAlive[count];
262 ++src0;
263 ++src1;
264 ++src2;
268 cell_temp = g_Context.cell_in;
269 g_Context.cell_in = g_Context.cell_out;
270 g_Context.cell_out = cell_temp;
272 /* Unmap the range, we no longer need it. */
273 g_pImageData->Unmap(image);
275 /* Replace the contexts, and block until it's on the screen. */
276 g_pGraphics2D->ReplaceContents(g_Context.ctx, image);
277 g_pGraphics2D->Flush(g_Context.ctx, PP_BlockUntilComplete());
279 /* Release the image data, we no longer need it. */
280 g_pCore->ReleaseResource(image);
284 * Starting point for the module. We do not use main since it would
285 * collide with main in libppapi_cpp.
287 int example_main(int argc, char *argv[]) {
288 fprintf(stdout,"Started main.\n");
289 g_pCore = (PPB_Core*)PSGetInterface(PPB_CORE_INTERFACE);
290 g_pFullscreen = (PPB_Fullscreen*)PSGetInterface(PPB_FULLSCREEN_INTERFACE);
291 g_pGraphics2D = (PPB_Graphics2D*)PSGetInterface(PPB_GRAPHICS_2D_INTERFACE);
292 g_pInstance = (PPB_Instance*)PSGetInterface(PPB_INSTANCE_INTERFACE);
293 g_pImageData = (PPB_ImageData*)PSGetInterface(PPB_IMAGEDATA_INTERFACE);
294 g_pView = (PPB_View*)PSGetInterface(PPB_VIEW_INTERFACE);
296 g_pInputEvent =
297 (PPB_InputEvent*) PSGetInterface(PPB_INPUT_EVENT_INTERFACE);
298 g_pKeyboardInput = (PPB_KeyboardInputEvent*)
299 PSGetInterface(PPB_KEYBOARD_INPUT_EVENT_INTERFACE);
300 g_pMouseInput =
301 (PPB_MouseInputEvent*) PSGetInterface(PPB_MOUSE_INPUT_EVENT_INTERFACE);
302 g_pTouchInput =
303 (PPB_TouchInputEvent*) PSGetInterface(PPB_TOUCH_INPUT_EVENT_INTERFACE);
305 PSEventSetFilter(PSE_ALL);
306 while (1) {
307 /* Process all waiting events without blocking */
308 PSEvent* event;
309 while ((event = PSEventTryAcquire()) != NULL) {
310 ProcessEvent(event);
311 PSEventRelease(event);
314 /* Render a frame, blocking until complete. */
315 if (g_Context.bound) {
316 Render();
319 return 0;
323 * Register the function to call once the Instance Object is initialized.
324 * see: pappi_simple/ps_main.h
326 PPAPI_SIMPLE_REGISTER_MAIN(example_main);