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

Side by Side Diff: visual_studio/NativeClientVSAddIn/InstallerResources/examples/hello_world_gles/hello_world_gles/hello_world.cc

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

Powered by Google App Engine
This is Rietveld 408576698