1ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Use of this source code is governed by a BSD-style license that can be
3ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//-----------------------------------------------------------------------------
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The spinning Cube
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//-----------------------------------------------------------------------------
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define _USE_MATH_DEFINES 1
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <limits.h>
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <math.h>
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdarg.h>
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stddef.h>
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdio.h>
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdlib.h>
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string.h>
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/c/pp_completion_callback.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/c/pp_errors.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/c/pp_graphics_3d.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/c/pp_module.h"
22b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "ppapi/c/pp_stdint.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/c/pp_var.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/c/ppb.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/c/ppb_core.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/c/ppb_graphics_3d.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/c/ppb_instance.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/c/ppb_messaging.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/c/ppb_opengles2.h"
30b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "ppapi/c/ppb_url_loader.h"
31b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "ppapi/c/ppb_url_request_info.h"
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/c/ppb_var.h"
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/c/ppp.h"
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/c/ppp_instance.h"
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/c/ppp_messaging.h"
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/c/ppp_graphics_3d.h"
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/lib/gl/gles2/gl2ext_ppapi.h"
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <GLES2/gl2.h>
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "matrix.h"
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static PPB_Messaging* ppb_messaging_interface = NULL;
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static PPB_Var* ppb_var_interface = NULL;
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static PPB_Core* ppb_core_interface = NULL;
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static PPB_Graphics3D* ppb_g3d_interface = NULL;
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static PPB_Instance* ppb_instance_interface = NULL;
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static PPB_URLRequestInfo* ppb_urlrequestinfo_interface = NULL;
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static PPB_URLLoader* ppb_urlloader_interface = NULL;
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static PP_Instance g_instance;
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static PP_Resource g_context;
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)GLuint g_positionLoc;
55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)GLuint g_texCoordLoc;
56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)GLuint g_colorLoc;
57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)GLuint g_MVPLoc;
58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)GLuint g_vboID;
59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)GLuint g_ibID;
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GLubyte g_Indices[36];
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GLuint g_programObj;
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GLuint g_vertexShader;
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GLuint g_fragmentShader;
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GLuint g_textureLoc = 0;
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GLuint g_textureID = 0;
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)float g_fSpinX = 0.0f;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)float g_fSpinY = 0.0f;
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//-----------------------------------------------------------------------------
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Rendering Assets
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//-----------------------------------------------------------------------------
75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)struct Vertex {
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  float tu, tv;
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  float color[3];
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  float loc[3];
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)Vertex* g_quadVertices = NULL;
82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char* g_TextureData = NULL;
83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char* g_VShaderData = NULL;
84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char* g_FShaderData = NULL;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int g_LoadCnt = 0;
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//-----------------------------------------------------------------------------
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// PROTOTYPES
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//-----------------------------------------------------------------------------
90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void PostMessage(const char* fmt, ...);
91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)char* LoadFile(const char* fileName);
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BuildQuad(Vertex* verts, int axis[3], float depth, float color[3]);
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Vertex* BuildCube(void);
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InitGL(void);
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InitProgram(void);
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Render(void);
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static struct PP_Var CStrToVar(const char* str) {
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ppb_var_interface != NULL) {
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ppb_var_interface->VarFromUtf8(str, strlen(str));
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return PP_MakeUndefined();
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void PostMessage(const char* fmt, ...) {
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  va_list args;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  va_start(args, fmt);
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char msg[4096];
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vsnprintf(msg, sizeof(msg), fmt, args);
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ppb_messaging_interface)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ppb_messaging_interface->PostMessage(g_instance, CStrToVar(msg));
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  va_end(args);
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MainLoop(void* foo, int bar) {
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (g_LoadCnt == 3) {
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    InitProgram();
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    g_LoadCnt++;
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (g_LoadCnt > 3) {
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Render();
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PP_CompletionCallback cc = PP_MakeCompletionCallback(MainLoop, 0);
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ppb_g3d_interface->SwapBuffers(g_context, cc);
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PP_CompletionCallback cc = PP_MakeCompletionCallback(MainLoop, 0);
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ppb_core_interface->CallOnMainThread(0, cc, 0);
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void InitGL(void) {
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32_t attribs[] = {
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PP_GRAPHICS3DATTRIB_ALPHA_SIZE, 8,
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PP_GRAPHICS3DATTRIB_DEPTH_SIZE, 24,
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PP_GRAPHICS3DATTRIB_STENCIL_SIZE, 8,
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PP_GRAPHICS3DATTRIB_SAMPLES, 0,
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PP_GRAPHICS3DATTRIB_SAMPLE_BUFFERS, 0,
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PP_GRAPHICS3DATTRIB_WIDTH, 640,
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PP_GRAPHICS3DATTRIB_HEIGHT, 480,
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PP_GRAPHICS3DATTRIB_NONE
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  g_context = ppb_g3d_interface->Create(g_instance, 0, attribs);
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32_t success = ppb_instance_interface->BindGraphics(g_instance, g_context);
149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (success == PP_FALSE) {
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    glSetCurrentContextPPAPI(0);
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printf("Failed to set context.\n");
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  glSetCurrentContextPPAPI(g_context);
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  glViewport(0, 0, 640, 480);
157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)GLuint compileShader(GLenum type, const char* data) {
161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const char* shaderStrings[1];
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  shaderStrings[0] = data;
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GLuint shader = glCreateShader(type);
165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  glShaderSource(shader, 1, shaderStrings, NULL);
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  glCompileShader(shader);
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return shader;
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void InitProgram(void) {
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  glSetCurrentContextPPAPI(g_context);
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_vertexShader = compileShader(GL_VERTEX_SHADER, g_VShaderData);
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_fragmentShader = compileShader(GL_FRAGMENT_SHADER, g_FShaderData);
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_programObj = glCreateProgram();
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  glAttachShader(g_programObj, g_vertexShader);
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  glAttachShader(g_programObj, g_fragmentShader);
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  glLinkProgram(g_programObj);
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  glGenBuffers(1, &g_vboID);
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  glBindBuffer(GL_ARRAY_BUFFER, g_vboID);
183c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  glBufferData(GL_ARRAY_BUFFER,
184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)               24 * sizeof(Vertex),
185c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)               (void*)&g_quadVertices[0],
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               GL_STATIC_DRAW);
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  glGenBuffers(1, &g_ibID);
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_ibID);
190c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  glBufferData(GL_ELEMENT_ARRAY_BUFFER,
191c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)               36 * sizeof(char),
192c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)               (void*)&g_Indices[0],
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               GL_STATIC_DRAW);
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create a texture to test out our fragment shader...
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  glGenTextures(1, &g_textureID);
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  glBindTexture(GL_TEXTURE_2D, g_textureID);
200c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
201c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
202c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  glTexImage2D(GL_TEXTURE_2D,
203c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)               0,
204c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)               GL_RGB,
205c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)               128,
206c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)               128,
207c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)               0,
208c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)               GL_RGB,
209c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)               GL_UNSIGNED_BYTE,
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               g_TextureData);
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Locate some parameters by name so we can set them later...
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_textureLoc = glGetUniformLocation(g_programObj, "arrowTexture");
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_positionLoc = glGetAttribLocation(g_programObj, "a_position");
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_texCoordLoc = glGetAttribLocation(g_programObj, "a_texCoord");
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_colorLoc = glGetAttribLocation(g_programObj, "a_color");
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_MVPLoc = glGetUniformLocation(g_programObj, "a_MVP");
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BuildQuad(Vertex* verts, int axis[3], float depth, float color[3]) {
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static float X[4] = { -1.0f, 1.0f, 1.0f, -1.0f };
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static float Y[4] = { -1.0f, -1.0f, 1.0f, 1.0f };
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < 4; i++) {
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    verts[i].tu = (1.0 - X[i]) / 2.0f;
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    verts[i].tv = (Y[i] + 1.0f) / -2.0f * depth;
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    verts[i].loc[axis[0]] = X[i] * depth;
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    verts[i].loc[axis[1]] = Y[i] * depth;
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    verts[i].loc[axis[2]] = depth;
232c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    for (int j = 0; j < 3; j++)
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      verts[i].color[j] = color[j] * (Y[i] + 1.0f) / 2.0f;
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
237c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)Vertex* BuildCube() {
238c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  Vertex* verts = new Vertex[24];
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < 3; i++) {
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int Faxis[3];
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int Baxis[3];
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    float Fcolor[3];
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    float Bcolor[3];
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int j = 0; j < 3; j++) {
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Faxis[j] = (j + i) % 3;
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Baxis[j] = (j + i) % 3;
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memset(Fcolor, 0, sizeof(float) * 3);
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memset(Bcolor, 0, sizeof(float) * 3);
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Fcolor[i] = 0.5f;
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Bcolor[i] = 1.0f;
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BuildQuad(&verts[0 + i * 4], Faxis, 1.0f, Fcolor);
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BuildQuad(&verts[12 + i * 4], Baxis, -1.0f, Bcolor);
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
256c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  for (int i = 0; i < 6; i++) {
257c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    g_Indices[i * 6 + 0] = 2 + i * 4;
258c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    g_Indices[i * 6 + 1] = 1 + i * 4;
259c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    g_Indices[i * 6 + 2] = 0 + i * 4;
260c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    g_Indices[i * 6 + 3] = 3 + i * 4;
261c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    g_Indices[i * 6 + 4] = 2 + i * 4;
262c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    g_Indices[i * 6 + 5] = 0 + i * 4;
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return verts;
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
267c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void Render(void) {
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static float xRot = 0.0;
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static float yRot = 0.0;
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  xRot += 2.0f;
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  yRot += 0.5f;
273c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (xRot >= 360.0f)
274c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    xRot = 0.0;
275c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (yRot >= 360.0f)
276c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    yRot = 0.0;
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
278c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  glClearColor(0.5, 0.5, 0.5, 1);
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  glClearDepthf(1.0);
280c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  glEnable(GL_DEPTH_TEST);
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //set what program to use
284c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  glUseProgram(g_programObj);
285c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  glActiveTexture(GL_TEXTURE0);
286c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  glBindTexture(GL_TEXTURE_2D, g_textureID);
287c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  glUniform1i(g_textureLoc, 0);
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //create our perspective matrix
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  float mpv[16];
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  float trs[16];
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  float rot[16];
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  identity_matrix(mpv);
295c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  glhPerspectivef2(&mpv[0], 45.0f, 640.0f / 480.0f, 1, 10);
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  translate_matrix(0, 0, -4.0, trs);
298c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  rotate_matrix(xRot, yRot, 0.0f, rot);
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  multiply_matrix(trs, rot, trs);
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  multiply_matrix(mpv, trs, mpv);
301c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  glUniformMatrix4fv(g_MVPLoc, 1, GL_FALSE, (GLfloat*)mpv);
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //define the attributes of the vertex
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  glBindBuffer(GL_ARRAY_BUFFER, g_vboID);
305c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  glVertexAttribPointer(g_positionLoc,
306c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                        3,
307c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                        GL_FLOAT,
308c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                        GL_FALSE,
309c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                        sizeof(Vertex),
310c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                        (void*)offsetof(Vertex, loc));
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  glEnableVertexAttribArray(g_positionLoc);
312c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  glVertexAttribPointer(g_texCoordLoc,
313c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                        2,
314c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                        GL_FLOAT,
315c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                        GL_FALSE,
316c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                        sizeof(Vertex),
317c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                        (void*)offsetof(Vertex, tu));
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  glEnableVertexAttribArray(g_texCoordLoc);
319c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  glVertexAttribPointer(g_colorLoc,
320c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                        3,
321c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                        GL_FLOAT,
322c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                        GL_FALSE,
323c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                        sizeof(Vertex),
324c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                        (void*)offsetof(Vertex, color));
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  glEnableVertexAttribArray(g_colorLoc);
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_ibID);
328c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_BYTE, 0);
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
331c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)typedef void (*OpenCB)(void* dataPtr);
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct OpenRequest {
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_Resource loader_;
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_Resource request_;
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char* buf_;
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* data_;
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64_t size_;
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64_t avail_;
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OpenCB cb_;
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void FreeRequest(OpenRequest* req) {
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (req) {
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ppb_core_interface->ReleaseResource(req->request_);
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ppb_core_interface->ReleaseResource(req->loader_);
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    free(req);
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void URLPartialRead(void* user_data, int mode) {
351c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  OpenRequest* req = (OpenRequest*)user_data;
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64_t total;
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32_t cnt;
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (mode < 0) {
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    free(req->buf_);
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    req->cb_(NULL);
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FreeRequest(req);
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  req->avail_ += mode;
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  total = req->size_ - req->avail_;
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cnt = (total > LONG_MAX) ? LONG_MAX : (int32_t) total;
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If we still have more to do, re-issue the read.
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (cnt > 0) {
368c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    int32_t bytes = ppb_urlloader_interface->ReadResponseBody(
369c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        req->loader_,
370c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        (void*)&req->buf_[req->avail_],
371c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        cnt,
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        PP_MakeCompletionCallback(URLPartialRead, req));
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If the reissue completes immediately, then process it.
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (bytes != PP_OK_COMPLETIONPENDING) {
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      URLPartialRead(user_data, bytes);
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
379c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
380c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Nothing left, so signal complete.
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  req->cb_(req);
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FreeRequest(req);
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printf("Loaded\n");
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void URLOpened(void* user_data, int mode) {
388c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  OpenRequest* req = (OpenRequest*)user_data;
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64_t cur, total;
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32_t cnt;
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ppb_urlloader_interface->GetDownloadProgress(req->loader_, &cur, &total);
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If we can't preallocate the buffer because the size is unknown, then
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // fail the load.
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (total == -1) {
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    req->cb_(NULL);
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FreeRequest(req);
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Otherwise allocate a buffer with enough space for a terminating
403c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // NULL in case we need one.
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cnt = (total > LONG_MAX) ? LONG_MAX : (int32_t) total;
405c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  req->buf_ = (char*)malloc(cnt + 1);
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  req->buf_[cnt] = 0;
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  req->size_ = cnt;
408c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int32_t bytes = ppb_urlloader_interface->ReadResponseBody(
409c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      req->loader_,
410c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      req->buf_,
411c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      cnt,
412c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      PP_MakeCompletionCallback(URLPartialRead, req));
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Usually we are pending.
415c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (bytes == PP_OK_COMPLETIONPENDING)
416c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // But if we did complete the read, then dispatch the handler.
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  URLPartialRead(req, bytes);
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
422c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void LoadURL(PP_Instance inst, const char* url, OpenCB cb, void* data) {
423c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  OpenRequest* req = (OpenRequest*)malloc(sizeof(OpenRequest));
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(req, 0, sizeof(OpenRequest));
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  req->loader_ = ppb_urlloader_interface->Create(inst);
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  req->request_ = ppb_urlrequestinfo_interface->Create(inst);
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  req->cb_ = cb;
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  req->data_ = data;
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!req->loader_ || !req->request_) {
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cb(NULL);
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FreeRequest(req);
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
437c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ppb_urlrequestinfo_interface->SetProperty(
438c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      req->request_, PP_URLREQUESTPROPERTY_URL, CStrToVar(url));
439c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ppb_urlrequestinfo_interface->SetProperty(
440c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      req->request_, PP_URLREQUESTPROPERTY_METHOD, CStrToVar("GET"));
441c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ppb_urlrequestinfo_interface->SetProperty(
442c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      req->request_,
443c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      PP_URLREQUESTPROPERTY_RECORDDOWNLOADPROGRESS,
444c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      PP_MakeBool(PP_TRUE));
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
446c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int val = ppb_urlloader_interface->Open(
447c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      req->loader_, req->request_, PP_MakeCompletionCallback(URLOpened, req));
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (val != PP_OK_COMPLETIONPENDING) {
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cb(NULL);
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    free(req);
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Loaded(void* data) {
456c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  OpenRequest* req = (OpenRequest*)data;
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (req && req->buf_) {
458c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    char** pptr = (char**)req->data_;
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *pptr = req->buf_;
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    g_LoadCnt++;
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PostMessage("Failed to load asset.\n");
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Called when the NaCl module is instantiated on the web page. The identifier
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * of the new instance will be passed in as the first argument (this value is
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * generated by the browser and is an opaque handle).  This is called for each
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * instantiation of the NaCl module, which is each time the <embed> tag for
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * this module is encountered.
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * If this function reports a failure (by returning @a PP_FALSE), the NaCl
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * module will be deleted and DidDestroy will be called.
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param[in] instance The identifier of the new instance representing this
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *     NaCl module.
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param[in] argc The number of arguments contained in @a argn and @a argv.
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param[in] argn An array of argument names.  These argument names are
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *     supplied in the <embed> tag, for example:
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *       <embed id="nacl_module" dimensions="2">
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *     will produce two arguments, one named "id" and one named "dimensions".
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param[in] argv An array of argument values.  These are the values of the
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *     arguments listed in the <embed> tag.  In the above example, there will
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *     be two elements in this array, "nacl_module" and "2".  The indices of
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *     these values match the indices of the corresponding names in @a argn.
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return @a PP_TRUE on success.
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static PP_Bool Instance_DidCreate(PP_Instance instance,
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  uint32_t argc,
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  const char* argn[],
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  const char* argv[]) {
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_instance = instance;
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LoadURL(instance, "hello.raw", Loaded, &g_TextureData);
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LoadURL(instance, "vertex_shader_es2.vert", Loaded, &g_VShaderData);
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LoadURL(instance, "fragment_shader_es2.frag", Loaded, &g_FShaderData);
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_quadVertices = BuildCube();
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return PP_TRUE;
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Called when the NaCl module is destroyed. This will always be called,
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * even if DidCreate returned failure. This routine should deallocate any data
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * associated with the instance.
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param[in] instance The identifier of the instance representing this NaCl
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *     module.
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void Instance_DidDestroy(PP_Instance instance) {
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete[] g_TextureData;
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete[] g_VShaderData;
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete[] g_FShaderData;
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete[] g_quadVertices;
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Called when the position, the size, or the clip rect of the element in the
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * browser that corresponds to this NaCl module has changed.
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param[in] instance The identifier of the instance representing this NaCl
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *     module.
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param[in] position The location on the page of this NaCl module. This is
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *     relative to the top left corner of the viewport, which changes as the
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *     page is scrolled.
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param[in] clip The visible region of the NaCl module. This is relative to
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *     the top left of the plugin's coordinate system (not the page).  If the
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *     plugin is invisible, @a clip will be (0, 0, 0, 0).
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void Instance_DidChangeView(PP_Instance instance,
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   PP_Resource view_resource) {
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (g_context == 0) {
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    InitGL();
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MainLoop(NULL, 0);
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Notification that the given NaCl module has gained or lost focus.
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Having focus means that keyboard events will be sent to the NaCl module
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * represented by @a instance. A NaCl module's default condition is that it
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * will not have focus.
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Note: clicks on NaCl modules will give focus only if you handle the
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * click event. You signal if you handled it by returning @a true from
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * HandleInputEvent. Otherwise the browser will bubble the event and give
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * focus to the element on the page that actually did end up consuming it.
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * If you're not getting focus, check to make sure you're returning true from
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the mouse click in HandleInputEvent.
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param[in] instance The identifier of the instance representing this NaCl
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *     module.
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param[in] has_focus Indicates whether this NaCl module gained or lost
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *     event focus.
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
551c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static void Instance_DidChangeFocus(PP_Instance instance, PP_Bool has_focus) {}
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Handler that gets called after a full-frame module is instantiated based on
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * registered MIME types.  This function is not called on NaCl modules.  This
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * function is essentially a place-holder for the required function pointer in
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the PPP_Instance structure.
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param[in] instance The identifier of the instance representing this NaCl
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *     module.
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param[in] url_loader A PP_Resource an open PPB_URLLoader instance.
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return PP_FALSE.
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static PP_Bool Instance_HandleDocumentLoad(PP_Instance instance,
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           PP_Resource url_loader) {
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* NaCl modules do not need to handle the document load function. */
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return PP_FALSE;
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Entry points for the module.
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Initialize needed interfaces: PPB_Core, PPB_Messaging and PPB_Var.
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param[in] a_module_id module ID
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param[in] get_browser pointer to PPB_GetInterface
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return PP_OK on success, any other value on failure.
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PP_EXPORT int32_t PPP_InitializeModule(PP_Module a_module_id,
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       PPB_GetInterface get_browser) {
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ppb_core_interface = (PPB_Core*)(get_browser(PPB_CORE_INTERFACE));
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ppb_instance_interface = (PPB_Instance*)get_browser(PPB_INSTANCE_INTERFACE);
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ppb_messaging_interface =
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (PPB_Messaging*)(get_browser(PPB_MESSAGING_INTERFACE));
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ppb_var_interface = (PPB_Var*)(get_browser(PPB_VAR_INTERFACE));
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ppb_urlloader_interface =
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (PPB_URLLoader*)(get_browser(PPB_URLLOADER_INTERFACE));
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ppb_urlrequestinfo_interface =
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (PPB_URLRequestInfo*)(get_browser(PPB_URLREQUESTINFO_INTERFACE));
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ppb_g3d_interface = (PPB_Graphics3D*)get_browser(PPB_GRAPHICS_3D_INTERFACE);
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!glInitializePPAPI(get_browser))
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return PP_ERROR_FAILED;
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return PP_OK;
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns an interface pointer for the interface of the given name, or NULL
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * if the interface is not supported.
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param[in] interface_name name of the interface
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return pointer to the interface
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PP_EXPORT const void* PPP_GetInterface(const char* interface_name) {
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (strcmp(interface_name, PPP_INSTANCE_INTERFACE) == 0) {
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    static PPP_Instance instance_interface = {
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &Instance_DidCreate,
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &Instance_DidDestroy,
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &Instance_DidChangeView,
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &Instance_DidChangeFocus,
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &Instance_HandleDocumentLoad,
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    };
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return &instance_interface;
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Called before the plugin module is unloaded.
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
616c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)PP_EXPORT void PPP_ShutdownModule() {}
617