Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(332)

Side by Side Diff: native_client_sdk/src/examples/demo/life/life.c

Issue 15011003: ppapi_simple (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Copyright Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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 */
5
6 #include <assert.h>
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10
11 #include "ppapi/c/pp_resource.h"
12 #include "ppapi/c/ppb_core.h"
13 #include "ppapi/c/ppb_fullscreen.h"
14 #include "ppapi/c/ppb_graphics_2d.h"
15 #include "ppapi/c/ppb_image_data.h"
16 #include "ppapi/c/ppb_input_event.h"
17 #include "ppapi/c/ppb_instance.h"
18 #include "ppapi/c/ppb_view.h"
19
20 #include "ppapi_simple/ps_event.h"
21 #include "ppapi_simple/ps_main.h"
22
23 PPB_Core* g_pCore;
24 PPB_Fullscreen* g_pFullscreen;
25 PPB_Graphics2D* g_pGraphics2D;
26 PPB_ImageData* g_pImageData;
27 PPB_Instance* g_pInstance;
28 PPB_View* g_pView;
29 PPB_InputEvent* g_pInputEvent;
30 PPB_KeyboardInputEvent* g_pKeyboardInput;
31 PPB_MouseInputEvent* g_pMouseInput;
32 PPB_TouchInputEvent* g_pTouchInput;
33
34 struct {
35 PP_Resource ctx;
36 struct PP_Size size;
37 int bound;
38 uint8_t* cell_in;
39 uint8_t* cell_out;
40 } g_Context;
41
42
43 const unsigned int kInitialRandSeed = 0xC0DE533D;
44
45 #define MakeRGBA(r, g, b, a) \
46 (((a) << 24) | ((r) << 16) | ((g) << 8) | (b))
47
48
49 /*
50 * Given a count of cells in a 3x3 grid where cells are worth 1 except for
51 * the center which is worth 9, this is a color representation of how
52 * "alive" that cell is making for a more interesting representation than
53 * a binary alive or dead.
54 */
55 const uint32_t kNeighborColors[] = {
56 MakeRGBA(0x00, 0x00, 0x00, 0xff),
57 MakeRGBA(0x00, 0x40, 0x00, 0xff),
58 MakeRGBA(0x00, 0x60, 0x00, 0xff),
59 MakeRGBA(0x00, 0x80, 0x00, 0xff),
60 MakeRGBA(0x00, 0xA0, 0x00, 0xff),
61 MakeRGBA(0x00, 0xC0, 0x00, 0xff),
62 MakeRGBA(0x00, 0xE0, 0x00, 0xff),
63 MakeRGBA(0x00, 0x00, 0x00, 0xff),
64 MakeRGBA(0x00, 0x40, 0x00, 0xff),
65 MakeRGBA(0x00, 0x60, 0x00, 0xff),
66 MakeRGBA(0x00, 0x80, 0x00, 0xff),
67 MakeRGBA(0x00, 0xA0, 0x00, 0xff),
68 MakeRGBA(0x00, 0xC0, 0x00, 0xff),
69 MakeRGBA(0x00, 0xE0, 0x00, 0xff),
70 MakeRGBA(0x00, 0xFF, 0x00, 0xff),
71 MakeRGBA(0x00, 0xFF, 0x00, 0xff),
72 MakeRGBA(0x00, 0xFF, 0x00, 0xff),
73 MakeRGBA(0x00, 0xFF, 0x00, 0xff),
74 };
75
76 /*
77 * These represent the new health value of a cell based on its neighboring
78 * values. The health is binary: either alive or dead.
79 */
80 const uint8_t kIsAlive[] = {
81 0, 0, 0, 1, 0, 0, 0, 0, 0, /* Values if the center cell is dead. */
82 0, 0, 1, 1, 0, 0, 0, 0, 0 /* Values if the center cell is alive. */
83 };
84
85 void UpdateContext(uint32_t width, uint32_t height) {
86 if (width != g_Context.size.width || height != g_Context.size.height) {
87 size_t size = width * height;
88 size_t index;
89
90 free(g_Context.cell_in);
91 free(g_Context.cell_out);
92
93 /* Create a new context */
94 g_Context.cell_in = (uint8_t*) malloc(size);
95 g_Context.cell_out = (uint8_t*) malloc(size);
96
97 memset(g_Context.cell_out, 0, size);
98 for (index = 0; index < size; index++) {
99 g_Context.cell_in[index] = rand() & 1;
100 }
101 }
102
103 /* Recreate the graphics context on a view change */
104 g_pCore->ReleaseResource(g_Context.ctx);
105 g_Context.size.width = width;
106 g_Context.size.height = height;
107 g_Context.ctx =
108 g_pGraphics2D->Create(PSGetInstanceId(), &g_Context.size, PP_TRUE);
109 g_Context.bound =
110 g_pInstance->BindGraphics(PSGetInstanceId(), g_Context.ctx);
111 }
112
113 void DrawCell(int32_t x, int32_t y) {
114 int32_t width = g_Context.size.width;
115 int32_t height = g_Context.size.height;
116
117 if (!g_Context.cell_in) return;
118
119 if (x > 0 && x < width - 1 && y > 0 && y < height - 1) {
120 g_Context.cell_in[x - 1 + y * width] = 1;
121 g_Context.cell_in[x + 1 + y * width] = 1;
122 g_Context.cell_in[x + (y - 1) * width] = 1;
123 g_Context.cell_in[x + (y + 1) * width] = 1;
124 }
125 }
126
127
128 void ProcessEvent(PSEvent* event) {
129 switch(event->type) {
130 /* If the view updates, build a new Graphics 2D Context */
131 case PSE_INSTANCE_DIDCHANGEVIEW: {
132 struct PP_Rect rect;
133
134 g_pView->GetRect(event->as_resource, &rect);
135 UpdateContext(rect.size.width, rect.size.height);
136 break;
137 }
138
139 case PSE_INSTANCE_HANDLEINPUT: {
140 PP_InputEvent_Type type = g_pInputEvent->GetType(event->as_resource);
141 PP_InputEvent_Modifier modifiers =
142 g_pInputEvent->GetModifiers(event->as_resource);
143
144 switch(type) {
145 case PP_INPUTEVENT_TYPE_MOUSEDOWN: {
146 struct PP_Point location =
147 g_pMouseInput->GetPosition(event->as_resource);
148 DrawCell(location.x, location.y);
149 break;
150 }
151
152 case PP_INPUTEVENT_TYPE_MOUSEMOVE: {
153 struct PP_Point location =
154 g_pMouseInput->GetPosition(event->as_resource);
155
156 /* If the button is down, draw */
157 if (modifiers & PP_INPUTEVENT_MODIFIER_LEFTBUTTONDOWN) {
158 DrawCell(location.x, location.y);
159 }
160 break;
161 }
162
163 case PP_INPUTEVENT_TYPE_KEYDOWN: {
164 PP_Bool fullscreen = g_pFullscreen->IsFullscreen(PSGetInstanceId());
165 g_pFullscreen->SetFullscreen(PSGetInstanceId(),
166 fullscreen ? PP_FALSE : PP_TRUE);
167 break;
168 }
169 default:
170 break;
171 }
172 /* case PSE_INSTANCE_HANDLEINPUT */
173 break;
174 }
175
176 default:
177 break;
178 }
179 }
180
181
182 void Stir(uint32_t width, uint32_t height) {
183 int i;
184 if (g_Context.cell_in == NULL || g_Context.cell_out == NULL)
185 return;
186
187 for (i = 0; i < width; ++i) {
188 g_Context.cell_in[i] = rand() & 1;
189 g_Context.cell_in[i + (height - 1) * width] = rand() & 1;
190 }
191 for (i = 0; i < height; ++i) {
192 g_Context.cell_in[i * width] = rand() & 1;
193 g_Context.cell_in[i * width + (width - 1)] = rand() & 1;
194 }
195 }
196
197 void Render() {
198 struct PP_Size* psize = &g_Context.size;
199 PP_ImageDataFormat format = g_pImageData->GetNativeImageDataFormat();
200
201 /*
202 * Create a buffer to draw into. Since we are waiting until the next flush
203 * chrome has an opportunity to cache this buffer see ppb_graphics_2d.h.
204 */
205 PP_Resource image =
206 g_pImageData->Create(PSGetInstanceId(), format, psize, PP_FALSE);
207 uint8_t* pixels = g_pImageData->Map(image);
208
209 struct PP_ImageDataDesc desc;
210 uint8_t* cell_temp;
211 uint32_t x, y;
212
213 /* If we somehow have not allocated these pointers yet, skip this frame. */
214 if (!g_Context.cell_in || !g_Context.cell_out) return;
215
216 /* Get the stride. */
217 g_pImageData->Describe(image, &desc);
218
219 /* Stir up the edges to prevent the simulation from reaching steady state. */
220 Stir(desc.size.width, desc.size.height);
221
222 /* Do neighbor summation; apply rules, output pixel color. */
223 for (y = 1; y < desc.size.height - 1; ++y) {
224 uint8_t *src0 = (g_Context.cell_in + (y - 1) * desc.size.width) + 1;
225 uint8_t *src1 = src0 + desc.size.width;
226 uint8_t *src2 = src1 + desc.size.width;
227 int count;
228 uint32_t color;
229 uint8_t *dst = (g_Context.cell_out + y * desc.size.width) + 1;
230 uint32_t *pixel_line = (uint32_t*) (pixels + y * desc.stride);
231
232 for (x = 1; x < (desc.size.width - 1); ++x) {
233 /* Build sum, weight center by 9x. */
234 count = src0[-1] + src0[0] + src0[1] +
235 src1[-1] + src1[0] * 9 + src1[1] +
236 src2[-1] + src2[0] + src2[1];
237 color = kNeighborColors[count];
238
239 *pixel_line++ = color;
240 *dst++ = kIsAlive[count];
241 ++src0;
242 ++src1;
243 ++src2;
244 }
245 }
246
247 cell_temp = g_Context.cell_in;
248 g_Context.cell_in = g_Context.cell_out;
249 g_Context.cell_out = cell_temp;
250
251 /* Unmap the range, we no longer need it. */
252 g_pImageData->Unmap(image);
253
254 /* Replace the contexts, and block until it's on the screen. */
255 g_pGraphics2D->ReplaceContents(g_Context.ctx, image);
256 g_pGraphics2D->Flush(g_Context.ctx, PP_BlockUntilComplete());
257
258 /* Release the image data, we no longer need it. */
259 g_pCore->ReleaseResource(image);
260 }
261
262 /*
263 * Starting point for the module. We do not use main since it would
264 * collide with main in libppapi_cpp.
265 */
266 int example_main(int argc, const char *argv[]) {
267 fprintf(stdout,"Started main.\n");
268 g_pCore = (PPB_Core*)PSGetInterface(PPB_CORE_INTERFACE);
269 g_pFullscreen = (PPB_Fullscreen*)PSGetInterface(PPB_FULLSCREEN_INTERFACE);
270 g_pGraphics2D = (PPB_Graphics2D*)PSGetInterface(PPB_GRAPHICS_2D_INTERFACE);
271 g_pInstance = (PPB_Instance*)PSGetInterface(PPB_INSTANCE_INTERFACE);
272 g_pImageData = (PPB_ImageData*)PSGetInterface(PPB_IMAGEDATA_INTERFACE);
273 g_pView = (PPB_View*)PSGetInterface(PPB_VIEW_INTERFACE);
274
275 g_pInputEvent =
276 (PPB_InputEvent*) PSGetInterface(PPB_INPUT_EVENT_INTERFACE);
277 g_pKeyboardInput = (PPB_KeyboardInputEvent*)
278 PSGetInterface(PPB_KEYBOARD_INPUT_EVENT_INTERFACE);
279 g_pMouseInput =
280 (PPB_MouseInputEvent*) PSGetInterface(PPB_MOUSE_INPUT_EVENT_INTERFACE);
281 g_pTouchInput =
282 (PPB_TouchInputEvent*) PSGetInterface(PPB_TOUCH_INPUT_EVENT_INTERFACE);
283
284 PSEventSetFilter(PSE_ALL);
285 while (1) {
286 /* Process all waiting events without blocking */
287 PSEvent* event;
288 while ((event = PSEventTryAcquire()) != NULL) {
289 ProcessEvent(event);
290 PSEventRelease(event);
291 }
292
293 /* Render a frame, blocking until complete. */
294 if (g_Context.bound) {
295 Render();
296 }
297 }
298 return 0;
299 }
300
301 /*
302 * Register the function to call once the Instance Object is initialized.
303 * see: pappi_simple/ps_main.h
304 */
305 PPAPI_SIMPLE_REGISTER_MAIN(example_main);
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698