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

Side by Side Diff: native_client_sdk/src/examples/api/graphics_3d/graphics_3d.cc

Issue 23838002: [NaCl SDK] Simplify graphics3d example. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: add stddef.h for offsetof Created 7 years, 3 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
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 //----------------------------------------------------------------------------- 5 #include <GLES2/gl2.h>
6 // The spinning Cube
7 //-----------------------------------------------------------------------------
8
9 #define _USE_MATH_DEFINES 1
10 #include <limits.h>
11 #include <math.h> 6 #include <math.h>
12 #include <stdarg.h>
13 #include <stddef.h> 7 #include <stddef.h>
8 #include <stdint.h>
14 #include <stdio.h> 9 #include <stdio.h>
15 #include <stdlib.h>
16 #include <string.h> 10 #include <string.h>
17 11
18 #include "ppapi/c/pp_completion_callback.h" 12 #include "matrix.h"
19 #include "ppapi/c/pp_errors.h" 13 #include "ppapi/cpp/graphics_3d.h"
20 #include "ppapi/c/pp_graphics_3d.h" 14 #include "ppapi/cpp/instance.h"
21 #include "ppapi/c/pp_module.h" 15 #include "ppapi/cpp/module.h"
22 #include "ppapi/c/pp_stdint.h" 16 #include "ppapi/cpp/var.h"
23 #include "ppapi/c/pp_var.h" 17 #include "ppapi/cpp/var_array.h"
24 #include "ppapi/c/ppb.h"
25 #include "ppapi/c/ppb_core.h"
26 #include "ppapi/c/ppb_graphics_3d.h"
27 #include "ppapi/c/ppb_instance.h"
28 #include "ppapi/c/ppb_messaging.h"
29 #include "ppapi/c/ppb_opengles2.h"
30 #include "ppapi/c/ppb_url_loader.h"
31 #include "ppapi/c/ppb_url_request_info.h"
32 #include "ppapi/c/ppb_var.h"
33 #include "ppapi/c/ppp.h"
34 #include "ppapi/c/ppp_instance.h"
35 #include "ppapi/c/ppp_messaging.h"
36
37 #include "ppapi/c/ppp_graphics_3d.h"
38 #include "ppapi/lib/gl/gles2/gl2ext_ppapi.h" 18 #include "ppapi/lib/gl/gles2/gl2ext_ppapi.h"
39 19 #include "ppapi/utility/completion_callback_factory.h"
40 #include <GLES2/gl2.h> 20
41 #include "matrix.h" 21 #ifdef WIN32
42 22 #undef PostMessage
43 static PPB_Messaging* ppb_messaging_interface = NULL; 23 // Allow 'this' in initializer list
44 static PPB_Var* ppb_var_interface = NULL; 24 #pragma warning(disable : 4355)
45 static PPB_Core* ppb_core_interface = NULL; 25 #endif
46 static PPB_Graphics3D* ppb_g3d_interface = NULL; 26
47 static PPB_Instance* ppb_instance_interface = NULL; 27 extern const uint8_t kRLETextureData[];
48 static PPB_URLRequestInfo* ppb_urlrequestinfo_interface = NULL; 28 extern const size_t kRLETextureDataLength;
49 static PPB_URLLoader* ppb_urlloader_interface = NULL; 29
50 30 namespace {
51 static PP_Instance g_instance; 31
52 static PP_Resource g_context; 32 const float kFovY = 45.0f;
53 33 const float kZNear = 1.0f;
54 GLuint g_positionLoc; 34 const float kZFar = 10.0f;
55 GLuint g_texCoordLoc; 35 const float kCameraZ = -4.0f;
56 GLuint g_colorLoc; 36 const float kXAngleDelta = 2.0f;
57 GLuint g_MVPLoc; 37 const float kYAngleDelta = 0.5f;
58 GLuint g_vboID; 38
59 GLuint g_ibID; 39 const size_t kTextureDataLength = 128 * 128 * 3; // 128x128, 3 Bytes/pixel.
60 GLubyte g_Indices[36]; 40
61 41 // The decompressed data is written here.
62 GLuint g_programObj; 42 uint8_t g_texture_data[kTextureDataLength];
63 GLuint g_vertexShader; 43
64 GLuint g_fragmentShader; 44 void DecompressTexture() {
65 45 // The image is first encoded with a very simple RLE scheme:
66 GLuint g_textureLoc = 0; 46 // <value0> <count0> <value1> <count1> ...
67 GLuint g_textureID = 0; 47 // Because a <count> of 0 is useless, we use it to represent 256.
68 48 //
69 float g_fSpinX = 0.0f; 49 // It is then Base64 encoded to make it use only printable characters (it
70 float g_fSpinY = 0.0f; 50 // stores more easily in a source file that way).
71 51 //
72 //----------------------------------------------------------------------------- 52 // To decompress, we have to reverse the process.
73 // Rendering Assets 53 static const uint8_t kBase64Decode[256] = {
74 //----------------------------------------------------------------------------- 54 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
75 struct Vertex { 55 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
76 float tu, tv; 56 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 0, 63,
77 float color[3]; 57 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0, 0, 0, 0, 0, 0,
78 float loc[3]; 58 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
79 }; 59 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, 0,
80 60 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
81 Vertex* g_quadVertices = NULL; 61 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
82 const char* g_TextureData = NULL; 62 };
83 const char* g_VShaderData = NULL; 63 const uint8_t* input = &kRLETextureData[0];
84 const char* g_FShaderData = NULL; 64 const uint8_t * const input_end = &kRLETextureData[kRLETextureDataLength];
85 int g_LoadCnt = 0; 65 uint8_t* output = &g_texture_data[0];
86 66 const uint8_t * const output_end = &g_texture_data[kTextureDataLength];
87 //----------------------------------------------------------------------------- 67
88 // PROTOTYPES 68 uint8_t decoded[4];
89 //----------------------------------------------------------------------------- 69 int decoded_count = 0;
90 void PostMessage(const char* fmt, ...); 70
91 char* LoadFile(const char* fileName); 71 while (input < input_end || decoded_count > 0) {
92 72 if (decoded_count < 2) {
93 void BuildQuad(Vertex* verts, int axis[3], float depth, float color[3]); 73 assert(input + 4 <= input_end);
94 Vertex* BuildCube(void); 74 // Grab four base-64 encoded (6-bit) bytes.
95 75 uint32_t data = 0;
96 void InitGL(void); 76 data |= (kBase64Decode[*input++] << 18);
97 void InitProgram(void); 77 data |= (kBase64Decode[*input++] << 12);
98 void Render(void); 78 data |= (kBase64Decode[*input++] << 6);
99 79 data |= (kBase64Decode[*input++] );
100 static struct PP_Var CStrToVar(const char* str) { 80 // And decode it to 3 (8-bit) bytes.
101 if (ppb_var_interface != NULL) { 81 decoded[decoded_count++] = (data >> 16) & 0xff;
102 return ppb_var_interface->VarFromUtf8(str, strlen(str)); 82 decoded[decoded_count++] = (data >> 8) & 0xff;
103 } 83 decoded[decoded_count++] = (data ) & 0xff;
104 return PP_MakeUndefined(); 84
85 // = is the base64 end marker. Remove decoded bytes if we see any.
86 if (input[-1] == '=') decoded_count--;
87 if (input[-2] == '=') decoded_count--;
88 }
89
90 int value = decoded[0];
91 int count = decoded[1];
92 decoded_count -= 2;
93 // Move the other decoded bytes (if any) down.
94 decoded[0] = decoded[2];
95 decoded[1] = decoded[3];
96
97 // Expand the RLE data.
98 if (count == 0)
99 count = 256;
100 assert(output <= output_end);
101 memset(output, value, count);
102 output += count;
103 }
104 assert(output == output_end);
105 } 105 }
106 106
107 void PostMessage(const char* fmt, ...) { 107 GLuint CompileShader(GLenum type, const char* data) {
108 va_list args;
109 va_start(args, fmt);
110
111 char msg[4096];
112 vsnprintf(msg, sizeof(msg), fmt, args);
113
114 if (ppb_messaging_interface)
115 ppb_messaging_interface->PostMessage(g_instance, CStrToVar(msg));
116
117 va_end(args);
118 }
119
120 void MainLoop(void* foo, int bar) {
121 if (g_LoadCnt == 3) {
122 InitProgram();
123 g_LoadCnt++;
124 }
125 if (g_LoadCnt > 3) {
126 Render();
127 PP_CompletionCallback cc = PP_MakeCompletionCallback(MainLoop, 0);
128 ppb_g3d_interface->SwapBuffers(g_context, cc);
129 } else {
130 PP_CompletionCallback cc = PP_MakeCompletionCallback(MainLoop, 0);
131 ppb_core_interface->CallOnMainThread(0, cc, 0);
132 }
133 }
134
135 void InitGL(void) {
136 int32_t attribs[] = {
137 PP_GRAPHICS3DATTRIB_ALPHA_SIZE, 8,
138 PP_GRAPHICS3DATTRIB_DEPTH_SIZE, 24,
139 PP_GRAPHICS3DATTRIB_STENCIL_SIZE, 8,
140 PP_GRAPHICS3DATTRIB_SAMPLES, 0,
141 PP_GRAPHICS3DATTRIB_SAMPLE_BUFFERS, 0,
142 PP_GRAPHICS3DATTRIB_WIDTH, 640,
143 PP_GRAPHICS3DATTRIB_HEIGHT, 480,
144 PP_GRAPHICS3DATTRIB_NONE
145 };
146
147 g_context = ppb_g3d_interface->Create(g_instance, 0, attribs);
148 int32_t success = ppb_instance_interface->BindGraphics(g_instance, g_context);
149 if (success == PP_FALSE) {
150 glSetCurrentContextPPAPI(0);
151 printf("Failed to set context.\n");
152 return;
153 }
154 glSetCurrentContextPPAPI(g_context);
155
156 glViewport(0, 0, 640, 480);
157 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
158 }
159
160 GLuint compileShader(GLenum type, const char* data) {
161 const char* shaderStrings[1];
162 shaderStrings[0] = data;
163
164 GLuint shader = glCreateShader(type); 108 GLuint shader = glCreateShader(type);
165 glShaderSource(shader, 1, shaderStrings, NULL); 109 glShaderSource(shader, 1, &data, NULL);
166 glCompileShader(shader); 110 glCompileShader(shader);
111
112 GLint compile_status;
113 glGetShaderiv(shader, GL_COMPILE_STATUS, &compile_status);
114 if (compile_status != GL_TRUE) {
115 // Shader failed to compile, let's see what the error is.
116 char buffer[1024];
117 GLsizei length;
118 glGetShaderInfoLog(shader, 1024, &length, &buffer[0]);
noelallen1 2013/09/03 20:55:25 1024 vs sizeof(buffer)?
119 fprintf(stderr, "Shader failed to compile: %s\n", buffer);
120 return 0;
121 }
122
167 return shader; 123 return shader;
168 } 124 }
169 125
170 void InitProgram(void) { 126 GLuint LinkProgram(GLuint frag_shader, GLuint vert_shader) {
171 glSetCurrentContextPPAPI(g_context); 127 GLuint program = glCreateProgram();
172 128 glAttachShader(program, frag_shader);
173 g_vertexShader = compileShader(GL_VERTEX_SHADER, g_VShaderData); 129 glAttachShader(program, vert_shader);
174 g_fragmentShader = compileShader(GL_FRAGMENT_SHADER, g_FShaderData); 130 glLinkProgram(program);
175 131
176 g_programObj = glCreateProgram(); 132 GLint link_status;
177 glAttachShader(g_programObj, g_vertexShader); 133 glGetProgramiv(program, GL_LINK_STATUS, &link_status);
178 glAttachShader(g_programObj, g_fragmentShader); 134 if (link_status != GL_TRUE) {
179 glLinkProgram(g_programObj); 135 // Program failed to link, let's see what the error is.
180 136 char buffer[1024];
181 glGenBuffers(1, &g_vboID); 137 GLsizei length;
182 glBindBuffer(GL_ARRAY_BUFFER, g_vboID); 138 glGetProgramInfoLog(program, 1024, &length, &buffer[0]);
noelallen1 2013/09/03 20:55:25 same
183 glBufferData(GL_ARRAY_BUFFER, 139 fprintf(stderr, "Program failed to link: %s\n", buffer);
184 24 * sizeof(Vertex), 140 return 0;
185 (void*)&g_quadVertices[0], 141 }
186 GL_STATIC_DRAW); 142
187 143 return program;
188 glGenBuffers(1, &g_ibID);
189 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_ibID);
190 glBufferData(GL_ELEMENT_ARRAY_BUFFER,
191 36 * sizeof(char),
192 (void*)&g_Indices[0],
193 GL_STATIC_DRAW);
194
195 //
196 // Create a texture to test out our fragment shader...
197 //
198 glGenTextures(1, &g_textureID);
199 glBindTexture(GL_TEXTURE_2D, g_textureID);
200 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
201 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
202 glTexImage2D(GL_TEXTURE_2D,
203 0,
204 GL_RGB,
205 128,
206 128,
207 0,
208 GL_RGB,
209 GL_UNSIGNED_BYTE,
210 g_TextureData);
211
212 //
213 // Locate some parameters by name so we can set them later...
214 //
215 g_textureLoc = glGetUniformLocation(g_programObj, "arrowTexture");
216 g_positionLoc = glGetAttribLocation(g_programObj, "a_position");
217 g_texCoordLoc = glGetAttribLocation(g_programObj, "a_texCoord");
218 g_colorLoc = glGetAttribLocation(g_programObj, "a_color");
219 g_MVPLoc = glGetUniformLocation(g_programObj, "a_MVP");
220 } 144 }
221 145
222 void BuildQuad(Vertex* verts, int axis[3], float depth, float color[3]) { 146 const char kFragShaderSource[] =
223 static float X[4] = { -1.0f, 1.0f, 1.0f, -1.0f }; 147 "precision mediump float;\n"
224 static float Y[4] = { -1.0f, -1.0f, 1.0f, 1.0f }; 148 "varying vec3 v_color;\n"
225 149 "varying vec2 v_texcoord;\n"
226 for (int i = 0; i < 4; i++) { 150 "uniform sampler2D u_texture;\n"
227 verts[i].tu = (1.0 - X[i]) / 2.0f; 151 "void main() {\n"
228 verts[i].tv = (Y[i] + 1.0f) / -2.0f * depth; 152 " gl_FragColor = texture2D(u_texture, v_texcoord);\n"
229 verts[i].loc[axis[0]] = X[i] * depth; 153 " gl_FragColor += vec4(v_color, 1);\n"
230 verts[i].loc[axis[1]] = Y[i] * depth; 154 "}\n";
231 verts[i].loc[axis[2]] = depth; 155
232 for (int j = 0; j < 3; j++) 156 const char kVertexShaderSource[] =
233 verts[i].color[j] = color[j] * (Y[i] + 1.0f) / 2.0f; 157 "uniform mat4 u_mvp;\n"
234 } 158 "attribute vec2 a_texcoord;\n"
235 } 159 "attribute vec3 a_color;\n"
236 160 "attribute vec4 a_position;\n"
237 Vertex* BuildCube() { 161 "varying vec3 v_color;\n"
238 Vertex* verts = new Vertex[24]; 162 "varying vec2 v_texcoord;\n"
239 for (int i = 0; i < 3; i++) { 163 "void main() {\n"
240 int Faxis[3]; 164 " gl_Position = u_mvp * a_position;\n"
241 int Baxis[3]; 165 " v_color = a_color;\n"
242 float Fcolor[3]; 166 " v_texcoord = a_texcoord;\n"
243 float Bcolor[3]; 167 "}\n";
244 for (int j = 0; j < 3; j++) { 168
245 Faxis[j] = (j + i) % 3; 169 struct Vertex {
246 Baxis[j] = (j + i) % 3; 170 float loc[3];
247 } 171 float color[3];
248 memset(Fcolor, 0, sizeof(float) * 3); 172 float tex[2];
249 memset(Bcolor, 0, sizeof(float) * 3);
250 Fcolor[i] = 0.5f;
251 Bcolor[i] = 1.0f;
252 BuildQuad(&verts[0 + i * 4], Faxis, 1.0f, Fcolor);
253 BuildQuad(&verts[12 + i * 4], Baxis, -1.0f, Bcolor);
254 }
255
256 for (int i = 0; i < 6; i++) {
257 g_Indices[i * 6 + 0] = 2 + i * 4;
258 g_Indices[i * 6 + 1] = 1 + i * 4;
259 g_Indices[i * 6 + 2] = 0 + i * 4;
260 g_Indices[i * 6 + 3] = 3 + i * 4;
261 g_Indices[i * 6 + 4] = 2 + i * 4;
262 g_Indices[i * 6 + 5] = 0 + i * 4;
263 }
264 return verts;
265 }
266
267 void Render(void) {
268 static float xRot = 0.0;
269 static float yRot = 0.0;
270
271 xRot += 2.0f;
272 yRot += 0.5f;
273 if (xRot >= 360.0f)
274 xRot = 0.0;
275 if (yRot >= 360.0f)
276 yRot = 0.0;
277
278 glClearColor(0.5, 0.5, 0.5, 1);
279 glClearDepthf(1.0);
280 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
281 glEnable(GL_DEPTH_TEST);
282
283 //set what program to use
284 glUseProgram(g_programObj);
285 glActiveTexture(GL_TEXTURE0);
286 glBindTexture(GL_TEXTURE_2D, g_textureID);
287 glUniform1i(g_textureLoc, 0);
288
289 //create our perspective matrix
290 float mpv[16];
291 float trs[16];
292 float rot[16];
293
294 identity_matrix(mpv);
295 glhPerspectivef2(&mpv[0], 45.0f, 640.0f / 480.0f, 1, 10);
296
297 translate_matrix(0, 0, -4.0, trs);
298 rotate_matrix(xRot, yRot, 0.0f, rot);
299 multiply_matrix(trs, rot, trs);
300 multiply_matrix(mpv, trs, mpv);
301 glUniformMatrix4fv(g_MVPLoc, 1, GL_FALSE, (GLfloat*)mpv);
302
303 //define the attributes of the vertex
304 glBindBuffer(GL_ARRAY_BUFFER, g_vboID);
305 glVertexAttribPointer(g_positionLoc,
306 3,
307 GL_FLOAT,
308 GL_FALSE,
309 sizeof(Vertex),
310 (void*)offsetof(Vertex, loc));
311 glEnableVertexAttribArray(g_positionLoc);
312 glVertexAttribPointer(g_texCoordLoc,
313 2,
314 GL_FLOAT,
315 GL_FALSE,
316 sizeof(Vertex),
317 (void*)offsetof(Vertex, tu));
318 glEnableVertexAttribArray(g_texCoordLoc);
319 glVertexAttribPointer(g_colorLoc,
320 3,
321 GL_FLOAT,
322 GL_FALSE,
323 sizeof(Vertex),
324 (void*)offsetof(Vertex, color));
325 glEnableVertexAttribArray(g_colorLoc);
326
327 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_ibID);
328 glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_BYTE, 0);
329 }
330
331 typedef void (*OpenCB)(void* dataPtr);
332 struct OpenRequest {
333 PP_Resource loader_;
334 PP_Resource request_;
335 char* buf_;
336 void* data_;
337 int64_t size_;
338 int64_t avail_;
339 OpenCB cb_;
340 }; 173 };
341 174
342 void FreeRequest(OpenRequest* req) { 175 const Vertex kCubeVerts[24] = {
343 if (req) { 176 // +Z (red arrow, black tip)
344 ppb_core_interface->ReleaseResource(req->request_); 177 {{-1.0, -1.0, +1.0}, {0.0, 0.0, 0.0}, {1.0, 0.0}},
345 ppb_core_interface->ReleaseResource(req->loader_); 178 {{+1.0, -1.0, +1.0}, {0.0, 0.0, 0.0}, {0.0, 0.0}},
346 free(req); 179 {{+1.0, +1.0, +1.0}, {0.5, 0.0, 0.0}, {0.0, 1.0}},
347 } 180 {{-1.0, +1.0, +1.0}, {0.5, 0.0, 0.0}, {1.0, 1.0}},
348 } 181
349 182 // +X (green arrow, black tip)
350 static void URLPartialRead(void* user_data, int mode) { 183 {{+1.0, -1.0, -1.0}, {0.0, 0.0, 0.0}, {1.0, 0.0}},
351 OpenRequest* req = (OpenRequest*)user_data; 184 {{+1.0, +1.0, -1.0}, {0.0, 0.0, 0.0}, {0.0, 0.0}},
352 int64_t total; 185 {{+1.0, +1.0, +1.0}, {0.0, 0.5, 0.0}, {0.0, 1.0}},
353 int32_t cnt; 186 {{+1.0, -1.0, +1.0}, {0.0, 0.5, 0.0}, {1.0, 1.0}},
354 187
355 if (mode < 0) { 188 // +Y (blue arrow, black tip)
356 free(req->buf_); 189 {{-1.0, +1.0, -1.0}, {0.0, 0.0, 0.0}, {1.0, 0.0}},
357 req->cb_(NULL); 190 {{-1.0, +1.0, +1.0}, {0.0, 0.0, 0.0}, {0.0, 0.0}},
358 FreeRequest(req); 191 {{+1.0, +1.0, +1.0}, {0.0, 0.0, 0.5}, {0.0, 1.0}},
359 return; 192 {{+1.0, +1.0, -1.0}, {0.0, 0.0, 0.5}, {1.0, 1.0}},
360 } 193
361 194 // -Z (red arrow, red tip)
362 req->avail_ += mode; 195 {{+1.0, +1.0, -1.0}, {0.0, 0.0, 0.0}, {1.0, 1.0}},
363 total = req->size_ - req->avail_; 196 {{-1.0, +1.0, -1.0}, {0.0, 0.0, 0.0}, {0.0, 1.0}},
364 197 {{-1.0, -1.0, -1.0}, {1.0, 0.0, 0.0}, {0.0, 0.0}},
365 cnt = (total > LONG_MAX) ? LONG_MAX : (int32_t) total; 198 {{+1.0, -1.0, -1.0}, {1.0, 0.0, 0.0}, {1.0, 0.0}},
366 // If we still have more to do, re-issue the read. 199
367 if (cnt > 0) { 200 // -X (green arrow, green tip)
368 int32_t bytes = ppb_urlloader_interface->ReadResponseBody( 201 {{-1.0, +1.0, +1.0}, {0.0, 0.0, 0.0}, {1.0, 1.0}},
369 req->loader_, 202 {{-1.0, -1.0, +1.0}, {0.0, 0.0, 0.0}, {0.0, 1.0}},
370 (void*)&req->buf_[req->avail_], 203 {{-1.0, -1.0, -1.0}, {0.0, 1.0, 0.0}, {0.0, 0.0}},
371 cnt, 204 {{-1.0, +1.0, -1.0}, {0.0, 1.0, 0.0}, {1.0, 0.0}},
372 PP_MakeCompletionCallback(URLPartialRead, req)); 205
373 206 // -Y (blue arrow, blue tip)
374 // If the reissue completes immediately, then process it. 207 {{+1.0, -1.0, +1.0}, {0.0, 0.0, 0.0}, {1.0, 1.0}},
375 if (bytes != PP_OK_COMPLETIONPENDING) { 208 {{+1.0, -1.0, -1.0}, {0.0, 0.0, 0.0}, {0.0, 1.0}},
376 URLPartialRead(user_data, bytes); 209 {{-1.0, -1.0, -1.0}, {0.0, 0.0, 1.0}, {0.0, 0.0}},
377 } 210 {{-1.0, -1.0, +1.0}, {0.0, 0.0, 1.0}, {1.0, 0.0}},
378 return; 211 };
379 } 212
380 213 const GLubyte kCubeIndexes[36] = {
381 // Nothing left, so signal complete. 214 2, 1, 0, 3, 2, 0,
382 req->cb_(req); 215 6, 5, 4, 7, 6, 4,
383 FreeRequest(req); 216 10, 9, 8, 11, 10, 8,
384 printf("Loaded\n"); 217 14, 13, 12, 15, 14, 12,
385 } 218 18, 17, 16, 19, 18, 16,
386 219 22, 21, 20, 23, 22, 20,
387 static void URLOpened(void* user_data, int mode) { 220 };
388 OpenRequest* req = (OpenRequest*)user_data; 221
389 222 } // namespace
390 int64_t cur, total; 223
391 int32_t cnt; 224
392 ppb_urlloader_interface->GetDownloadProgress(req->loader_, &cur, &total); 225 class Graphics3DInstance : public pp::Instance {
393 226 public:
394 // If we can't preallocate the buffer because the size is unknown, then 227 explicit Graphics3DInstance(PP_Instance instance)
395 // fail the load. 228 : pp::Instance(instance),
396 if (total == -1) { 229 callback_factory_(this),
397 req->cb_(NULL); 230 width_(0),
398 FreeRequest(req); 231 height_(0),
399 return; 232 frag_shader_(0),
400 } 233 vertex_shader_(0),
401 234 program_(0),
402 // Otherwise allocate a buffer with enough space for a terminating 235 texture_loc_(0),
403 // NULL in case we need one. 236 position_loc_(0),
404 cnt = (total > LONG_MAX) ? LONG_MAX : (int32_t) total; 237 color_loc_(0),
405 req->buf_ = (char*)malloc(cnt + 1); 238 mvp_loc_(0),
406 req->buf_[cnt] = 0; 239 x_angle_(0),
407 req->size_ = cnt; 240 y_angle_(0),
408 int32_t bytes = ppb_urlloader_interface->ReadResponseBody( 241 animating_(true) {}
409 req->loader_, 242
410 req->buf_, 243 virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]) {
411 cnt, 244 return true;
412 PP_MakeCompletionCallback(URLPartialRead, req)); 245 }
413 246
414 // Usually we are pending. 247 virtual void DidChangeView(const pp::View& view) {
415 if (bytes == PP_OK_COMPLETIONPENDING) 248 int32_t new_width = view.GetRect().width();
416 return; 249 int32_t new_height = view.GetRect().height();
417 250
418 // But if we did complete the read, then dispatch the handler. 251 if (context_.is_null()) {
419 URLPartialRead(req, bytes); 252 if (!InitGL(new_width, new_height)) {
420 } 253 // failed.
421 254 return;
422 void LoadURL(PP_Instance inst, const char* url, OpenCB cb, void* data) { 255 }
423 OpenRequest* req = (OpenRequest*)malloc(sizeof(OpenRequest)); 256
424 memset(req, 0, sizeof(OpenRequest)); 257 InitShaders();
425 258 InitBuffers();
426 req->loader_ = ppb_urlloader_interface->Create(inst); 259 InitTexture();
427 req->request_ = ppb_urlrequestinfo_interface->Create(inst); 260 MainLoop(0);
428 req->cb_ = cb; 261 } else {
429 req->data_ = data; 262 // Resize the buffers to the new size of the module.
430 263 int32_t result = context_.ResizeBuffers(new_width, new_height);
431 if (!req->loader_ || !req->request_) { 264 if (result < 0) {
432 cb(NULL); 265 fprintf(stderr,
433 FreeRequest(req); 266 "Unable to resize buffers to %d x %d!\n",
434 return; 267 new_width,
435 } 268 new_height);
436 269 return;
437 ppb_urlrequestinfo_interface->SetProperty( 270 }
438 req->request_, PP_URLREQUESTPROPERTY_URL, CStrToVar(url)); 271 }
439 ppb_urlrequestinfo_interface->SetProperty( 272
440 req->request_, PP_URLREQUESTPROPERTY_METHOD, CStrToVar("GET")); 273 width_ = new_width;
441 ppb_urlrequestinfo_interface->SetProperty( 274 height_ = new_height;
442 req->request_, 275 glViewport(0, 0, width_, height_);
443 PP_URLREQUESTPROPERTY_RECORDDOWNLOADPROGRESS, 276 }
444 PP_MakeBool(PP_TRUE)); 277
445 278 virtual void HandleMessage(const pp::Var& message) {
446 int val = ppb_urlloader_interface->Open( 279 // A bool message sets whether the cube is animating or not.
447 req->loader_, req->request_, PP_MakeCompletionCallback(URLOpened, req)); 280 if (message.is_bool()) {
448 281 animating_ = message.AsBool();
449 if (val != PP_OK_COMPLETIONPENDING) { 282 return;
450 cb(NULL); 283 }
451 free(req); 284
452 } 285 // An array message sets the current x and y rotation.
453 } 286 if (!message.is_array()) {
454 287 fprintf(stderr, "Expected array message.\n");
455 void Loaded(void* data) { 288 return;
456 OpenRequest* req = (OpenRequest*)data; 289 }
457 if (req && req->buf_) { 290
458 char** pptr = (char**)req->data_; 291 pp::VarArray array(message);
459 *pptr = req->buf_; 292 if (array.GetLength() != 2) {
460 g_LoadCnt++; 293 fprintf(stderr, "Expected array of length 2.\n");
461 return; 294 return;
462 } 295 }
463 PostMessage("Failed to load asset.\n"); 296
464 } 297 pp::Var x_angle_var = array.Get(0);
465 298 if (x_angle_var.is_int()) {
466 /** 299 x_angle_ = x_angle_var.AsInt();
467 * Called when the NaCl module is instantiated on the web page. The identifier 300 } else if (x_angle_var.is_double()) {
468 * of the new instance will be passed in as the first argument (this value is 301 x_angle_ = x_angle_var.AsDouble();
469 * generated by the browser and is an opaque handle). This is called for each 302 } else {
470 * instantiation of the NaCl module, which is each time the <embed> tag for 303 fprintf(stderr, "Expected value to be an int or double.\n");
471 * this module is encountered. 304 }
472 * 305
473 * If this function reports a failure (by returning @a PP_FALSE), the NaCl 306 pp::Var y_angle_var = array.Get(1);
474 * module will be deleted and DidDestroy will be called. 307 if (y_angle_var.is_int()) {
475 * @param[in] instance The identifier of the new instance representing this 308 y_angle_ = y_angle_var.AsInt();
476 * NaCl module. 309 } else if (y_angle_var.is_double()) {
477 * @param[in] argc The number of arguments contained in @a argn and @a argv. 310 y_angle_ = y_angle_var.AsDouble();
478 * @param[in] argn An array of argument names. These argument names are 311 } else {
479 * supplied in the <embed> tag, for example: 312 fprintf(stderr, "Expected value to be an int or double.\n");
480 * <embed id="nacl_module" dimensions="2"> 313 }
481 * will produce two arguments, one named "id" and one named "dimensions". 314 }
482 * @param[in] argv An array of argument values. These are the values of the 315
483 * arguments listed in the <embed> tag. In the above example, there will 316 private:
484 * be two elements in this array, "nacl_module" and "2". The indices of 317 bool InitGL(int32_t new_width, int32_t new_height) {
485 * these values match the indices of the corresponding names in @a argn. 318 if (!glInitializePPAPI(pp::Module::Get()->get_browser_interface())) {
486 * @return @a PP_TRUE on success. 319 fprintf(stderr, "Unable to initialize GL PPAPI!\n");
487 */ 320 return false;
488 static PP_Bool Instance_DidCreate(PP_Instance instance, 321 }
489 uint32_t argc, 322
490 const char* argn[], 323 const int32_t attrib_list[] = {
491 const char* argv[]) { 324 PP_GRAPHICS3DATTRIB_ALPHA_SIZE, 8,
492 g_instance = instance; 325 PP_GRAPHICS3DATTRIB_DEPTH_SIZE, 24,
493 LoadURL(instance, "hello.raw", Loaded, &g_TextureData); 326 PP_GRAPHICS3DATTRIB_WIDTH, new_width,
494 LoadURL(instance, "vertex_shader_es2.vert", Loaded, &g_VShaderData); 327 PP_GRAPHICS3DATTRIB_HEIGHT, new_height,
495 LoadURL(instance, "fragment_shader_es2.frag", Loaded, &g_FShaderData); 328 PP_GRAPHICS3DATTRIB_NONE
496 g_quadVertices = BuildCube();
497 return PP_TRUE;
498 }
499
500 /**
501 * Called when the NaCl module is destroyed. This will always be called,
502 * even if DidCreate returned failure. This routine should deallocate any data
503 * associated with the instance.
504 * @param[in] instance The identifier of the instance representing this NaCl
505 * module.
506 */
507 static void Instance_DidDestroy(PP_Instance instance) {
508 delete[] g_TextureData;
509 delete[] g_VShaderData;
510 delete[] g_FShaderData;
511 delete[] g_quadVertices;
512 }
513
514 /**
515 * Called when the position, the size, or the clip rect of the element in the
516 * browser that corresponds to this NaCl module has changed.
517 * @param[in] instance The identifier of the instance representing this NaCl
518 * module.
519 * @param[in] position The location on the page of this NaCl module. This is
520 * relative to the top left corner of the viewport, which changes as the
521 * page is scrolled.
522 * @param[in] clip The visible region of the NaCl module. This is relative to
523 * the top left of the plugin's coordinate system (not the page). If the
524 * plugin is invisible, @a clip will be (0, 0, 0, 0).
525 */
526 static void Instance_DidChangeView(PP_Instance instance,
527 PP_Resource view_resource) {
528 if (g_context == 0) {
529 InitGL();
530 MainLoop(NULL, 0);
531 }
532 }
533
534 /**
535 * Notification that the given NaCl module has gained or lost focus.
536 * Having focus means that keyboard events will be sent to the NaCl module
537 * represented by @a instance. A NaCl module's default condition is that it
538 * will not have focus.
539 *
540 * Note: clicks on NaCl modules will give focus only if you handle the
541 * click event. You signal if you handled it by returning @a true from
542 * HandleInputEvent. Otherwise the browser will bubble the event and give
543 * focus to the element on the page that actually did end up consuming it.
544 * If you're not getting focus, check to make sure you're returning true from
545 * the mouse click in HandleInputEvent.
546 * @param[in] instance The identifier of the instance representing this NaCl
547 * module.
548 * @param[in] has_focus Indicates whether this NaCl module gained or lost
549 * event focus.
550 */
551 static void Instance_DidChangeFocus(PP_Instance instance, PP_Bool has_focus) {}
552
553 /**
554 * Handler that gets called after a full-frame module is instantiated based on
555 * registered MIME types. This function is not called on NaCl modules. This
556 * function is essentially a place-holder for the required function pointer in
557 * the PPP_Instance structure.
558 * @param[in] instance The identifier of the instance representing this NaCl
559 * module.
560 * @param[in] url_loader A PP_Resource an open PPB_URLLoader instance.
561 * @return PP_FALSE.
562 */
563 static PP_Bool Instance_HandleDocumentLoad(PP_Instance instance,
564 PP_Resource url_loader) {
565 /* NaCl modules do not need to handle the document load function. */
566 return PP_FALSE;
567 }
568
569 /**
570 * Entry points for the module.
571 * Initialize needed interfaces: PPB_Core, PPB_Messaging and PPB_Var.
572 * @param[in] a_module_id module ID
573 * @param[in] get_browser pointer to PPB_GetInterface
574 * @return PP_OK on success, any other value on failure.
575 */
576 PP_EXPORT int32_t PPP_InitializeModule(PP_Module a_module_id,
577 PPB_GetInterface get_browser) {
578 ppb_core_interface = (PPB_Core*)(get_browser(PPB_CORE_INTERFACE));
579 ppb_instance_interface = (PPB_Instance*)get_browser(PPB_INSTANCE_INTERFACE);
580 ppb_messaging_interface =
581 (PPB_Messaging*)(get_browser(PPB_MESSAGING_INTERFACE));
582 ppb_var_interface = (PPB_Var*)(get_browser(PPB_VAR_INTERFACE));
583 ppb_urlloader_interface =
584 (PPB_URLLoader*)(get_browser(PPB_URLLOADER_INTERFACE));
585 ppb_urlrequestinfo_interface =
586 (PPB_URLRequestInfo*)(get_browser(PPB_URLREQUESTINFO_INTERFACE));
587 ppb_g3d_interface = (PPB_Graphics3D*)get_browser(PPB_GRAPHICS_3D_INTERFACE);
588 if (!glInitializePPAPI(get_browser))
589 return PP_ERROR_FAILED;
590 return PP_OK;
591 }
592
593 /**
594 * Returns an interface pointer for the interface of the given name, or NULL
595 * if the interface is not supported.
596 * @param[in] interface_name name of the interface
597 * @return pointer to the interface
598 */
599 PP_EXPORT const void* PPP_GetInterface(const char* interface_name) {
600 if (strcmp(interface_name, PPP_INSTANCE_INTERFACE) == 0) {
601 static PPP_Instance instance_interface = {
602 &Instance_DidCreate,
603 &Instance_DidDestroy,
604 &Instance_DidChangeView,
605 &Instance_DidChangeFocus,
606 &Instance_HandleDocumentLoad,
607 }; 329 };
608 return &instance_interface; 330
609 } 331 context_ = pp::Graphics3D(this, attrib_list);
610 return NULL; 332 if (!BindGraphics(context_)) {
611 } 333 fprintf(stderr, "Unable to bind 3d context!\n");
612 334 context_ = pp::Graphics3D();
613 /** 335 glSetCurrentContextPPAPI(0);
614 * Called before the plugin module is unloaded. 336 return false;
615 */ 337 }
616 PP_EXPORT void PPP_ShutdownModule() {} 338
339 glSetCurrentContextPPAPI(context_.pp_resource());
340 return true;
341 }
342
343 void InitShaders() {
344 frag_shader_ = CompileShader(GL_FRAGMENT_SHADER, kFragShaderSource);
345 if (!frag_shader_)
346 return;
347
348 vertex_shader_ = CompileShader(GL_VERTEX_SHADER, kVertexShaderSource);
349 if (!vertex_shader_)
350 return;
351
352 program_ = LinkProgram(frag_shader_, vertex_shader_);
353 if (!program_)
354 return;
355
356 texture_loc_ = glGetUniformLocation(program_, "u_texture");
357 position_loc_ = glGetAttribLocation(program_, "a_position");
358 texcoord_loc_ = glGetAttribLocation(program_, "a_texcoord");
359 color_loc_ = glGetAttribLocation(program_, "a_color");
360 mvp_loc_ = glGetUniformLocation(program_, "u_mvp");
361 }
362
363 void InitBuffers() {
364 glGenBuffers(1, &vertex_buffer_);
365 glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_);
366 glBufferData(GL_ARRAY_BUFFER, sizeof(kCubeVerts), &kCubeVerts[0],
367 GL_STATIC_DRAW);
368
369 glGenBuffers(1, &index_buffer_);
370 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer_);
371 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(kCubeIndexes),
372 &kCubeIndexes[0], GL_STATIC_DRAW);
373 }
374
375 void InitTexture() {
376 DecompressTexture();
377 glGenTextures(1, &texture_);
378 glBindTexture(GL_TEXTURE_2D, texture_);
379 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
380 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
381 glTexImage2D(GL_TEXTURE_2D,
382 0,
383 GL_RGB,
384 128,
385 128,
386 0,
387 GL_RGB,
388 GL_UNSIGNED_BYTE,
389 &g_texture_data[0]);
390 }
391
392 void Animate() {
393 if (animating_) {
394 x_angle_ = fmod(360.0f + x_angle_ + kXAngleDelta, 360.0f);
395 y_angle_ = fmod(360.0f + y_angle_ + kYAngleDelta, 360.0f);
396
397 // Send new values to JavaScript.
398 pp::VarArray array;
399 array.SetLength(2);
400 array.Set(0, x_angle_);
401 array.Set(1, y_angle_);
402 PostMessage(array);
403 }
404 }
405
406 void Render() {
407 glClearColor(0.5, 0.5, 0.5, 1);
408 glClearDepthf(1.0f);
409 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
410 glEnable(GL_DEPTH_TEST);
411
412 //set what program to use
413 glUseProgram(program_);
414 glActiveTexture(GL_TEXTURE0);
415 glBindTexture(GL_TEXTURE_2D, texture_);
416 glUniform1i(texture_loc_, 0);
417
418 //create our perspective matrix
419 float mvp[16];
420 float trs[16];
421 float rot[16];
422
423 identity_matrix(mvp);
424 const float aspect_ratio = static_cast<float>(width_) / height_;
425 glhPerspectivef2(&mvp[0], kFovY, aspect_ratio, kZNear, kZFar);
426
427 translate_matrix(0, 0, kCameraZ, trs);
428 rotate_matrix(x_angle_, y_angle_, 0.0f, rot);
429 multiply_matrix(trs, rot, trs);
430 multiply_matrix(mvp, trs, mvp);
431 glUniformMatrix4fv(mvp_loc_, 1, GL_FALSE, mvp);
432
433 //define the attributes of the vertex
434 glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_);
435 glVertexAttribPointer(position_loc_,
436 3,
437 GL_FLOAT,
438 GL_FALSE,
439 sizeof(Vertex),
440 reinterpret_cast<void*>(offsetof(Vertex, loc)));
441 glEnableVertexAttribArray(position_loc_);
442 glVertexAttribPointer(color_loc_,
443 3,
444 GL_FLOAT,
445 GL_FALSE,
446 sizeof(Vertex),
447 reinterpret_cast<void*>(offsetof(Vertex, color)));
448 glEnableVertexAttribArray(color_loc_);
449 glVertexAttribPointer(texcoord_loc_,
450 2,
451 GL_FLOAT,
452 GL_FALSE,
453 sizeof(Vertex),
454 reinterpret_cast<void*>(offsetof(Vertex, tex)));
455 glEnableVertexAttribArray(texcoord_loc_);
456
457 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer_);
458 glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_BYTE, 0);
459 }
460
461 void MainLoop(int32_t) {
462 Animate();
463 Render();
464 context_.SwapBuffers(
465 callback_factory_.NewCallback(&Graphics3DInstance::MainLoop));
466 }
467
468 pp::CompletionCallbackFactory<Graphics3DInstance> callback_factory_;
469 pp::Graphics3D context_;
470 int32_t width_;
471 int32_t height_;
472 GLuint frag_shader_;
473 GLuint vertex_shader_;
474 GLuint program_;
475 GLuint vertex_buffer_;
476 GLuint index_buffer_;
477 GLuint texture_;
478
479 GLuint texture_loc_;
480 GLuint position_loc_;
481 GLuint texcoord_loc_;
482 GLuint color_loc_;
483 GLuint mvp_loc_;
484
485 float x_angle_;
486 float y_angle_;
487 bool animating_;
488 };
489
490 class Graphics3DModule : public pp::Module {
491 public:
492 Graphics3DModule() : pp::Module() {}
493 virtual ~Graphics3DModule() {}
494
495 virtual pp::Instance* CreateInstance(PP_Instance instance) {
496 return new Graphics3DInstance(instance);
497 }
498 };
499
500 namespace pp {
501 Module* CreateModule() { return new Graphics3DModule(); }
502 } // namespace pp
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698