1562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project// Copyright (c) 2013 The Chromium Authors. All rights reserved.
2562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project// Use of this source code is governed by a BSD-style license that can be
3562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project// found in the LICENSE file.
4562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project
5562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project#include <GLES2/gl2.h>
6562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project#include <math.h>
7562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project#include <stddef.h>
8562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project#include <stdint.h>
9562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project#include <stdio.h>
10562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project#include <string.h>
11562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project
12562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project#include "matrix.h"
13562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project#include "ppapi/cpp/graphics_3d.h"
14562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project#include "ppapi/cpp/instance.h"
15562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project#include "ppapi/cpp/module.h"
16562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project#include "ppapi/cpp/var.h"
17562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project#include "ppapi/cpp/var_array.h"
18562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project#include "ppapi/lib/gl/gles2/gl2ext_ppapi.h"
19562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project#include "ppapi/utility/completion_callback_factory.h"
20562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project
21562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project#ifdef WIN32
22562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project#undef PostMessage
23562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project// Allow 'this' in initializer list
24562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project#pragma warning(disable : 4355)
25562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project#endif
26562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project
27562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Projectextern const uint8_t kRLETextureData[];
28562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Projectextern const size_t kRLETextureDataLength;
29562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project
30562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Projectnamespace {
31562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project
32562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Projectconst float kFovY = 45.0f;
33562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Projectconst float kZNear = 1.0f;
34562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Projectconst float kZFar = 10.0f;
35562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Projectconst float kCameraZ = -4.0f;
36562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Projectconst float kXAngleDelta = 2.0f;
37562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Projectconst float kYAngleDelta = 0.5f;
38562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project
39562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Projectconst size_t kTextureDataLength = 128 * 128 * 3;  // 128x128, 3 Bytes/pixel.
40562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project
41562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project// The decompressed data is written here.
42562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Projectuint8_t g_texture_data[kTextureDataLength];
43562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project
44562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Projectvoid DecompressTexture() {
45562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  // The image is first encoded with a very simple RLE scheme:
46562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  //   <value0> <count0> <value1> <count1> ...
47562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  // Because a <count> of 0 is useless, we use it to represent 256.
48562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  //
49562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  // It is then Base64 encoded to make it use only printable characters (it
50562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  // stores more easily in a source file that way).
51562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  //
52562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  // To decompress, we have to reverse the process.
53562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  static const uint8_t kBase64Decode[256] = {
54562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
55562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
56562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 62,  0,  0,  0, 63,
57562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project   52, 53, 54, 55, 56, 57, 58, 59, 60, 61,  0,  0,  0,  0,  0,  0,
58562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    0,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
59562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project   15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,  0,  0,  0,  0,  0,
60562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
61562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project   41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
62562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  };
63562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  const uint8_t* input = &kRLETextureData[0];
64562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  const uint8_t* const input_end = &kRLETextureData[kRLETextureDataLength];
65562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  uint8_t* output = &g_texture_data[0];
66562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project#ifndef NDEBUG
67562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  const uint8_t* const output_end = &g_texture_data[kTextureDataLength];
68562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project#endif
69562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project
70562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  uint8_t decoded[4];
71562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  int decoded_count = 0;
72562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project
73562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  while (input < input_end || decoded_count > 0) {
74562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    if (decoded_count < 2) {
75562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project      assert(input + 4 <= input_end);
76562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project      // Grab four base-64 encoded (6-bit) bytes.
77562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project      uint32_t data = 0;
78562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project      data |= (kBase64Decode[*input++] << 18);
79562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project      data |= (kBase64Decode[*input++] << 12);
80562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project      data |= (kBase64Decode[*input++] <<  6);
81562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project      data |= (kBase64Decode[*input++]      );
82562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project      // And decode it to 3 (8-bit) bytes.
83562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project      decoded[decoded_count++] = (data >> 16) & 0xff;
84562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project      decoded[decoded_count++] = (data >>  8) & 0xff;
85562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project      decoded[decoded_count++] = (data      ) & 0xff;
86562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project
87562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project      // = is the base64 end marker. Remove decoded bytes if we see any.
88562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project      if (input[-1] == '=') decoded_count--;
89562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project      if (input[-2] == '=') decoded_count--;
90562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    }
91562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project
92562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    int value = decoded[0];
93562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    int count = decoded[1];
94562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    decoded_count -= 2;
95562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    // Move the other decoded bytes (if any) down.
96562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    decoded[0] = decoded[2];
97562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    decoded[1] = decoded[3];
98562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project
99562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    // Expand the RLE data.
100562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    if (count == 0)
101562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project      count = 256;
102562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    assert(output <= output_end);
103562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    memset(output, value, count);
104562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    output += count;
105562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  }
106562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  assert(output == output_end);
107562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project}
108562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project
109562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source ProjectGLuint CompileShader(GLenum type, const char* data) {
110562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  GLuint shader = glCreateShader(type);
111562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  glShaderSource(shader, 1, &data, NULL);
112562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  glCompileShader(shader);
113562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project
114562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  GLint compile_status;
115562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  glGetShaderiv(shader, GL_COMPILE_STATUS, &compile_status);
116562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  if (compile_status != GL_TRUE) {
117562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    // Shader failed to compile, let's see what the error is.
118562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    char buffer[1024];
119562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    GLsizei length;
120562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    glGetShaderInfoLog(shader, sizeof(buffer), &length, &buffer[0]);
121562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    fprintf(stderr, "Shader failed to compile: %s\n", buffer);
122562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    return 0;
123562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  }
124562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project
125562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  return shader;
126562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project}
127562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project
128562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source ProjectGLuint LinkProgram(GLuint frag_shader, GLuint vert_shader) {
129562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  GLuint program = glCreateProgram();
130562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  glAttachShader(program, frag_shader);
131562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  glAttachShader(program, vert_shader);
132562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  glLinkProgram(program);
133562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project
134562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  GLint link_status;
135562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  glGetProgramiv(program, GL_LINK_STATUS, &link_status);
136562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  if (link_status != GL_TRUE) {
137562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    // Program failed to link, let's see what the error is.
138562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    char buffer[1024];
139562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    GLsizei length;
140562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    glGetProgramInfoLog(program, sizeof(buffer), &length, &buffer[0]);
141562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    fprintf(stderr, "Program failed to link: %s\n", buffer);
142562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    return 0;
143562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  }
144562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project
145562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  return program;
146562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project}
147562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project
148562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Projectconst char kFragShaderSource[] =
149562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    "precision mediump float;\n"
150562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    "varying vec3 v_color;\n"
151562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    "varying vec2 v_texcoord;\n"
152562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    "uniform sampler2D u_texture;\n"
153562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    "void main() {\n"
154562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    "  gl_FragColor = texture2D(u_texture, v_texcoord);\n"
155562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    "  gl_FragColor += vec4(v_color, 1);\n"
156562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    "}\n";
157562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project
158562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Projectconst char kVertexShaderSource[] =
159562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    "uniform mat4 u_mvp;\n"
160562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    "attribute vec2 a_texcoord;\n"
161562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    "attribute vec3 a_color;\n"
162562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    "attribute vec4 a_position;\n"
163562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    "varying vec3 v_color;\n"
164562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    "varying vec2 v_texcoord;\n"
165562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    "void main() {\n"
166562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    "  gl_Position = u_mvp * a_position;\n"
167562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    "  v_color = a_color;\n"
168562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    "  v_texcoord = a_texcoord;\n"
169562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    "}\n";
170562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project
171562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Projectstruct Vertex {
172562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  float loc[3];
173562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  float color[3];
174562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  float tex[2];
175562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project};
176562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project
177562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Projectconst Vertex kCubeVerts[24] = {
178562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  // +Z (red arrow, black tip)
179562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  {{-1.0, -1.0, +1.0}, {0.0, 0.0, 0.0}, {1.0, 0.0}},
180562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  {{+1.0, -1.0, +1.0}, {0.0, 0.0, 0.0}, {0.0, 0.0}},
181562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  {{+1.0, +1.0, +1.0}, {0.5, 0.0, 0.0}, {0.0, 1.0}},
182562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  {{-1.0, +1.0, +1.0}, {0.5, 0.0, 0.0}, {1.0, 1.0}},
183562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project
184562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  // +X (green arrow, black tip)
185562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  {{+1.0, -1.0, -1.0}, {0.0, 0.0, 0.0}, {1.0, 0.0}},
186562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  {{+1.0, +1.0, -1.0}, {0.0, 0.0, 0.0}, {0.0, 0.0}},
187562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  {{+1.0, +1.0, +1.0}, {0.0, 0.5, 0.0}, {0.0, 1.0}},
188562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  {{+1.0, -1.0, +1.0}, {0.0, 0.5, 0.0}, {1.0, 1.0}},
189562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project
190562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  // +Y (blue arrow, black tip)
191562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  {{-1.0, +1.0, -1.0}, {0.0, 0.0, 0.0}, {1.0, 0.0}},
192562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  {{-1.0, +1.0, +1.0}, {0.0, 0.0, 0.0}, {0.0, 0.0}},
193562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  {{+1.0, +1.0, +1.0}, {0.0, 0.0, 0.5}, {0.0, 1.0}},
194562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  {{+1.0, +1.0, -1.0}, {0.0, 0.0, 0.5}, {1.0, 1.0}},
195562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project
196562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  // -Z (red arrow, red tip)
197562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  {{+1.0, +1.0, -1.0}, {0.0, 0.0, 0.0}, {1.0, 1.0}},
198562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  {{-1.0, +1.0, -1.0}, {0.0, 0.0, 0.0}, {0.0, 1.0}},
199562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  {{-1.0, -1.0, -1.0}, {1.0, 0.0, 0.0}, {0.0, 0.0}},
200562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  {{+1.0, -1.0, -1.0}, {1.0, 0.0, 0.0}, {1.0, 0.0}},
201562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project
202562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  // -X (green arrow, green tip)
203562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  {{-1.0, +1.0, +1.0}, {0.0, 0.0, 0.0}, {1.0, 1.0}},
204562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  {{-1.0, -1.0, +1.0}, {0.0, 0.0, 0.0}, {0.0, 1.0}},
205562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  {{-1.0, -1.0, -1.0}, {0.0, 1.0, 0.0}, {0.0, 0.0}},
206562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  {{-1.0, +1.0, -1.0}, {0.0, 1.0, 0.0}, {1.0, 0.0}},
207562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project
208562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  // -Y (blue arrow, blue tip)
209562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  {{+1.0, -1.0, +1.0}, {0.0, 0.0, 0.0}, {1.0, 1.0}},
210562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  {{+1.0, -1.0, -1.0}, {0.0, 0.0, 0.0}, {0.0, 1.0}},
211562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  {{-1.0, -1.0, -1.0}, {0.0, 0.0, 1.0}, {0.0, 0.0}},
212562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  {{-1.0, -1.0, +1.0}, {0.0, 0.0, 1.0}, {1.0, 0.0}},
213562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project};
214562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project
215562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Projectconst GLubyte kCubeIndexes[36] = {
216562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project   2,  1,  0,  3,  2,  0,
217562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project   6,  5,  4,  7,  6,  4,
218562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  10,  9,  8, 11, 10,  8,
219562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  14, 13, 12, 15, 14, 12,
220562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  18, 17, 16, 19, 18, 16,
221562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  22, 21, 20, 23, 22, 20,
222562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project};
223562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project
224562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project}  // namespace
225562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project
226562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project
227562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Projectclass Graphics3DInstance : public pp::Instance {
228562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project public:
229562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  explicit Graphics3DInstance(PP_Instance instance)
230562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project      : pp::Instance(instance),
231562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project        callback_factory_(this),
232562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project        width_(0),
233562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project        height_(0),
234562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project        frag_shader_(0),
235562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project        vertex_shader_(0),
236562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project        program_(0),
237562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project        texture_loc_(0),
238562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project        position_loc_(0),
239562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project        color_loc_(0),
240562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project        mvp_loc_(0),
241562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project        x_angle_(0),
242562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project        y_angle_(0),
243562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project        animating_(true) {}
244562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project
245562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]) {
246562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    return true;
247562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  }
248562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project
249562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  virtual void DidChangeView(const pp::View& view) {
250562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    // Pepper specifies dimensions in DIPs (device-independent pixels). To
251562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    // generate a context that is at device-pixel resolution on HiDPI devices,
252562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    // scale the dimensions by view.GetDeviceScale().
253562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    int32_t new_width = view.GetRect().width() * view.GetDeviceScale();
254562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    int32_t new_height = view.GetRect().height() * view.GetDeviceScale();
255562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project
256562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    if (context_.is_null()) {
257562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project      if (!InitGL(new_width, new_height)) {
258562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project        // failed.
259562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project        return;
260562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project      }
261562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project
262562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project      InitShaders();
263562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project      InitBuffers();
264562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project      InitTexture();
265562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project      MainLoop(0);
266562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    } else {
267562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project      // Resize the buffers to the new size of the module.
268562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project      int32_t result = context_.ResizeBuffers(new_width, new_height);
269562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project      if (result < 0) {
270562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project        fprintf(stderr,
271562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project                "Unable to resize buffers to %d x %d!\n",
272562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project                new_width,
273562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project                new_height);
274562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project        return;
275562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project      }
276562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    }
277562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project
278562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    width_ = new_width;
279562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    height_ = new_height;
280562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    glViewport(0, 0, width_, height_);
281562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  }
282562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project
283562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  virtual void HandleMessage(const pp::Var& message) {
284562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    // A bool message sets whether the cube is animating or not.
285562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    if (message.is_bool()) {
286562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project      animating_ = message.AsBool();
287562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project      return;
288562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    }
289562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project
290562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    // An array message sets the current x and y rotation.
291562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    if (!message.is_array()) {
292562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project      fprintf(stderr, "Expected array message.\n");
293562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project      return;
294562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    }
295562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project
296562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    pp::VarArray array(message);
297562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    if (array.GetLength() != 2) {
298562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project      fprintf(stderr, "Expected array of length 2.\n");
299562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project      return;
300562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    }
301562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project
302562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    pp::Var x_angle_var = array.Get(0);
303562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    if (x_angle_var.is_int()) {
304562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project      x_angle_ = x_angle_var.AsInt();
305562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    } else if (x_angle_var.is_double()) {
306562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project      x_angle_ = x_angle_var.AsDouble();
307562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    } else {
308562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project      fprintf(stderr, "Expected value to be an int or double.\n");
309562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    }
310562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project
311562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    pp::Var y_angle_var = array.Get(1);
312562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    if (y_angle_var.is_int()) {
313562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project      y_angle_ = y_angle_var.AsInt();
314562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    } else if (y_angle_var.is_double()) {
315562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project      y_angle_ = y_angle_var.AsDouble();
316562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    } else {
317562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project      fprintf(stderr, "Expected value to be an int or double.\n");
318562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    }
319562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  }
320562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project
321562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project private:
322562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  bool InitGL(int32_t new_width, int32_t new_height) {
323562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    if (!glInitializePPAPI(pp::Module::Get()->get_browser_interface())) {
324562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project      fprintf(stderr, "Unable to initialize GL PPAPI!\n");
325562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project      return false;
326562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    }
327562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project
328562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    const int32_t attrib_list[] = {
329562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project      PP_GRAPHICS3DATTRIB_ALPHA_SIZE, 8,
330562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project      PP_GRAPHICS3DATTRIB_DEPTH_SIZE, 24,
331562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project      PP_GRAPHICS3DATTRIB_WIDTH, new_width,
332562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project      PP_GRAPHICS3DATTRIB_HEIGHT, new_height,
333562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project      PP_GRAPHICS3DATTRIB_NONE
334562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    };
335562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project
336562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    context_ = pp::Graphics3D(this, attrib_list);
337562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    if (!BindGraphics(context_)) {
338562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project      fprintf(stderr, "Unable to bind 3d context!\n");
339562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project      context_ = pp::Graphics3D();
340562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project      glSetCurrentContextPPAPI(0);
341562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project      return false;
342562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    }
343562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project
344562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    glSetCurrentContextPPAPI(context_.pp_resource());
345562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    return true;
346562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  }
347562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project
348562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  void InitShaders() {
349562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    frag_shader_ = CompileShader(GL_FRAGMENT_SHADER, kFragShaderSource);
350562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    if (!frag_shader_)
351562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project      return;
352562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project
353562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    vertex_shader_ = CompileShader(GL_VERTEX_SHADER, kVertexShaderSource);
354562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    if (!vertex_shader_)
355562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project      return;
356562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project
357562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    program_ = LinkProgram(frag_shader_, vertex_shader_);
358562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    if (!program_)
359562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project      return;
360562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project
361562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    texture_loc_ = glGetUniformLocation(program_, "u_texture");
362562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    position_loc_ = glGetAttribLocation(program_, "a_position");
363562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    texcoord_loc_ = glGetAttribLocation(program_, "a_texcoord");
364562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    color_loc_ = glGetAttribLocation(program_, "a_color");
365562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    mvp_loc_ = glGetUniformLocation(program_, "u_mvp");
366562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  }
367562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project
368562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  void InitBuffers() {
369562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    glGenBuffers(1, &vertex_buffer_);
370562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_);
371562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    glBufferData(GL_ARRAY_BUFFER, sizeof(kCubeVerts), &kCubeVerts[0],
372562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project                 GL_STATIC_DRAW);
373562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project
374562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    glGenBuffers(1, &index_buffer_);
375562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer_);
376562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(kCubeIndexes),
377562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project                 &kCubeIndexes[0], GL_STATIC_DRAW);
378562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  }
379562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project
380562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  void InitTexture() {
381562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    DecompressTexture();
382562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    glGenTextures(1, &texture_);
383562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    glBindTexture(GL_TEXTURE_2D, texture_);
384562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
385562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
386562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
387562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
388562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    glTexImage2D(GL_TEXTURE_2D,
389562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project                 0,
390562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project                 GL_RGB,
391562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project                 128,
392562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project                 128,
393562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project                 0,
394562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project                 GL_RGB,
395562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project                 GL_UNSIGNED_BYTE,
396562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project                 &g_texture_data[0]);
397562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  }
398562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project
399562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  void Animate() {
400562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    if (animating_) {
401562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project      x_angle_ = fmod(360.0f + x_angle_ + kXAngleDelta, 360.0f);
402562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project      y_angle_ = fmod(360.0f + y_angle_ + kYAngleDelta, 360.0f);
403562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project
404562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project      // Send new values to JavaScript.
405562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project      pp::VarArray array;
406562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project      array.SetLength(2);
407562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project      array.Set(0, x_angle_);
408562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project      array.Set(1, y_angle_);
409562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project      PostMessage(array);
410562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    }
411562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  }
412562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project
413562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  void Render() {
414562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    glClearColor(0.5, 0.5, 0.5, 1);
415562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    glClearDepthf(1.0f);
416562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
417562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    glEnable(GL_DEPTH_TEST);
418562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project
419562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    //set what program to use
420562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    glUseProgram(program_);
421562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    glActiveTexture(GL_TEXTURE0);
422562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    glBindTexture(GL_TEXTURE_2D, texture_);
423562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    glUniform1i(texture_loc_, 0);
424562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project
425562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    //create our perspective matrix
426562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    float mvp[16];
427562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    float trs[16];
428562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    float rot[16];
429562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project
430562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    identity_matrix(mvp);
431562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    const float aspect_ratio = static_cast<float>(width_) / height_;
432562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    glhPerspectivef2(&mvp[0], kFovY, aspect_ratio, kZNear, kZFar);
433562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project
434562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    translate_matrix(0, 0, kCameraZ, trs);
435562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    rotate_matrix(x_angle_, y_angle_, 0.0f, rot);
436562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    multiply_matrix(trs, rot, trs);
437562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    multiply_matrix(mvp, trs, mvp);
438562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    glUniformMatrix4fv(mvp_loc_, 1, GL_FALSE, mvp);
439562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project
440562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    //define the attributes of the vertex
441562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_);
442562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    glVertexAttribPointer(position_loc_,
443562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project                          3,
444562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project                          GL_FLOAT,
445562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project                          GL_FALSE,
446562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project                          sizeof(Vertex),
447562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project                          reinterpret_cast<void*>(offsetof(Vertex, loc)));
448562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    glEnableVertexAttribArray(position_loc_);
449562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    glVertexAttribPointer(color_loc_,
450562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project                          3,
451562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project                          GL_FLOAT,
452562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project                          GL_FALSE,
453562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project                          sizeof(Vertex),
454562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project                          reinterpret_cast<void*>(offsetof(Vertex, color)));
455562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    glEnableVertexAttribArray(color_loc_);
456562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    glVertexAttribPointer(texcoord_loc_,
457562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project                          2,
458562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project                          GL_FLOAT,
459562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project                          GL_FALSE,
460562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project                          sizeof(Vertex),
461562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project                          reinterpret_cast<void*>(offsetof(Vertex, tex)));
462562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    glEnableVertexAttribArray(texcoord_loc_);
463562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project
464562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer_);
465562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_BYTE, 0);
466562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  }
467562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project
468562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  void MainLoop(int32_t) {
469562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    Animate();
470562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    Render();
471562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    context_.SwapBuffers(
472562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project        callback_factory_.NewCallback(&Graphics3DInstance::MainLoop));
473562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  }
474562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project
475562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  pp::CompletionCallbackFactory<Graphics3DInstance> callback_factory_;
476562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  pp::Graphics3D context_;
477562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  int32_t width_;
478562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  int32_t height_;
479562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  GLuint frag_shader_;
480562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  GLuint vertex_shader_;
481562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  GLuint program_;
482562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  GLuint vertex_buffer_;
483562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  GLuint index_buffer_;
484562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  GLuint texture_;
485562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project
486562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  GLuint texture_loc_;
487562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  GLuint position_loc_;
488562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  GLuint texcoord_loc_;
489562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  GLuint color_loc_;
490562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  GLuint mvp_loc_;
491562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project
492562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  float x_angle_;
493562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  float y_angle_;
494562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  bool animating_;
495562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project};
496562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project
497562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Projectclass Graphics3DModule : public pp::Module {
498562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project public:
499562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  Graphics3DModule() : pp::Module() {}
500562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  virtual ~Graphics3DModule() {}
501562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project
502562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  virtual pp::Instance* CreateInstance(PP_Instance instance) {
503562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project    return new Graphics3DInstance(instance);
504562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project  }
505562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project};
506562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project
507562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Projectnamespace pp {
508562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source ProjectModule* CreateModule() { return new Graphics3DModule(); }
509562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project}  // namespace pp
510562be06492c3ac43adf153f550abaede6bc18a44The Android Open Source Project