Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2011 The Native Client SDK Authors. All rights reserved. | |
|
binji
2013/05/23 18:06:49
2013
noelallen1
2013/05/30 18:07:18
Done.
| |
| 2 // Use of this source code is governed by a BSD-style license that can | |
| 3 // be found in the LICENSE file. | |
| 4 | |
| 5 #include <assert.h> | |
| 6 #include <stdio.h> | |
| 7 #include <stdlib.h> | |
| 8 #include <string.h> | |
| 9 | |
| 10 #include "ppapi/c/pp_resource.h" | |
| 11 #include "ppapi/c/ppb_core.h" | |
| 12 #include "ppapi/c/ppb_graphics_2d.h" | |
| 13 #include "ppapi/c/ppb_image_data.h" | |
| 14 #include "ppapi/c/ppb_input_event.h" | |
| 15 #include "ppapi/c/ppb_instance.h" | |
| 16 #include "ppapi/c/ppb_view.h" | |
| 17 | |
| 18 #include "ppapi_simple/ppapi_event.h" | |
| 19 #include "ppapi_simple/ppapi_simple_main.h" | |
| 20 | |
| 21 PPB_Core* g_pCore; | |
| 22 PPB_Graphics2D* g_pGraphics2D; | |
| 23 PPB_ImageData* g_pImageData; | |
| 24 PPB_Instance* g_pInstance; | |
| 25 PPB_View* g_pView; | |
| 26 PPB_InputEvent* g_pInputEvent; | |
| 27 PPB_KeyboardInputEvent* g_pKeyboardInput; | |
| 28 PPB_MouseInputEvent* g_pMouseInput; | |
| 29 PPB_TouchInputEvent* g_pTouchInput; | |
| 30 | |
| 31 struct { | |
|
binji
2013/05/23 18:06:49
why store this is a struct instead of individual g
noelallen1
2013/05/23 22:01:24
Just for organization reasons.
| |
| 32 PP_Resource ctx_; | |
|
binji
2013/05/23 18:06:49
public members for structs don't have trailing _
noelallen1
2013/05/23 22:01:24
Done.
| |
| 33 struct PP_Size size_; | |
| 34 int bound_; | |
| 35 uint8_t* cell_in_; | |
| 36 uint8_t* cell_out_; | |
| 37 } g_Context; | |
| 38 | |
| 39 | |
| 40 const unsigned int kInitialRandSeed = 0xC0DE533D; | |
| 41 | |
| 42 #define MakeRGBA(r, g, b, a) \ | |
| 43 (((a) << 24) | ((r) << 16) | ((g) << 8) | (b)) | |
| 44 | |
| 45 // Map of neighboring colors. | |
|
binji
2013/05/23 18:06:49
these numbers seem pretty random. Maybe explain a
noelallen1
2013/05/23 22:01:24
Done.
| |
| 46 const uint32_t kNeighborColors[] = { | |
| 47 MakeRGBA(0x00, 0x00, 0x00, 0xff), | |
| 48 MakeRGBA(0x00, 0x40, 0x00, 0xff), | |
| 49 MakeRGBA(0x00, 0x60, 0x00, 0xff), | |
| 50 MakeRGBA(0x00, 0x80, 0x00, 0xff), | |
| 51 MakeRGBA(0x00, 0xA0, 0x00, 0xff), | |
| 52 MakeRGBA(0x00, 0xC0, 0x00, 0xff), | |
| 53 MakeRGBA(0x00, 0xE0, 0x00, 0xff), | |
| 54 MakeRGBA(0x00, 0x00, 0x00, 0xff), | |
| 55 MakeRGBA(0x00, 0x40, 0x00, 0xff), | |
| 56 MakeRGBA(0x00, 0x60, 0x00, 0xff), | |
| 57 MakeRGBA(0x00, 0x80, 0x00, 0xff), | |
| 58 MakeRGBA(0x00, 0xA0, 0x00, 0xff), | |
| 59 MakeRGBA(0x00, 0xC0, 0x00, 0xff), | |
| 60 MakeRGBA(0x00, 0xE0, 0x00, 0xff), | |
| 61 MakeRGBA(0x00, 0xFF, 0x00, 0xff), | |
| 62 MakeRGBA(0x00, 0xFF, 0x00, 0xff), | |
| 63 MakeRGBA(0x00, 0xFF, 0x00, 0xff), | |
| 64 MakeRGBA(0x00, 0xFF, 0x00, 0xff), | |
| 65 }; | |
| 66 | |
| 67 // These represent the new health value of a cell based on its neighboring | |
| 68 // values. The health is binary: either alive or dead. | |
| 69 const uint8_t kIsAlive[] = { | |
| 70 0, 0, 0, 1, 0, 0, 0, 0, 0, // Values if the center cell is dead. | |
| 71 0, 0, 1, 1, 0, 0, 0, 0, 0 // Values if the center cell is alive. | |
| 72 }; | |
| 73 | |
| 74 | |
| 75 void UpdateContext(uint32_t width, uint32_t height) { | |
| 76 size_t size = width * height; | |
| 77 size_t index; | |
| 78 | |
| 79 free(g_Context.cell_in_); | |
| 80 free(g_Context.cell_out_); | |
| 81 | |
| 82 // | |
| 83 // Create a new context | |
| 84 // | |
| 85 g_Context.cell_in_ = (uint8_t*) malloc(size); | |
| 86 g_Context.cell_out_ = (uint8_t*) malloc(size); | |
| 87 | |
| 88 memset(g_Context.cell_out_, 0, size); | |
| 89 for (index = 0; index < size; index++) { | |
| 90 g_Context.cell_in_[index] = rand() & 1; | |
| 91 } | |
| 92 } | |
| 93 | |
| 94 void ProcessEvent(PSEvent* event) { | |
| 95 static int mouse_down = 0; | |
|
binji
2013/05/23 18:06:49
unused
noelallen1
2013/05/23 22:01:24
Done.
| |
| 96 | |
| 97 switch(event->type_) { | |
| 98 /* If the view updates, build a new Graphics 2D Context */ | |
| 99 case PS_VIEW_EVENT: { | |
| 100 struct PP_Rect rect; | |
| 101 int32_t width; | |
| 102 int32_t height; | |
| 103 if (g_Context.ctx_) { | |
| 104 g_pCore->ReleaseResource(g_Context.ctx_); | |
| 105 g_Context.ctx_ = 0; | |
| 106 } | |
| 107 | |
| 108 g_pView->GetRect(event->resource_, &rect); | |
| 109 width = rect.size.width; | |
| 110 height = rect.size.height; | |
| 111 | |
| 112 if (width != g_Context.size_.width || height != g_Context.size_.height) { | |
| 113 UpdateContext(rect.size.width, rect.size.height); | |
| 114 } | |
| 115 if (width != g_Context.size_.width || height != g_Context.size_.height || | |
| 116 !g_Context.bound_) { | |
| 117 g_Context.ctx_ = | |
| 118 g_pGraphics2D->Create(PSGetInstanceId(), &rect.size, PP_TRUE); | |
| 119 g_Context.bound_ = | |
| 120 g_pInstance->BindGraphics(PSGetInstanceId(), g_Context.ctx_); | |
| 121 g_Context.size_ = rect.size; | |
| 122 } | |
| 123 break; | |
| 124 } | |
| 125 | |
| 126 case PS_INPUT_EVENT: { | |
|
nfullagar1
2013/05/23 21:58:36
I'm not super keen on how PS is defining a PS_INPU
noelallen1
2013/05/30 18:07:18
Done.
| |
| 127 PP_InputEvent_Type type = g_pInputEvent->GetType(event->resource_); | |
| 128 PP_InputEvent_Modifier modifiers = | |
| 129 g_pInputEvent->GetModifiers(event->resource_); | |
| 130 int32_t width = g_Context.size_.width; | |
| 131 int32_t height = g_Context.size_.height; | |
| 132 | |
| 133 switch(type) { | |
| 134 case PP_INPUTEVENT_TYPE_MOUSEMOVE: | |
| 135 { | |
| 136 struct PP_Point location = | |
| 137 g_pMouseInput->GetPosition(event->resource_); | |
| 138 | |
| 139 if (!g_Context.cell_in_) break; | |
| 140 | |
| 141 // If the button is down, draw | |
| 142 if (modifiers & PP_INPUTEVENT_MODIFIER_LEFTBUTTONDOWN) { | |
| 143 int x = location.x; | |
| 144 int y = location.y; | |
| 145 | |
| 146 if (x > 0 && x < width && y > 0 && y < height) { | |
|
binji
2013/05/23 18:06:49
x < width - 1
y < height - 1
noelallen1
2013/05/23 22:01:24
Done.
binji
2013/05/30 05:07:50
Missed this one.
noelallen1
2013/05/30 18:07:18
Done.
| |
| 147 g_Context.cell_in_[x-1 + y * width] = 1; | |
| 148 g_Context.cell_in_[x+1 + y * width] = 1; | |
| 149 g_Context.cell_in_[x + (y - 1) * width] = 1; | |
| 150 g_Context.cell_in_[x + (y + 1) * width] = 1; | |
| 151 } | |
| 152 } | |
| 153 } | |
| 154 break; | |
| 155 | |
| 156 case PP_INPUTEVENT_TYPE_KEYUP: { | |
| 157 if (g_pKeyboardInput->GetKeyCode(event->resource_) == 13) { | |
|
binji
2013/05/23 18:06:49
enter key
noelallen1
2013/05/30 18:07:18
Done.
| |
| 158 // PSToggleFullscreen(); | |
|
binji
2013/05/23 18:06:49
does this not work?
noelallen1
2013/05/23 22:01:24
Done.
| |
| 159 } | |
| 160 break; | |
| 161 } | |
| 162 | |
| 163 default: | |
| 164 break; | |
| 165 } | |
| 166 break; | |
| 167 } | |
| 168 | |
| 169 default: | |
| 170 break; | |
| 171 } | |
| 172 } | |
| 173 | |
| 174 | |
| 175 void Stir(uint32_t width, uint32_t height) { | |
| 176 int i; | |
| 177 if (g_Context.cell_in_ == NULL || g_Context.cell_out_ == NULL) | |
| 178 return; | |
| 179 | |
| 180 for (i = 0; i < width; ++i) { | |
| 181 g_Context.cell_in_[i] = rand() & 1; | |
|
binji
2013/05/23 18:06:49
probably not a big deal, but I always heard that t
| |
| 182 g_Context.cell_in_[i + (height - 1) * width] = rand() & 1; | |
| 183 } | |
| 184 for (i = 0; i < height; ++i) { | |
| 185 g_Context.cell_in_[i * width] = rand() & 1; | |
| 186 g_Context.cell_in_[i * width + (width - 1)] = rand() & 1; | |
| 187 } | |
| 188 } | |
| 189 | |
| 190 void Render() { | |
| 191 struct PP_Size* psize = &g_Context.size_; | |
| 192 PP_ImageDataFormat format = g_pImageData->GetNativeImageDataFormat(); | |
| 193 PP_Resource image = | |
| 194 g_pImageData->Create(PSGetInstanceId(), format, psize, PP_FALSE); | |
|
binji
2013/05/23 18:06:49
seems strange to create a new image every frame. M
noelallen1
2013/05/23 22:01:24
Done.
| |
| 195 uint8_t* pixels = g_pImageData->Map(image); | |
| 196 | |
| 197 struct PP_ImageDataDesc desc; | |
| 198 uint8_t* cell_temp; | |
| 199 uint32_t x, y; | |
| 200 | |
| 201 // If we somehow have not allocated these pointers yet, skip this frame. | |
| 202 if (!g_Context.cell_in_ || !g_Context.cell_out_) return; | |
| 203 | |
| 204 // Get the stride | |
| 205 g_pImageData->Describe(image, &desc); | |
|
nfullagar1
2013/05/23 21:58:36
For consistency, use the desc.size.width & height
noelallen1
2013/05/24 18:08:31
Done.
| |
| 206 | |
| 207 // Stir up the edges to prevent the simulation from reaching steady state. | |
| 208 Stir(psize->width, psize->height); | |
| 209 | |
| 210 // Do neighbor sumation; apply rules, output pixel color. | |
|
binji
2013/05/23 18:06:49
sp: summation
noelallen1
2013/05/23 22:01:24
Done.
| |
| 211 for (y = 1; y < (psize->height - 1); ++y) { | |
|
binji
2013/05/23 18:06:49
why ()?
noelallen1
2013/05/23 22:01:24
Done.
| |
| 212 uint8_t *src0 = (g_Context.cell_in_ + (y - 1) * psize->width) + 1; | |
| 213 uint8_t *src1 = src0 + psize->width; | |
| 214 uint8_t *src2 = src1 + psize->width; | |
| 215 int count; | |
| 216 uint32_t color; | |
| 217 uint8_t *dst = (g_Context.cell_out_ + (y) * psize->width) + 1; | |
|
binji
2013/05/23 18:06:49
why (y)?
noelallen1
2013/05/23 22:01:24
Done.
| |
| 218 uint32_t *pixel_line = (uint32_t*) (pixels + y * desc.stride); | |
| 219 | |
| 220 for (x = 1; x < (psize->width - 1); ++x) { | |
| 221 // Build sum, weight center by 9x. | |
| 222 count = src0[-1] + src0[0] + src0[1] + | |
| 223 src1[-1] + src1[0] * 9 + src1[1] + | |
| 224 src2[-1] + src2[0] + src2[1]; | |
| 225 color = kNeighborColors[count]; | |
| 226 | |
| 227 *pixel_line++ = color; | |
| 228 *dst++ = kIsAlive[count]; | |
| 229 ++src0; | |
| 230 ++src1; | |
| 231 ++src2; | |
| 232 } | |
| 233 } | |
| 234 | |
| 235 cell_temp = g_Context.cell_in_; | |
| 236 g_Context.cell_in_ = g_Context.cell_out_; | |
| 237 g_Context.cell_out_ = cell_temp; | |
| 238 | |
| 239 /* Unmap the range, we no longer need it. */ | |
| 240 g_pImageData->Unmap(image); | |
| 241 | |
| 242 /* Replace the contexts, and block until it's on the screen. */ | |
| 243 g_pGraphics2D->ReplaceContents(g_Context.ctx_, image); | |
| 244 g_pGraphics2D->Flush(g_Context.ctx_, PP_BlockUntilComplete()); | |
| 245 | |
| 246 /* Release the image data, we no longer need it. */ | |
| 247 g_pCore->ReleaseResource(image); | |
| 248 } | |
| 249 | |
| 250 | |
| 251 int my_main(int argc, const char *argv[]) { | |
|
binji
2013/05/23 18:06:49
might want to mention this can be called anything
noelallen1
2013/05/23 22:01:24
Done.
| |
| 252 fprintf(stdout,"Started main.\n"); | |
| 253 g_pCore = (PPB_Core*)PSGetInterface(PPB_CORE_INTERFACE); | |
| 254 g_pGraphics2D = (PPB_Graphics2D*)PSGetInterface(PPB_GRAPHICS_2D_INTERFACE); | |
| 255 g_pInstance = (PPB_Instance*)PSGetInterface(PPB_INSTANCE_INTERFACE); | |
| 256 g_pImageData = (PPB_ImageData*)PSGetInterface(PPB_IMAGEDATA_INTERFACE); | |
| 257 g_pView = (PPB_View*)PSGetInterface(PPB_VIEW_INTERFACE); | |
| 258 | |
| 259 g_pInputEvent = | |
| 260 (PPB_InputEvent*) PSGetInterface(PPB_INPUT_EVENT_INTERFACE); | |
| 261 g_pKeyboardInput = (PPB_KeyboardInputEvent*) | |
| 262 PSGetInterface(PPB_KEYBOARD_INPUT_EVENT_INTERFACE); | |
| 263 g_pMouseInput = | |
| 264 (PPB_MouseInputEvent*) PSGetInterface(PPB_MOUSE_INPUT_EVENT_INTERFACE); | |
| 265 g_pTouchInput = | |
|
binji
2013/05/23 18:06:49
unused
noelallen1
2013/05/30 18:07:18
Done.
| |
| 266 (PPB_TouchInputEvent*) PSGetInterface(PPB_TOUCH_INPUT_EVENT_INTERFACE); | |
| 267 | |
| 268 PSSetEventFilter(PS_ALL_EVENTS); | |
| 269 while (1) { | |
| 270 /* Process all waiting events without blocking */ | |
| 271 PSEvent* event; | |
| 272 while ((event = PSAcquireEvent(0)) != NULL) { | |
|
binji
2013/05/23 18:06:49
what is 0?
noelallen1
2013/05/23 22:01:24
Means don't block, see comment above.
| |
| 273 ProcessEvent(event); | |
| 274 PSReleaseEvent(event); | |
| 275 } | |
| 276 | |
| 277 /* Render a frame, blocking until complete. */ | |
| 278 if (g_Context.bound_) { | |
| 279 Render(); | |
| 280 } | |
| 281 } | |
| 282 return 0; | |
| 283 } | |
| 284 | |
|
nfullagar1
2013/05/23 21:58:36
How would this sample differ if PPAPI_SIMPLE_MAIN2
noelallen1
2013/05/24 18:08:31
The idea is that PPAPI_SIMPLE_MAIN2D would automat
| |
| 285 PPAPI_SIMPLE_MAIN(my_main); | |
|
binji
2013/05/23 18:06:49
what is this doing? Maybe a little comment.
noelallen1
2013/05/23 22:01:24
Done.
| |
| OLD | NEW |