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

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

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

Powered by Google App Engine
This is Rietveld 408576698