summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authornoelallen@google.com <noelallen@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2013-01-30 20:31:40 +0000
committernoelallen@google.com <noelallen@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2013-01-30 20:31:40 +0000
commitb31d645164494c33d74a1a8493ea37e5de9cd21f (patch)
tree2355317c38d5cf7600585911197b0da7195fb1c7
parentc731ac75dd33b52655f0b64a7e8366ebc86b87d0 (diff)
downloadchromium_src-b31d645164494c33d74a1a8493ea37e5de9cd21f.zip
chromium_src-b31d645164494c33d74a1a8493ea37e5de9cd21f.tar.gz
chromium_src-b31d645164494c33d74a1a8493ea37e5de9cd21f.tar.bz2
Add 3D version of instance.
Add an example which uses the ppapi_main and nacl_mounts to simplify the 3D example. NOTRY=true R=binji@chromium.org BUG=168867 Review URL: https://codereview.chromium.org/11647030 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@179692 0039d316-1c4b-4281-b951-d872f2087c98
-rwxr-xr-xnative_client_sdk/src/build_tools/build_sdk.py1
-rw-r--r--native_client_sdk/src/examples/hello_nacl_mounts/Makefile2
-rw-r--r--native_client_sdk/src/examples/hello_nacl_mounts/example.dsc2
-rw-r--r--native_client_sdk/src/examples/hello_world_instance3d/Makefile81
-rw-r--r--native_client_sdk/src/examples/hello_world_instance3d/example.dsc34
-rw-r--r--native_client_sdk/src/examples/hello_world_instance3d/fragment_shader_es2.frag8
-rw-r--r--native_client_sdk/src/examples/hello_world_instance3d/hello_world.cc313
-rw-r--r--native_client_sdk/src/examples/hello_world_instance3d/index.html22
-rw-r--r--native_client_sdk/src/examples/hello_world_instance3d/matrix.cc136
-rw-r--r--native_client_sdk/src/examples/hello_world_instance3d/matrix.h37
-rw-r--r--native_client_sdk/src/examples/hello_world_instance3d/vertex_shader_es2.vert12
-rw-r--r--native_client_sdk/src/libraries/nacl_mounts/Makefile2
-rw-r--r--native_client_sdk/src/libraries/nacl_mounts/kernel_wrap_newlib.cc10
-rw-r--r--native_client_sdk/src/libraries/nacl_mounts/library.dsc2
-rw-r--r--native_client_sdk/src/libraries/nacl_mounts/mount_http.cc1
-rw-r--r--native_client_sdk/src/libraries/ppapi_main/Makefile5
-rw-r--r--native_client_sdk/src/libraries/ppapi_main/library.dsc8
-rw-r--r--native_client_sdk/src/libraries/ppapi_main/ppapi_event.h81
-rw-r--r--native_client_sdk/src/libraries/ppapi_main/ppapi_instance.cc143
-rw-r--r--native_client_sdk/src/libraries/ppapi_main/ppapi_instance.h21
-rw-r--r--native_client_sdk/src/libraries/ppapi_main/ppapi_instance3d.cc232
-rw-r--r--native_client_sdk/src/libraries/ppapi_main/ppapi_instance3d.h59
-rw-r--r--native_client_sdk/src/libraries/ppapi_main/ppapi_main.cc15
-rw-r--r--native_client_sdk/src/libraries/ppapi_main/ppapi_main.h22
-rw-r--r--native_client_sdk/src/libraries/ppapi_main/ppapi_queue.cc97
-rw-r--r--native_client_sdk/src/libraries/ppapi_main/ppapi_queue.h84
26 files changed, 1376 insertions, 54 deletions
diff --git a/native_client_sdk/src/build_tools/build_sdk.py b/native_client_sdk/src/build_tools/build_sdk.py
index 320e468..38a5e4b 100755
--- a/native_client_sdk/src/build_tools/build_sdk.py
+++ b/native_client_sdk/src/build_tools/build_sdk.py
@@ -607,6 +607,7 @@ EXAMPLE_LIST = [
'hello_world_stdio',
'hello_world',
'hello_world_gles',
+ 'hello_world_instance3d',
'hello_world_interactive',
'input_events',
'load_progress',
diff --git a/native_client_sdk/src/examples/hello_nacl_mounts/Makefile b/native_client_sdk/src/examples/hello_nacl_mounts/Makefile
index 8a24b63..c4d9da8 100644
--- a/native_client_sdk/src/examples/hello_nacl_mounts/Makefile
+++ b/native_client_sdk/src/examples/hello_nacl_mounts/Makefile
@@ -16,7 +16,7 @@
# to override this, specify TOOLCHAIN=newlib|glibc or CONFIG=Debug|Release on
# the make command-line or in this file prior to including common.mk. The
# toolchain we use by default will be the first valid one listed
-VALID_TOOLCHAINS:=newlib glibc win
+VALID_TOOLCHAINS:=newlib glibc pnacl win
#
diff --git a/native_client_sdk/src/examples/hello_nacl_mounts/example.dsc b/native_client_sdk/src/examples/hello_nacl_mounts/example.dsc
index ea55c44..0ac6dd6 100644
--- a/native_client_sdk/src/examples/hello_nacl_mounts/example.dsc
+++ b/native_client_sdk/src/examples/hello_nacl_mounts/example.dsc
@@ -1,5 +1,5 @@
{
- 'TOOLS': ['newlib', 'glibc', 'win'],
+ 'TOOLS': ['newlib', 'glibc', 'pnacl', 'win'],
'TARGETS': [
{
'NAME' : 'hello_nacl_mounts',
diff --git a/native_client_sdk/src/examples/hello_world_instance3d/Makefile b/native_client_sdk/src/examples/hello_world_instance3d/Makefile
new file mode 100644
index 0000000..41d3833
--- /dev/null
+++ b/native_client_sdk/src/examples/hello_world_instance3d/Makefile
@@ -0,0 +1,81 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+#
+# GNU Make based build file. For details on GNU Make see:
+# http://www.gnu.org/software/make/manual/make.html
+#
+#
+
+
+#
+# Default configuration
+#
+# By default we will build a Debug configuration using the GCC newlib toolcahin
+# to override this, specify TOOLCHAIN=newlib|glibc or CONFIG=Debug|Release on
+# the make command-line or in this file prior to including common.mk. The
+# toolchain we use by default will be the first valid one listed
+VALID_TOOLCHAINS:=newlib glibc pnacl
+
+
+#
+# Get pepper directory for toolchain and includes.
+#
+# If NACL_SDK_ROOT is not set, then assume it can be found relative to
+# to this Makefile.
+#
+NACL_SDK_ROOT?=$(abspath $(CURDIR)/../..)
+include $(NACL_SDK_ROOT)/tools/common.mk
+
+
+#
+# Target Name
+#
+# The base name of the final NEXE, also the name of the NMF file containing
+# the mapping between architecture and actual NEXE.
+#
+TARGET=hello_world_instance3d
+
+#
+# List of sources to compile
+#
+SOURCES=hello_world.cc matrix.cc
+
+
+#
+# List of libraries to link against. Unlike some tools, the GCC and LLVM
+# based tools require libraries to be specified in the correct order. The
+# order should be symbol reference followed by symbol definition, with direct
+# sources to the link (object files) are left most. In this case:
+# hello_world -> ppapi_main -> ppapi_cpp -> ppapi -> pthread -> libc
+# Notice that libc is implied and come last through standard compiler/link
+# switches.
+#
+# We break this list down into two parts, the set we need to rebuild (DEPS)
+# and the set we do not. This example does not have any additional library
+# dependencies.
+#
+DEPS=ppapi_main nacl_mounts ppapi_cpp ppapi_gles2
+LIBS=$(DEPS) ppapi pthread
+
+
+#
+# Use the library dependency macro for each dependency
+#
+$(foreach dep,$(DEPS),$(eval $(call DEPEND_RULE,$(dep))))
+
+#
+# Use the compile macro for each source.
+#
+$(foreach src,$(SOURCES),$(eval $(call COMPILE_RULE,$(src))))
+
+#
+# Use the link macro for this target on the list of sources.
+#
+$(eval $(call LINK_RULE,$(TARGET),$(SOURCES),$(LIBS),$(DEPS)))
+
+#
+# Specify the NMF to be created with no additional arugments.
+#
+$(eval $(call NMF_RULE,$(TARGET),))
diff --git a/native_client_sdk/src/examples/hello_world_instance3d/example.dsc b/native_client_sdk/src/examples/hello_world_instance3d/example.dsc
new file mode 100644
index 0000000..128f40c
--- /dev/null
+++ b/native_client_sdk/src/examples/hello_world_instance3d/example.dsc
@@ -0,0 +1,34 @@
+{
+ 'TOOLS': ['newlib', 'glibc', 'pnacl'],
+ 'TARGETS': [
+ {
+ 'NAME' : 'hello_world_instance3d',
+ 'TYPE' : 'main',
+ 'SOURCES' : ['hello_world.cc', 'matrix.cc', 'matrix.h'],
+ 'CXXFLAGS': [
+ '-I../../src',
+ '-I../../src/ppapi/lib/gl'
+ ],
+ 'LIBS': ['ppapi_main', 'nacl_mounts', 'ppapi_gles2', 'ppapi_cpp', 'ppapi',
+ 'pthread']
+ }
+ ],
+ 'DATA': [
+ 'Makefile',
+ 'fragment_shader_es2.frag',
+ 'hello.raw',
+ 'vertex_shader_es2.vert'
+ ],
+ 'DEST': 'examples',
+ 'NAME': 'hello_world_instance3d',
+ 'TITLE': 'Hello World GLES 2.0 using ppapi_instance3d',
+ 'DESC': """
+The Hello World GLES 2.0 example demonstrates how to create a 3D cube
+that rotates. This is a simpler example than the tumbler example, and
+written in C. It loads the assets using URLLoader.""",
+ 'FOCUS': '3D graphics, URL Loader.',
+ 'GROUP': 'API'
+}
+
+
+
diff --git a/native_client_sdk/src/examples/hello_world_instance3d/fragment_shader_es2.frag b/native_client_sdk/src/examples/hello_world_instance3d/fragment_shader_es2.frag
new file mode 100644
index 0000000..247c559
--- /dev/null
+++ b/native_client_sdk/src/examples/hello_world_instance3d/fragment_shader_es2.frag
@@ -0,0 +1,8 @@
+precision mediump float;
+varying vec3 v_color;
+varying vec2 v_texCoord;
+uniform sampler2D s_texture;
+void main()
+{
+ gl_FragColor = texture2D( s_texture, vec2(v_texCoord.x,1.0 - v_texCoord.y) ) + vec4(v_color.x,v_color.y,v_color.z,1);
+} \ No newline at end of file
diff --git a/native_client_sdk/src/examples/hello_world_instance3d/hello_world.cc b/native_client_sdk/src/examples/hello_world_instance3d/hello_world.cc
new file mode 100644
index 0000000..304c0fb
--- /dev/null
+++ b/native_client_sdk/src/examples/hello_world_instance3d/hello_world.cc
@@ -0,0 +1,313 @@
+/* Copyright (c) 2012 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/** @file hello_world_gles.cc
+ * This example demonstrates loading and running a simple 3D openGL ES 2.0
+ * application.
+ */
+
+//---------------------------------------------------------------------------
+// The spinning Cube
+//---------------------------------------------------------------------------
+
+#define _USE_MATH_DEFINES 1
+#include <fcntl.h>
+#include <limits.h>
+#include <math.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include "nacl_mounts/nacl_mounts.h"
+
+#include "ppapi/c/pp_completion_callback.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/c/pp_module.h"
+#include "ppapi/c/pp_stdint.h"
+#include "ppapi/c/pp_var.h"
+#include "ppapi/c/ppb.h"
+#include "ppapi/c/ppb_opengles2.h"
+#include "ppapi/c/ppb_var.h"
+#include "ppapi/c/ppp.h"
+#include "ppapi/c/ppp_graphics_3d.h"
+#include "ppapi/c/ppp_instance.h"
+
+#include "ppapi/lib/gl/gles2/gl2ext_ppapi.h"
+
+#include "ppapi_main/ppapi_event.h"
+#include "ppapi_main/ppapi_instance3d.h"
+#include "ppapi_main/ppapi_main.h"
+
+#include <GLES2/gl2.h>
+#include "matrix.h"
+
+GLuint g_positionLoc;
+GLuint g_texCoordLoc;
+GLuint g_colorLoc;
+GLuint g_MVPLoc;
+GLuint g_vboID;
+GLuint g_ibID;
+GLubyte g_Indices[36];
+
+GLuint g_programObj;
+GLuint g_vertexShader;
+GLuint g_fragmentShader;
+
+GLuint g_textureLoc = 0;
+GLuint g_textureID = 0;
+
+float g_fSpinX = 0.0f;
+float g_fSpinY = 0.0f;
+
+//----------------------------------------------------------------------------
+// Rendering Assets
+//----------------------------------------------------------------------------
+struct Vertex
+{
+ float tu, tv;
+ float color[3];
+ float loc[3];
+};
+
+Vertex *g_quadVertices = NULL;
+const char *g_TextureData = NULL;
+const char *g_VShaderData = NULL;
+const char *g_FShaderData = NULL;
+
+bool g_Loaded = false;
+bool g_Ready = false;
+
+
+float g_xSpin = 2.0f;
+float g_ySpin = 0.5f;
+
+
+GLuint compileShader(GLenum type, const char *data) {
+ const char *shaderStrings[1];
+ shaderStrings[0] = data;
+
+ GLuint shader = glCreateShader(type);
+ glShaderSource(shader, 1, shaderStrings, NULL );
+ glCompileShader(shader);
+ return shader;
+}
+
+
+void InitProgram(void) {
+ g_vertexShader = compileShader(GL_VERTEX_SHADER, g_VShaderData);
+ g_fragmentShader = compileShader(GL_FRAGMENT_SHADER, g_FShaderData);
+
+ g_programObj = glCreateProgram();
+ glAttachShader(g_programObj, g_vertexShader);
+ glAttachShader(g_programObj, g_fragmentShader);
+ glLinkProgram(g_programObj);
+
+ glGenBuffers(1, &g_vboID);
+ glBindBuffer(GL_ARRAY_BUFFER, g_vboID);
+ glBufferData(GL_ARRAY_BUFFER, 24 * sizeof(Vertex),
+ (void*)&g_quadVertices[0], GL_STATIC_DRAW);
+
+ glGenBuffers(1, &g_ibID);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_ibID);
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, 36 * sizeof(char),
+ (void*)&g_Indices[0], GL_STATIC_DRAW);
+
+ //
+ // Create a texture to test out our fragment shader...
+ //
+ glGenTextures(1, &g_textureID);
+ glBindTexture(GL_TEXTURE_2D, g_textureID);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 128, 128, 0, GL_RGB,
+ GL_UNSIGNED_BYTE, g_TextureData);
+
+ //
+ // Locate some parameters by name so we can set them later...
+ //
+ g_textureLoc = glGetUniformLocation(g_programObj, "arrowTexture");
+ g_positionLoc = glGetAttribLocation(g_programObj, "a_position");
+ g_texCoordLoc = glGetAttribLocation(g_programObj, "a_texCoord");
+ g_colorLoc = glGetAttribLocation(g_programObj, "a_color");
+ g_MVPLoc = glGetUniformLocation(g_programObj, "a_MVP");
+ printf("Program initialized.\n");
+}
+
+
+void BuildQuad(Vertex* verts, int axis[3], float depth, float color[3]) {
+ static float X[4] = { -1.0f, 1.0f, 1.0f, -1.0f };
+ static float Y[4] = { -1.0f, -1.0f, 1.0f, 1.0f };
+
+ for (int i = 0; i < 4; i++) {
+ verts[i].tu = (1.0 - X[i]) / 2.0f;
+ verts[i].tv = (Y[i] + 1.0f) / -2.0f * depth;
+ verts[i].loc[axis[0]] = X[i] * depth;
+ verts[i].loc[axis[1]] = Y[i] * depth;
+ verts[i].loc[axis[2]] = depth;
+ for (int j = 0; j < 3; j++)
+ verts[i].color[j] = color[j] * (Y[i] + 1.0f) / 2.0f;
+ }
+}
+
+
+Vertex *BuildCube() {
+ Vertex *verts = new Vertex[24];
+ for (int i = 0; i < 3; i++) {
+ int Faxis[3];
+ int Baxis[3];
+ float Fcolor[3];
+ float Bcolor[3];
+ for (int j = 0; j < 3; j++) {
+ Faxis[j] = (j + i) % 3;
+ Baxis[j] = (j + i) % 3;
+ }
+ memset(Fcolor, 0, sizeof(float) * 3);
+ memset(Bcolor, 0, sizeof(float) * 3);
+ Fcolor[i] = 0.5f;
+ Bcolor[i] = 1.0f;
+ BuildQuad(&verts[0 + i * 4], Faxis, 1.0f, Fcolor);
+ BuildQuad(&verts[12 + i * 4], Baxis, -1.0f, Bcolor);
+ }
+
+ for(int i = 0; i < 6; i++) {
+ g_Indices[i*6 + 0] = 2 + i * 4;
+ g_Indices[i*6 + 1] = 1 + i * 4;
+ g_Indices[i*6 + 2] = 0 + i * 4;
+ g_Indices[i*6 + 3] = 3 + i * 4;
+ g_Indices[i*6 + 4] = 2 + i * 4;
+ g_Indices[i*6 + 5] = 0 + i * 4;
+ }
+ return verts;
+}
+
+
+static float clamp(float val, float min, float max) {
+ if (val < min) return min;
+ if (val > max) return max;
+ return val;
+}
+
+
+void ProcessEvent(PPAPIEvent* event) {
+ if (event->event_type == PP_INPUTEVENT_TYPE_MOUSEMOVE) {
+ PPAPIMouseEvent* mouse = (PPAPIMouseEvent*) event;
+ g_ySpin = clamp((float) mouse->delta.x / 2, -4.0, 4.0);
+ g_xSpin = clamp((float) mouse->delta.y / 2, -4.0, 4.0);
+ }
+ if (event->event_type == PP_INPUTEVENT_TYPE_KEYUP) {
+ PPAPIKeyEvent* key = (PPAPIKeyEvent*) event;
+ if (key->key_code == 13) {
+ PPAPIInstance3D::GetInstance3D()->ToggleFullscreen();
+ }
+ }
+}
+
+void PPAPIRender(uint32_t width, uint32_t height) {
+ if (!g_Ready) {
+ if (g_Loaded) {
+ InitProgram();
+ g_Ready = true;
+ } else {
+ return;
+ }
+ }
+
+ PPAPIEvent* event;
+ while (PPAPIEvent* event = PPAPI_AcquireEvent()) {
+ ProcessEvent(event);
+ PPAPI_ReleaseEvent(event);
+ }
+
+ static float xRot = 0.0;
+ static float yRot = 0.0;
+
+ xRot -= g_xSpin;
+ yRot -= g_ySpin;
+
+ if (xRot >= 360.0f) xRot = 0.0;
+ if (xRot <= -360.0f) xRot = 0.0;
+
+ if (yRot >= 360.0f) yRot = 0.0;
+ if (yRot <= -360.0f) yRot = 0.0;
+
+ glClearColor(0.5,0.5,0.5,1);
+ glClearDepthf(1.0);
+ glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
+ glEnable(GL_DEPTH_TEST);
+
+ //set what program to use
+ glUseProgram( g_programObj );
+ glActiveTexture ( GL_TEXTURE0 );
+ glBindTexture ( GL_TEXTURE_2D,g_textureID );
+ glUniform1i ( g_textureLoc, 0 );
+
+ //create our perspective matrix
+ float mpv[16];
+ float trs[16];
+ float rot[16];
+
+ identity_matrix(mpv);
+ glhPerspectivef2(&mpv[0], 45.0f, (float) (width) / (float) height, 1, 10);
+
+ translate_matrix(0, 0, -4.0, trs);
+ rotate_matrix(xRot, yRot , 0.0f ,rot);
+ multiply_matrix(trs, rot, trs);
+ multiply_matrix(mpv, trs, mpv);
+ glUniformMatrix4fv(g_MVPLoc, 1, GL_FALSE, (GLfloat*) mpv);
+
+ //define the attributes of the vertex
+ glBindBuffer(GL_ARRAY_BUFFER, g_vboID);
+ glVertexAttribPointer(g_positionLoc, 3, GL_FLOAT, GL_FALSE,
+ sizeof(Vertex), (void*)offsetof(Vertex,loc));
+ glEnableVertexAttribArray(g_positionLoc);
+ glVertexAttribPointer(g_texCoordLoc, 2, GL_FLOAT, GL_FALSE,
+ sizeof(Vertex), (void*)offsetof(Vertex,tu));
+ glEnableVertexAttribArray(g_texCoordLoc);
+ glVertexAttribPointer(g_colorLoc, 3, GL_FLOAT, GL_FALSE,
+ sizeof(Vertex), (void*)offsetof(Vertex,color));
+ glEnableVertexAttribArray(g_colorLoc);
+
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_ibID);
+ glDrawElements ( GL_TRIANGLES, 36, GL_UNSIGNED_BYTE ,0 );
+}
+
+
+const char *LoadData(const char *url) {
+ char *buf;
+ struct stat stat_buf;
+
+ int fp = open(url, O_RDONLY);
+ fstat(fp, &stat_buf);
+
+ int len = static_cast<int>(stat_buf.st_size);
+ buf = new char[len + 1];
+ int read_size = read(fp, buf, len);
+ buf[len] = 0;
+ return buf;
+}
+
+
+PPAPI_MAIN_USE(PPAPI_CreateInstance3D, PPAPI_MAIN_DEFAULT_ARGS)
+int ppapi_main(int argc, const char *argv[]) {
+ printf("Started main.\n");
+
+ // Mount URL loads to /http
+ mount("", "/http", "httpfs", 0, "");
+
+ g_TextureData = LoadData("/http/hello.raw");
+ g_VShaderData = LoadData("/http/vertex_shader_es2.vert");
+ g_FShaderData = LoadData("/http/fragment_shader_es2.frag");
+ g_quadVertices = BuildCube();
+
+ fprintf(stderr,"Loaded\n");
+ g_Loaded = true;
+ return 0;
+}
diff --git a/native_client_sdk/src/examples/hello_world_instance3d/index.html b/native_client_sdk/src/examples/hello_world_instance3d/index.html
new file mode 100644
index 0000000..cfc9ddd
--- /dev/null
+++ b/native_client_sdk/src/examples/hello_world_instance3d/index.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<!--
+Copyright (c) 2012 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<head>
+ <meta http-equiv="Pragma" content="no-cache">
+ <meta http-equiv="Expires" content="-1">
+ <title><TITLE></title>
+ <script type="text/javascript" src="common.js"></script>
+</head>
+<body data-name="<NAME>" data-tc="<tc>" data-path="<path>" data-width="640"
+ data-height="480">
+ <h1><TITLE></h1>
+ <h2>Status: <code id="statusField">NO-STATUS</code></h2>
+ <!-- The NaCl plugin will be embedded inside the element with id "listener".
+ See common.js.-->
+ <div id="listener"></div>
+</body>
+</html>
diff --git a/native_client_sdk/src/examples/hello_world_instance3d/matrix.cc b/native_client_sdk/src/examples/hello_world_instance3d/matrix.cc
new file mode 100644
index 0000000..32200c7
--- /dev/null
+++ b/native_client_sdk/src/examples/hello_world_instance3d/matrix.cc
@@ -0,0 +1,136 @@
+/* Copyright (c) 2012 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/** @file matrix.cc
+ * Implements simple matrix manipulation functions.
+ */
+
+//-----------------------------------------------------------------------------
+#include <stdlib.h>
+#include <string.h>
+#include "matrix.h"
+#define deg_to_rad(x) (x * (M_PI/180.0f))
+
+void glhFrustumf2(Matrix_t mat, GLfloat left, GLfloat right, GLfloat bottom,
+ GLfloat top, GLfloat znear, GLfloat zfar)
+{
+ float temp, temp2, temp3, temp4;
+ temp = 2.0f * znear;
+ temp2 = right - left;
+ temp3 = top - bottom;
+ temp4 = zfar - znear;
+ mat[0] = temp / temp2;
+ mat[1] = 0.0f;
+ mat[2] = 0.0f;
+ mat[3] = 0.0f;
+ mat[4] = 0.0f;
+ mat[5] = temp / temp3;
+ mat[6] = 0.0f;
+ mat[7] = 0.0f;
+ mat[8] = (right + left) / temp2;
+ mat[9] = (top + bottom) / temp3;
+ mat[10] = (-zfar - znear) / temp4;
+ mat[11] = -1.0f;
+ mat[12] = 0.0f;
+ mat[13] = 0.0f;
+ mat[14] = (-temp * zfar) / temp4;
+ mat[15] = 0.0f;
+}
+
+void glhPerspectivef2(Matrix_t mat, GLfloat fovyInDegrees,
+ GLfloat aspectRatio, GLfloat znear, GLfloat zfar)
+{
+ float ymax, xmax;
+ ymax = znear * tanf(fovyInDegrees * 3.14f / 360.0f);
+ xmax = ymax * aspectRatio;
+ glhFrustumf2(mat, -xmax, xmax, -ymax, ymax, znear, zfar);
+}
+
+void identity_matrix(Matrix_t mat) {
+ memset(mat, 0, sizeof(Matrix_t));
+ mat[0] = 1.0;
+ mat[5] = 1.0;
+ mat[10] = 1.0;
+ mat[15] = 1.0;
+}
+
+void multiply_matrix(const Matrix_t a, const Matrix_t b, Matrix_t mat) {
+ // Generate to a temporary first in case the output matrix and input
+ // matrix are thes same.
+ Matrix_t out;
+
+ out[0] = a[0] * b[0] + a[4] * b[1] + a[8] * b[2] + a[12] * b[3];
+ out[1] = a[1] * b[0] + a[5] * b[1] + a[9] * b[2] + a[13] * b[3];
+ out[2] = a[2] * b[0] + a[6] * b[1] + a[10] * b[2] + a[14] * b[3];
+ out[3] = a[3] * b[0] + a[7] * b[1] + a[11] * b[2] + a[15] * b[3];
+
+ out[4] = a[0] * b[4] + a[4] * b[5] + a[8] * b[6] + a[12] * b[7];
+ out[5] = a[1] * b[4] + a[5] * b[5] + a[9] * b[6] + a[13] * b[7];
+ out[6] = a[2] * b[4] + a[6] * b[5] + a[10] * b[6] + a[14] * b[7];
+ out[7] = a[3] * b[4] + a[7] * b[5] + a[11] * b[6] + a[15] * b[7];
+
+ out[8] = a[0] * b[8] + a[4] * b[9] + a[8] * b[10] + a[12] * b[11];
+ out[9] = a[1] * b[8] + a[5] * b[9] + a[9] * b[10] + a[13] * b[11];
+ out[10] = a[2] * b[8] + a[6] * b[9] + a[10] * b[10] + a[14] * b[11];
+ out[11] = a[3] * b[8] + a[7] * b[9] + a[11] * b[10] + a[15] * b[11];
+
+ out[12] = a[0] * b[12] + a[4] * b[13] + a[8] * b[14] + a[12] * b[15];
+ out[13] = a[1] * b[12] + a[5] * b[13] + a[9] * b[14] + a[13] * b[15];
+ out[14] = a[2] * b[12] + a[6] * b[13] + a[10] * b[14] + a[14] * b[15];
+ out[15] = a[3] * b[12] + a[7] * b[13] + a[11] * b[14] + a[15] * b[15];
+
+ memcpy(mat, out, sizeof(Matrix_t));
+}
+
+void rotate_x_matrix(GLfloat x_rad, Matrix_t mat) {
+ identity_matrix(mat);
+ mat[5] = cosf(x_rad);
+ mat[6] = -sinf(x_rad);
+ mat[9] = -mat[6];
+ mat[10] = mat[5];
+}
+
+void rotate_y_matrix(GLfloat y_rad, Matrix_t mat) {
+ identity_matrix(mat);
+ mat[0] = cosf(y_rad);
+ mat[2] = sinf(y_rad);
+ mat[8] = -mat[2];
+ mat[10] = mat[0];
+}
+
+void rotate_z_matrix(GLfloat z_rad, Matrix_t mat) {
+ identity_matrix(mat);
+ mat[0] = cosf(z_rad);
+ mat[1] = sinf(z_rad);
+ mat[4] = -mat[1];
+ mat[5] = mat[0];
+}
+
+void rotate_matrix(GLfloat x_deg, GLfloat y_deg, GLfloat z_deg,
+ Matrix_t mat) {
+ GLfloat x_rad = (GLfloat) deg_to_rad(x_deg);
+ GLfloat y_rad = (GLfloat) deg_to_rad(y_deg);
+ GLfloat z_rad = (GLfloat) deg_to_rad(z_deg);
+
+ Matrix_t x_matrix;
+ Matrix_t y_matrix;
+ Matrix_t z_matrix;
+
+ rotate_x_matrix(x_rad, x_matrix);
+ rotate_y_matrix(y_rad, y_matrix);
+ rotate_z_matrix(z_rad, z_matrix);
+
+ Matrix_t xy_matrix;
+ multiply_matrix(y_matrix, x_matrix, xy_matrix);
+ multiply_matrix(z_matrix, xy_matrix, mat);
+}
+
+void translate_matrix(GLfloat x, GLfloat y, GLfloat z, Matrix_t mat) {
+ identity_matrix(mat);
+ mat[12] += x;
+ mat[13] += y;
+ mat[14] += z;
+}
+
diff --git a/native_client_sdk/src/examples/hello_world_instance3d/matrix.h b/native_client_sdk/src/examples/hello_world_instance3d/matrix.h
new file mode 100644
index 0000000..7db7985
--- /dev/null
+++ b/native_client_sdk/src/examples/hello_world_instance3d/matrix.h
@@ -0,0 +1,37 @@
+#ifndef EXAMPLES_HELLO_WORLD_GLES_MATRIX_H
+#define EXAMPLES_HELLO_WORLD_GLES_MATRIX_H
+
+/* Copyright (c) 2012 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/** @file matrix.cc
+ * Implements simple matrix manipulation functions.
+ */
+
+//-----------------------------------------------------------------------------
+#define _USE_MATH_DEFINES 1
+#include <limits.h>
+#include <math.h>
+#include <GLES2/gl2.h>
+
+typedef GLfloat Matrix_t[16];
+
+/// Since GLES2 doesn't have all the nifty matrix transform functions that GL
+/// has, we emulate some of them here for the sake of sanity from:
+/// http://www.opengl.org/wiki/GluPerspective_code
+void glhFrustumf2(Matrix_t mat, GLfloat left, GLfloat right, GLfloat bottom,
+ GLfloat top, GLfloat znear, GLfloat zfar);
+
+void glhPerspectivef2(Matrix_t mat, GLfloat fovyInDegrees,
+ GLfloat aspectRatio, GLfloat znear, GLfloat zfar);
+
+
+void identity_matrix(Matrix_t mat);
+void multiply_matrix(const Matrix_t a, const Matrix_t b, Matrix_t mat);
+void rotate_matrix(GLfloat x_deg, GLfloat y_deg, GLfloat z_deg, Matrix_t mat);
+void translate_matrix(GLfloat x, GLfloat y, GLfloat z, Matrix_t mat);
+
+#endif // EXAMPLES_HELLO_WORLD_GLES_MATRIX_H
+
diff --git a/native_client_sdk/src/examples/hello_world_instance3d/vertex_shader_es2.vert b/native_client_sdk/src/examples/hello_world_instance3d/vertex_shader_es2.vert
new file mode 100644
index 0000000..da616cb
--- /dev/null
+++ b/native_client_sdk/src/examples/hello_world_instance3d/vertex_shader_es2.vert
@@ -0,0 +1,12 @@
+uniform mat4 a_MVP;
+attribute vec2 a_texCoord;
+attribute vec3 a_color;
+attribute vec4 a_position;
+varying vec3 v_color;
+varying vec2 v_texCoord;
+void main()
+{
+ gl_Position = a_MVP * a_position;
+ v_color = a_color;
+ v_texCoord = a_texCoord;
+} \ No newline at end of file
diff --git a/native_client_sdk/src/libraries/nacl_mounts/Makefile b/native_client_sdk/src/libraries/nacl_mounts/Makefile
index 5597f0c..6c9714e 100644
--- a/native_client_sdk/src/libraries/nacl_mounts/Makefile
+++ b/native_client_sdk/src/libraries/nacl_mounts/Makefile
@@ -16,7 +16,7 @@
# to override this, specify TOOLCHAIN=newlib|glibc or CONFIG=Debug|Release on
# the make command-line or in this file prior to including common.mk. The
# toolchain we use by default will be the first valid one listed
-VALID_TOOLCHAINS:=newlib glibc win
+VALID_TOOLCHAINS:=newlib glibc pnacl win
#
diff --git a/native_client_sdk/src/libraries/nacl_mounts/kernel_wrap_newlib.cc b/native_client_sdk/src/libraries/nacl_mounts/kernel_wrap_newlib.cc
index 32a12e4..1e67faf 100644
--- a/native_client_sdk/src/libraries/nacl_mounts/kernel_wrap_newlib.cc
+++ b/native_client_sdk/src/libraries/nacl_mounts/kernel_wrap_newlib.cc
@@ -123,8 +123,9 @@ int WRAP(open)(const char* pathname, int oflag, mode_t cmode, int* newfd) {
}
int WRAP(read)(int fd, void *buf, size_t count, size_t *nread) {
- *nread = ki_read(fd, buf, count);
- return (*nread < 0) ? errno : 0;
+ ssize_t signed_nread = ki_read(fd, buf, count);
+ *nread = static_cast<size_t>(signed_nread);
+ return (signed_nread < 0) ? errno : 0;
}
int remove(const char* path) {
@@ -157,8 +158,9 @@ int unlink(const char* path) {
}
int WRAP(write)(int fd, const void *buf, size_t count, size_t *nwrote) {
- *nwrote = ki_write(fd, buf, count);
- return (*nwrote < 0) ? errno : 0;
+ ssize_t signed_nwrote = ki_write(fd, buf, count);
+ *nwrote = static_cast<size_t>(signed_nwrote);
+ return (signed_nwrote < 0) ? errno : 0;
}
diff --git a/native_client_sdk/src/libraries/nacl_mounts/library.dsc b/native_client_sdk/src/libraries/nacl_mounts/library.dsc
index 83e95eb..0e76844 100644
--- a/native_client_sdk/src/libraries/nacl_mounts/library.dsc
+++ b/native_client_sdk/src/libraries/nacl_mounts/library.dsc
@@ -1,7 +1,7 @@
{
# Disabled pnacl for now because it warns on using the language extension
# typeof(...)
- 'TOOLS': ['newlib', 'glibc', 'win'],
+ 'TOOLS': ['newlib', 'glibc', 'pnacl', 'win'],
'SEARCH': [
'.',
'pepper',
diff --git a/native_client_sdk/src/libraries/nacl_mounts/mount_http.cc b/native_client_sdk/src/libraries/nacl_mounts/mount_http.cc
index 06dc954..bd5fc40 100644
--- a/native_client_sdk/src/libraries/nacl_mounts/mount_http.cc
+++ b/native_client_sdk/src/libraries/nacl_mounts/mount_http.cc
@@ -82,7 +82,6 @@ StringMap_t ParseHeaders(const char* headers, int32_t headers_length) {
// Found value.
value.assign(start, &headers[i] - start);
result[key] = value;
-
start = &headers[i + 1];
state = FINDING_KEY;
}
diff --git a/native_client_sdk/src/libraries/ppapi_main/Makefile b/native_client_sdk/src/libraries/ppapi_main/Makefile
index fb16a49..dbe8852 100644
--- a/native_client_sdk/src/libraries/ppapi_main/Makefile
+++ b/native_client_sdk/src/libraries/ppapi_main/Makefile
@@ -16,7 +16,7 @@
# to override this, specify TOOLCHAIN=newlib|glibc or CONFIG=Debug|Release on
# the make command-line or in this file prior to including common.mk. The
# toolchain we use by default will be the first valid one listed
-VALID_TOOLCHAINS:=newlib glibc
+VALID_TOOLCHAINS:=newlib glibc pnacl
#
@@ -40,7 +40,8 @@ TARGET=ppapi_main
#
# List of sources to compile
#
-SOURCES:=ppapi_main.cc ppapi_instance.cc
+SOURCES:=ppapi_main.cc ppapi_instance.cc ppapi_instance3d.cc
+SOURCES+=ppapi_queue.cc
#
# Use the compile macro for each source.
#
diff --git a/native_client_sdk/src/libraries/ppapi_main/library.dsc b/native_client_sdk/src/libraries/ppapi_main/library.dsc
index 65e1c0f..ea13689 100644
--- a/native_client_sdk/src/libraries/ppapi_main/library.dsc
+++ b/native_client_sdk/src/libraries/ppapi_main/library.dsc
@@ -1,23 +1,25 @@
{
'TOOLS': ['newlib', 'glibc'],
- 'SEARCH': [
- '.',
- ],
'TARGETS': [
{
'NAME' : 'ppapi_main',
'TYPE' : 'lib',
'SOURCES' : [
"ppapi_instance.cc",
+ "ppapi_instance3d.cc",
"ppapi_main.cc",
+ "ppapi_queue.cc",
],
}
],
'HEADERS': [
{
'FILES': [
+ "ppapi_event.h",
"ppapi_instance.h",
+ "ppapi_instance3d.h",
"ppapi_main.h",
+ "ppapi_queue.h",
],
'DEST': 'include/ppapi_main',
},
diff --git a/native_client_sdk/src/libraries/ppapi_main/ppapi_event.h b/native_client_sdk/src/libraries/ppapi_main/ppapi_event.h
new file mode 100644
index 0000000..6d222db
--- /dev/null
+++ b/native_client_sdk/src/libraries/ppapi_main/ppapi_event.h
@@ -0,0 +1,81 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+
+#ifndef PPAPI_MAIN_PPAPI_EVENT_H_
+#define PPAPI_MAIN_PPAPI_EVENT_H_
+
+#include "ppapi/c/pp_input_event.h"
+#include "ppapi/c/pp_point.h"
+#include "ppapi/c/pp_touch_point.h"
+#include "ppapi/c/ppb_input_event.h"
+
+#include "utils/macros.h"
+
+EXTERN_C_BEGIN
+
+/*
+ * Event Structures
+ *
+ * The following event structures are based on the equivilent structs
+ * defined in ppapi/c/ppb_input_event.h.
+ *
+ */
+
+// Generic Event
+typedef struct {
+ PP_InputEvent_Type event_type;
+ PP_TimeTicks time_ticks;
+ uint32_t modifiers;
+} PPAPIEvent;
+
+
+// Key Code Up/Down
+typedef struct {
+ PPAPIEvent event;
+
+ uint32_t key_code;
+} PPAPIKeyEvent;
+
+
+// Cooked Character Event
+typedef struct {
+ PPAPIEvent event;
+
+ char text[5];
+} PPAPICharEvent;
+
+
+// Mouse Event
+typedef struct {
+ PPAPIEvent event;
+
+ PP_InputEvent_MouseButton button;
+ struct PP_Point location;
+ struct PP_Point delta;
+} PPAPIMouseEvent;
+
+
+// Wheel Event
+typedef struct {
+ PPAPIEvent event;
+
+ PP_InputEvent_MouseButton button;
+ struct PP_FloatPoint delta;
+ uint32_t by_page;
+} PPAPIWheelEvent;
+
+
+// Touch Event
+#define MAX_TOUCH_POINTS 4
+typedef struct {
+ PPAPIEvent event;
+
+ uint32_t point_count;
+ struct PP_TouchPoint points[MAX_TOUCH_POINTS];
+} PPAPITouchEvent;
+
+EXTERN_C_END
+
+#endif // PPAPI_MAIN_PPAPI_EVENT_H_ \ No newline at end of file
diff --git a/native_client_sdk/src/libraries/ppapi_main/ppapi_instance.cc b/native_client_sdk/src/libraries/ppapi_main/ppapi_instance.cc
index 7f4c1d2..5bd92d2 100644
--- a/native_client_sdk/src/libraries/ppapi_main/ppapi_instance.cc
+++ b/native_client_sdk/src/libraries/ppapi_main/ppapi_instance.cc
@@ -5,6 +5,7 @@
#include <fcntl.h>
#include <pthread.h>
#include <stdio.h>
+#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
@@ -18,21 +19,30 @@
#include "nacl_mounts/nacl_mounts.h"
#include "ppapi/cpp/input_event.h"
+#include "ppapi/cpp/message_loop.h"
#include "ppapi/cpp/rect.h"
#include "ppapi/cpp/size.h"
+#include "ppapi/cpp/touch_point.h"
#include "ppapi/cpp/var.h"
+#include "ppapi_main/ppapi_event.h"
#include "ppapi_main/ppapi_instance.h"
#include "ppapi_main/ppapi_main.h"
+PPAPIInstance* PPAPI_GetInstance() {
+ return static_cast<PPAPIInstance*>(PPAPI_GetInstanceObject());
+}
+
struct StartInfo {
+ PPAPIInstance* inst_;
uint32_t argc_;
const char** argv_;
};
-static void* StartMain(void *info) {
+void* PPAPIInstance::StartMain(void *info) {
StartInfo* si = static_cast<StartInfo*>(info);
+ si->inst_->main_loop_.AttachToCurrentThread();
if (NULL != info) {
ppapi_main(si->argc_, si->argv_);
@@ -47,21 +57,24 @@ static void* StartMain(void *info) {
const char *argv[] = { "NEXE", NULL };
ppapi_main(1, argv);
}
+
return NULL;
}
PPAPIInstance::PPAPIInstance(PP_Instance instance, const char *args[])
: pp::Instance(instance),
+ main_loop_(this),
has_focus_(false) {
-
while (*args) {
std::string key = *args++;
std::string val = *args++;
properties_[key] = val;
}
- RequestInputEvents(PP_INPUTEVENT_CLASS_MOUSE);
- RequestFilteringInputEvents(PP_INPUTEVENT_CLASS_KEYBOARD);
+ RequestInputEvents(PP_INPUTEVENT_CLASS_MOUSE |
+ PP_INPUTEVENT_CLASS_KEYBOARD |
+ PP_INPUTEVENT_CLASS_WHEEL |
+ PP_INPUTEVENT_CLASS_TOUCH);
}
PPAPIInstance::~PPAPIInstance() {
@@ -72,13 +85,14 @@ bool PPAPIInstance::Init(uint32_t arg,
const char* argv[]) {
StartInfo* si = new StartInfo;
+ si->inst_ = this;
si->argc_ = 1;
si->argv_ = new const char *[arg*2+1];
si->argv_[0] = NULL;
for (uint32_t i=0; i < arg; i++) {
// If we start with PM prefix set the instance argument map
- if (0 == strncmp(argn[i], "PM_", 3)) {
+ if (0 == strncmp(argn[i], "pm_", 3)) {
std::string key = argn[i];
std::string val = argv[i];
properties_[key] = val;
@@ -125,7 +139,7 @@ bool PPAPIInstance::Init(uint32_t arg,
}
const char* PPAPIInstance::GetProperty(const char* key, const char* def) {
- PropteryMap_t::iterator it = properties_.find(key);
+ PropertyMap_t::iterator it = properties_.find(key);
if (it != properties_.end()) {
return it->second.c_str();
}
@@ -133,54 +147,115 @@ const char* PPAPIInstance::GetProperty(const char* key, const char* def) {
}
bool PPAPIInstance::ProcessProperties() {
- const char* stdin_path = GetProperty("PM_STDIO", "/dev/null");
- const char* stdout_path = GetProperty("PM_STDOUT", "/dev/tty");
- const char* stderr_path = GetProperty("PM_STDERR", "/dev/console3");
+ const char* stdin_path = GetProperty("pm_stdio", "/dev/null");
+ const char* stdout_path = GetProperty("pm_stdout", "/dev/console1");
+ const char* stderr_path = GetProperty("pm_stderr", "/dev/console3");
+ const char* queue_size = GetProperty("pm_queue_size", "1024");
+
+ // Force a miniumum size of 4
+ uint32_t queue_size_int = atoi(queue_size);
+ if (queue_size_int < 4) queue_size_int = 4;
+ event_queue_.SetSize(queue_size_int);
nacl_mounts_init_ppapi(PPAPI_GetInstanceId(), PPAPI_GetInterface);
- int f1 = open(stdin_path, O_RDONLY);
- int f2 = open(stdout_path, O_WRONLY);
- int f3 = open(stderr_path, O_WRONLY);
+ int fd0 = open(stdin_path, O_RDONLY);
+ int fd1 = open(stdout_path, O_WRONLY);
+ int fd2 = open(stderr_path, O_WRONLY);
- return true;
+ return (fd0 == 0) && (fd1 == 1) && (fd2 == 2);
}
-void PPAPIInstance::HandleMessage(const pp::Var& message) {
-}
+void PPAPIInstance::HandleMessage(const pp::Var& message) {}
bool PPAPIInstance::HandleInputEvent(const pp::InputEvent& event) {
+ PPAPIEvent* event_ptr;
+
+ // Remove a stale message if one is available
+ event_ptr = static_cast<PPAPIEvent*>(event_queue_.RemoveStaleMessage());
+ delete event_ptr;
+
switch (event.GetType()) {
- case PP_INPUTEVENT_TYPE_UNDEFINED:
- break;
case PP_INPUTEVENT_TYPE_MOUSEDOWN:
- // If we do not yet have focus, return true. In return Chrome will give
- // focus to the NaCl embed.
- return !has_focus_;
- break;
- case PP_INPUTEVENT_TYPE_KEYDOWN:
- break;
case PP_INPUTEVENT_TYPE_MOUSEUP:
case PP_INPUTEVENT_TYPE_MOUSEMOVE:
case PP_INPUTEVENT_TYPE_MOUSEENTER:
- case PP_INPUTEVENT_TYPE_MOUSELEAVE:
- case PP_INPUTEVENT_TYPE_WHEEL:
+ case PP_INPUTEVENT_TYPE_MOUSELEAVE: {
+ pp::MouseInputEvent mouse_event(event);
+ PPAPIMouseEvent* mouse_ptr = new PPAPIMouseEvent;
+ mouse_ptr->button = mouse_event.GetButton();
+ mouse_ptr->location = mouse_event.GetPosition().pp_point();
+ mouse_ptr->delta = mouse_event.GetMovement().pp_point();
+ event_ptr = &mouse_ptr->event;
+ break;
+ }
+
+ case PP_INPUTEVENT_TYPE_WHEEL: {
+ pp::WheelInputEvent wheel_event(event);
+ PPAPIWheelEvent* wheel_ptr = new PPAPIWheelEvent;
+ wheel_ptr->by_page =
+ static_cast<uint32_t>(wheel_event.GetScrollByPage());
+ wheel_ptr->delta = wheel_event.GetDelta().pp_float_point();
+ event_ptr = &wheel_ptr->event;
+ break;
+ }
+
+ case PP_INPUTEVENT_TYPE_CHAR: {
+ pp::KeyboardInputEvent key_event(event);
+ PPAPICharEvent* char_ptr = new PPAPICharEvent;
+ strncpy(char_ptr->text,
+ key_event.GetCharacterText().DebugString().c_str(),
+ sizeof(char_ptr->text));
+ event_ptr = &char_ptr->event;
+ break;
+ }
+
case PP_INPUTEVENT_TYPE_RAWKEYDOWN:
- case PP_INPUTEVENT_TYPE_KEYUP:
- case PP_INPUTEVENT_TYPE_CHAR:
- case PP_INPUTEVENT_TYPE_CONTEXTMENU:
- case PP_INPUTEVENT_TYPE_IME_COMPOSITION_START:
- case PP_INPUTEVENT_TYPE_IME_COMPOSITION_UPDATE:
- case PP_INPUTEVENT_TYPE_IME_COMPOSITION_END:
- case PP_INPUTEVENT_TYPE_IME_TEXT:
+ case PP_INPUTEVENT_TYPE_KEYDOWN:
+ case PP_INPUTEVENT_TYPE_KEYUP: {
+ pp::KeyboardInputEvent key_event(event);
+ PPAPIKeyEvent* key_ptr = new PPAPIKeyEvent;
+ key_ptr->key_code = key_event.GetKeyCode();
+ event_ptr = &key_ptr->event;
+ break;
+ }
+
case PP_INPUTEVENT_TYPE_TOUCHSTART:
case PP_INPUTEVENT_TYPE_TOUCHMOVE:
case PP_INPUTEVENT_TYPE_TOUCHEND:
- case PP_INPUTEVENT_TYPE_TOUCHCANCEL:
+ case PP_INPUTEVENT_TYPE_TOUCHCANCEL: {
+ pp::TouchInputEvent touch_event(event);
+ PPAPITouchEvent* touch_ptr = new PPAPITouchEvent;
+ touch_ptr->point_count =
+ touch_event.GetTouchCount(PP_TOUCHLIST_TYPE_TOUCHES);
+ for (uint32_t cnt = 0; cnt < touch_ptr->point_count; cnt++) {
+ pp::TouchPoint *pnt = (pp::TouchPoint*) &touch_ptr->points[cnt];
+ *pnt = touch_event.GetTouchByIndex(PP_TOUCHLIST_TYPE_TOUCHES ,cnt);
+ }
+ event_ptr = &touch_ptr->event;
+ break;
+ }
+
default:
+ fprintf(stderr, "Unhandled event type %d\n", event.GetType());
return false;
}
- return false;
+
+ event_ptr->event_type = event.GetType();
+ event_ptr->time_ticks = event.GetTimeStamp();
+ event_ptr->modifiers = event.GetModifiers();
+ if (!event_queue_.AddNewMessage(event_ptr)) {
+ printf("Warning: Event Queue is full, dropping message.\n");
+ }
+ return true;
+}
+
+PPAPIEvent* PPAPIInstance::AcquireInputEvent() {
+ return static_cast<PPAPIEvent*>(event_queue_.AcquireTopMessage());
+}
+
+void PPAPIInstance::ReleaseInputEvent(PPAPIEvent* event) {
+ event_queue_.ReleaseTopMessage(event);
}
void PPAPIInstance::DidChangeView(const pp::View&) {
diff --git a/native_client_sdk/src/libraries/ppapi_main/ppapi_instance.h b/native_client_sdk/src/libraries/ppapi_main/ppapi_instance.h
index 279388e..47be29b 100644
--- a/native_client_sdk/src/libraries/ppapi_main/ppapi_instance.h
+++ b/native_client_sdk/src/libraries/ppapi_main/ppapi_instance.h
@@ -10,8 +10,12 @@
#include "ppapi/c/pp_instance.h"
#include "ppapi/cpp/fullscreen.h"
#include "ppapi/cpp/instance.h"
+#include "ppapi/cpp/message_loop.h"
-typedef std::map<std::string, std::string> PropteryMap_t;
+#include "ppapi_main/ppapi_event.h"
+#include "ppapi_main/ppapi_queue.h"
+
+typedef std::map<std::string, std::string> PropertyMap_t;
class PPAPIInstance : public pp::Instance {
public:
@@ -33,7 +37,18 @@ class PPAPIInstance : public pp::Instance {
// Called by the browser to handle incoming input events.
virtual bool HandleInputEvent(const pp::InputEvent& event);
+ // Accessors for the PPAPIQueue object. Use Acquire to fetch the top
+ // event if one is available, then release when done. Events must be
+ // acquired and released one at a time.
+ virtual PPAPIEvent* AcquireInputEvent();
+ virtual void ReleaseInputEvent(PPAPIEvent* event);
+
+ static PPAPIInstance* GetInstance();
+
protected:
+ // Called to launch ppapi_main
+ static void* StartMain(void *start_info);
+
// Called by Init to processes default and embed tag arguments prior to
// launching the 'ppapi_main' thread.
virtual bool ProcessProperties();
@@ -42,7 +57,9 @@ class PPAPIInstance : public pp::Instance {
const char* GetProperty(const char* key, const char* def = NULL);
private:
- PropteryMap_t properties_;
+ pp::MessageLoop main_loop_;
+ PropertyMap_t properties_;
+ PPAPIQueue event_queue_;
bool has_focus_;
};
diff --git a/native_client_sdk/src/libraries/ppapi_main/ppapi_instance3d.cc b/native_client_sdk/src/libraries/ppapi_main/ppapi_instance3d.cc
new file mode 100644
index 0000000..068f39f
--- /dev/null
+++ b/native_client_sdk/src/libraries/ppapi_main/ppapi_instance3d.cc
@@ -0,0 +1,232 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <fcntl.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <cstdlib>
+#include <cstring>
+#include <map>
+#include <string>
+#include <vector>
+
+#include "nacl_mounts/nacl_mounts.h"
+
+#include "ppapi/cpp/fullscreen.h"
+#include "ppapi/cpp/graphics_3d.h"
+#include "ppapi/cpp/input_event.h"
+#include "ppapi/cpp/message_loop.h"
+#include "ppapi/cpp/mouse_lock.h"
+#include "ppapi/cpp/rect.h"
+#include "ppapi/cpp/size.h"
+#include "ppapi/cpp/var.h"
+
+#include "ppapi/lib/gl/gles2/gl2ext_ppapi.h"
+#include "ppapi/lib/gl/include/GLES2/gl2.h"
+
+#include "ppapi/utility/completion_callback_factory.h"
+
+#include "ppapi_main/ppapi_instance.h"
+#include "ppapi_main/ppapi_instance3d.h"
+#include "ppapi_main/ppapi_main.h"
+
+
+static const uint32_t kReturnKeyCode = 13;
+
+
+void* PPAPI_CreateInstance3D(PP_Instance inst, const char *args[]) {
+ return static_cast<void*>(new PPAPIInstance3D(inst, args));
+}
+
+
+int32_t *PPAPIGet3DAttribs(uint32_t width, uint32_t height) {
+ static int32_t attribs[] = {
+ PP_GRAPHICS3DATTRIB_WIDTH, 0,
+ PP_GRAPHICS3DATTRIB_HEIGHT, 0,
+ PP_GRAPHICS3DATTRIB_ALPHA_SIZE, 8,
+ PP_GRAPHICS3DATTRIB_DEPTH_SIZE, 24,
+ PP_GRAPHICS3DATTRIB_STENCIL_SIZE, 8,
+ PP_GRAPHICS3DATTRIB_SAMPLES, 0,
+ PP_GRAPHICS3DATTRIB_SAMPLE_BUFFERS, 0,
+ PP_GRAPHICS3DATTRIB_NONE
+ };
+
+ attribs[1] = width;
+ attribs[3] = height;
+
+ printf("Building attribs for %dx%d.\n", width, height);
+ return attribs;
+}
+
+void PPAPIBuildContext(uint32_t width, uint32_t height) {
+ glViewport(0, 0, width, height);
+ glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+ printf("Built Context %d, %d.\n", width, height);
+}
+
+
+PPAPIInstance3D* PPAPIInstance3D::GetInstance3D() {
+ return static_cast<PPAPIInstance3D*>(PPAPI_GetInstanceObject());
+}
+
+
+void *PPAPIInstance3D::RenderLoop(void *this_ptr) {
+ PPAPIInstance3D *pInst = static_cast<PPAPIInstance3D*>(this_ptr);
+ pInst->render_loop_.AttachToCurrentThread();
+ pInst->render_loop_.Run();
+ return NULL;
+}
+
+
+void PPAPIInstance3D::Swapped(int result) {
+ if (result != 0) {
+ printf("Swapped result=%d.\n", result);
+ }
+
+ if (is_context_bound_) {
+ PPAPIRender(size_.width(), size_.height());
+ int result;
+ result = device_context_.SwapBuffers(callback_factory_.NewCallback(
+ &PPAPIInstance3D::Swapped));
+ if (result == PP_OK_COMPLETIONPENDING) return;
+ printf("Failed swap with %d.\n", result);
+ }
+
+ // Failed to draw, so add a callback for the future.
+ pp::MessageLoop::GetCurrent().PostWork(callback_factory_.NewCallback(
+ &PPAPIInstance3D::Swapped), 100);
+}
+
+void PPAPIInstance3D::BuildContext(int32_t result, const pp::Size& new_size) {
+ printf("Building context.\n");
+
+ // If already bound, try to resize to avoid the need to rebuild the context.
+ if (is_context_bound_) {
+ // If the size is correct, then just skip this request.
+ if (new_size == size_) {
+ printf("Skipped building context, same size as bound.\n");
+ return;
+ }
+ int err = device_context_.ResizeBuffers(new_size.width(),
+ new_size.height());
+
+ // Resized the context, we are done
+ if (err == PP_OK) {
+ size_ = new_size;
+ fprintf(stderr, "Resized context from %dx%d to %dx%d",
+ size_.width(), size_.height(), new_size.width(),
+ new_size.height());
+ PPAPIBuildContext(size_.width(), size_.height());
+ return;
+ }
+
+ // Failed to resize, fall through and start from scratch
+ fprintf(stderr, "Failed to resize buffer from %dx%d to %dx%d",
+ size_.width(), size_.height(), new_size.width(), new_size.height());
+
+ is_context_bound_ = false;
+ }
+
+ printf("Calling create context....\n");
+ size_ = new_size;
+ device_context_ = pp::Graphics3D(this, PPAPIGet3DAttribs(size_.width(),
+ size_.height()));
+ printf("Got Context!\n");
+ is_context_bound_ = BindGraphics(device_context_);
+ printf("Context is bound=%d\n", is_context_bound_);
+
+ // The the context regardless to make sure we have a valid one
+ glSetCurrentContextPPAPI(device_context_.pp_resource());
+ if (is_context_bound_) {
+ PPAPIBuildContext(size_.width(), size_.height());
+ device_context_.SwapBuffers(callback_factory_.NewCallback(
+ &PPAPIInstance3D::Swapped));
+ } else {
+ fprintf(stderr, "Failed to bind context for %dx%d.\n", size_.width(),
+ size_.height());
+ }
+}
+
+PPAPIInstance3D::PPAPIInstance3D(PP_Instance instance, const char *args[])
+ : PPAPIInstance(instance, args),
+ mouse_locked_(false),
+ callback_factory_(this),
+ fullscreen_(this),
+ is_context_bound_(false),
+ was_fullscreen_(false),
+ render_loop_(this),
+ main_thread_3d_(true) {
+ glInitializePPAPI(pp::Module::Get()->get_browser_interface());
+}
+
+
+PPAPIInstance3D::~PPAPIInstance3D() {
+ if (is_context_bound_) {
+ is_context_bound_ = false;
+ // Cleanup code?
+ }
+}
+
+bool PPAPIInstance3D::Init(uint32_t arg,
+ const char* argn[],
+ const char* argv[]) {
+ if (!PPAPIInstance::Init(arg, argn, argv)) {
+ return false;
+ }
+
+ for (uint32_t a=0; a < arg; a++) {
+ printf("%s=%s\n", argn[a], argv[a]);
+ }
+
+ const char *use_main = GetProperty("pm_main3d", "true");
+ main_thread_3d_ = !strcasecmp(use_main, "true");
+ printf("Using 3D on main thread = %s.\n", use_main);
+ if (!main_thread_3d_) {
+ pthread_t render_thread;
+ int ret = pthread_create(&render_thread, NULL, RenderLoop,
+ static_cast<void*>(this));
+ return ret == 0;
+ }
+ return true;
+}
+
+void PPAPIInstance3D::DidChangeView(const pp::View& view) {
+ pp::Size new_size = view.GetRect().size();
+ printf("View changed: %dx%d\n", new_size.width(), new_size.height());
+
+ // Build or update the 3D context when the view changes.
+ if (main_thread_3d_) {
+ // If using the main thread, update the context immediately
+ BuildContext(0, new_size);
+ } else {
+ // If using a seperate thread, then post the message so we can build the
+ // context on the correct thread.
+ render_loop_.PostWork(callback_factory_.NewCallback(
+ &PPAPIInstance3D::BuildContext, new_size));
+ }
+}
+
+bool PPAPIInstance3D::ToggleFullscreen() {
+ // Ignore switch if in transition
+ if (!is_context_bound_)
+ return false;
+
+ if (fullscreen_.IsFullscreen()) {
+ if (!fullscreen_.SetFullscreen(false)) {
+ printf("Could not leave fullscreen mode\n");
+ return false;
+ }
+ } else {
+ if (!fullscreen_.SetFullscreen(true)) {
+ printf("Could not enter fullscreen mode\n");
+ return false;
+ }
+ }
+ return true;
+}
diff --git a/native_client_sdk/src/libraries/ppapi_main/ppapi_instance3d.h b/native_client_sdk/src/libraries/ppapi_main/ppapi_instance3d.h
new file mode 100644
index 0000000..8c392809
--- /dev/null
+++ b/native_client_sdk/src/libraries/ppapi_main/ppapi_instance3d.h
@@ -0,0 +1,59 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_MAIN_PPAPI_INSTANCE3D_H_
+#define PPAPI_MAIN_PPAPI_INSTANCE3D_H_
+
+#include <map>
+
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/cpp/fullscreen.h"
+#include "ppapi/cpp/graphics_3d.h"
+#include "ppapi/cpp/input_event.h"
+#include "ppapi/cpp/instance.h"
+#include "ppapi/cpp/message_loop.h"
+#include "ppapi/cpp/mouse_lock.h"
+#include "ppapi/utility/completion_callback_factory.h"
+
+#include "ppapi_main/ppapi_instance.h"
+
+
+class PPAPIInstance3D : public PPAPIInstance {
+ public:
+ PPAPIInstance3D(PP_Instance instance, const char *args[]);
+ virtual ~PPAPIInstance3D();
+
+ // Called during initialization
+ virtual bool Init(uint32_t arg, const char* argn[], const char* argv[]);
+
+ // Called whenever the in-browser window changes size.
+ virtual void DidChangeView(const pp::View& view);
+
+ // Called when we need to rebuild the context
+ virtual void BuildContext(int32_t result, const pp::Size& new_size);
+
+ // Called whenever a swap takes place
+ virtual void Swapped(int result);
+
+ // Toggle in and out of Fullscreen mode
+ virtual bool ToggleFullscreen();
+
+ static PPAPIInstance3D* GetInstance3D();
+
+ protected:
+ static void *RenderLoop(void *this_ptr);
+
+ pp::CompletionCallbackFactory<PPAPIInstance3D> callback_factory_;
+ pp::Fullscreen fullscreen_;
+ pp::Graphics3D device_context_;
+ pp::Size size_;
+ pp::MessageLoop render_loop_;
+ bool is_context_bound_;
+ bool was_fullscreen_;
+ bool mouse_locked_;
+ bool main_thread_3d_;
+};
+
+
+#endif // PPAPI_MAIN_PPAPI_INSTANCE3D_H_
diff --git a/native_client_sdk/src/libraries/ppapi_main/ppapi_main.cc b/native_client_sdk/src/libraries/ppapi_main/ppapi_main.cc
index c3c7392..3d666c9 100644
--- a/native_client_sdk/src/libraries/ppapi_main/ppapi_main.cc
+++ b/native_client_sdk/src/libraries/ppapi_main/ppapi_main.cc
@@ -10,6 +10,7 @@
#include "ppapi/cpp/module.h"
#include "ppapi_main/ppapi_instance.h"
+#include "ppapi_main/ppapi_instance3d.h"
#include "ppapi_main/ppapi_main.h"
@@ -17,6 +18,10 @@ static pp::Instance* s_Instance = NULL;
// Helpers to access PPAPI interfaces
+void* PPAPI_GetInstanceObject() {
+ return s_Instance;
+}
+
PP_Instance PPAPI_GetInstanceId() {
return s_Instance->pp_instance();
}
@@ -25,11 +30,19 @@ const void* PPAPI_GetInterface(const char *name) {
return pp::Module::Get()->GetBrowserInterface(name);
}
-
void* PPAPI_CreateInstance(PP_Instance inst, const char *args[]) {
return static_cast<void*>(new PPAPIInstance(inst, args));
}
+PPAPIEvent* PPAPI_AcquireEvent() {
+ return static_cast<PPAPIInstance*>(s_Instance)->AcquireInputEvent();
+}
+
+void PPAPI_ReleaseEvent(PPAPIEvent* event) {
+ static_cast<PPAPIInstance*>(s_Instance)->ReleaseInputEvent(event);
+}
+
+
/// The Module class. The browser calls the CreateInstance() method to create
/// an instance of your NaCl module on the web page. The browser creates a new
/// instance for each <embed> tag with type="application/x-nacl".
diff --git a/native_client_sdk/src/libraries/ppapi_main/ppapi_main.h b/native_client_sdk/src/libraries/ppapi_main/ppapi_main.h
index 01958384..7f653d1 100644
--- a/native_client_sdk/src/libraries/ppapi_main/ppapi_main.h
+++ b/native_client_sdk/src/libraries/ppapi_main/ppapi_main.h
@@ -7,6 +7,8 @@
#include "ppapi/c/pp_instance.h"
#include "ppapi/c/pp_module.h"
+#include "ppapi_main/ppapi_event.h"
+
#include "utils/macros.h"
EXTERN_C_BEGIN
@@ -18,6 +20,7 @@ int ppapi_main(int argc, const char *argv[]);
void* UserCreateInstance(PP_Instance inst);
// Helpers to access PPAPI interfaces
+void* PPAPI_GetInstanceObject();
PP_Instance PPAPI_GetInstanceId();
const void* PPAPI_GetInterface(const char *name);
@@ -26,13 +29,23 @@ void* PPAPI_CreateInstance(PP_Instance inst, const char *args[]);
void* PPAPI_CreateInstance2D(PP_Instance inst, const char *args[]);
void* PPAPI_CreateInstance3D(PP_Instance inst, const char *args[]);
+// Event APIs
+PPAPIEvent* PPAPI_AcquireEvent();
+void PPAPI_ReleaseEvent(PPAPIEvent* event);
+
+
+// Functions for 3D instances
+int32_t *PPAPIGet3DAttribs(uint32_t width, uint32_t height);
+void PPAPIBuildContext(uint32_t width, uint32_t height);
+void PPAPIRender(uint32_t width, uint32_t height);
+
EXTERN_C_END
#define PPAPI_MAIN_DEFAULT_ARGS \
{ \
- "PM_STDIN", "/dev/null", \
- "PM_STDIO", "/dev/console0", \
- "PM_STDERR", "/dev/console3", \
+ "pm_stdin", "/dev/null", \
+ "pm_stdout", "/dev/console0", \
+ "pm_stderr", "/dev/console3", \
NULL, NULL \
}
@@ -46,6 +59,9 @@ void* UserCreateInstance(PP_Instance inst) { \
#define PPAPI_MAIN_WITH_DEFAULT_ARGS \
PPAPI_MAIN_USE(PPAPI_CreateInstance, PPAPI_MAIN_DEFAULT_ARGS)
+#define PPAPI_MAIN_3D_WITH_DEFAULT_ARGS \
+ PPAPI_MAIN_USE(PPAPI_CreateInstance3D, PPAPI_MAIN_DEFAULT_ARGS)
+
#define PPAPI_MAIN_WITH_ARGS(args) \
PPAPI_MAIN_USE(PPAPI_CreateInstance, args)
diff --git a/native_client_sdk/src/libraries/ppapi_main/ppapi_queue.cc b/native_client_sdk/src/libraries/ppapi_main/ppapi_queue.cc
new file mode 100644
index 0000000..ff5ed38
--- /dev/null
+++ b/native_client_sdk/src/libraries/ppapi_main/ppapi_queue.cc
@@ -0,0 +1,97 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "ppapi_main/ppapi_queue.h"
+
+PPAPIQueue::PPAPIQueue()
+ : read_(0),
+ write_(0),
+ freed_(0),
+ size_(0),
+ array_(NULL) { }
+
+PPAPIQueue::~PPAPIQueue() {
+ // Messages may be leaked if the queue is not empty.
+ assert(read_ == write_);
+
+ delete[] array_;
+}
+
+bool PPAPIQueue::SetSize(uint32_t queue_size) {
+ assert(queue_size > 0);
+
+ if (array_) return false;
+
+ array_ = new void*[queue_size];
+ size_ = queue_size;
+
+ memset(array_, 0, sizeof(void*) * queue_size);
+ return true;
+}
+
+bool PPAPIQueue::AddNewMessage(void* msg) {
+ // Writting a NULL message is illegal
+ assert(array_ != NULL);
+ assert(msg != NULL);
+
+ // If the slot not empty, the queue must be full. Calling RemoveStaleMessage
+ // may create space by freeing messages that have already been read.
+ if (array_[write_] != NULL) return false;
+
+ // Write to the spot
+ array_[write_] = msg;
+
+ // Fence to make sure the payload and payload pointer are visible.
+ // Since Win32 is x86 which provides ordered writes, we don't need to
+ // synchronize in that case.
+#ifndef WIN32
+ __sync_synchronize();
+#endif
+
+ // Increment the write pointer, to signal it's readable.
+ write_ = (write_ + 1) % size_;
+ return true;
+}
+
+void* PPAPIQueue::RemoveStaleMessage() {
+ assert(array_ != NULL);
+
+ // If freed and read pointer are equal, this hasn't been read yet
+ if (freed_ == read_) return NULL;
+
+ assert(array_[freed_] != NULL);
+
+ void* ret = array_[freed_];
+ array_[freed_] = NULL;
+
+ freed_ = (freed_ + 1) % size_;
+ return ret;
+}
+
+void* PPAPIQueue::AcquireTopMessage() {
+ // Assert that we aren't already reading a message.
+ assert(last_msg_ == NULL);
+
+ // If read and write pointers are equal, the queue is empty.
+ if (read_ == write_) return NULL;
+
+ // Track the last message to look for illegal API use.
+ last_msg_ = array_[read_];
+ return last_msg_;
+}
+
+void PPAPIQueue::ReleaseTopMessage(void* msg) {
+ // Verify we currently acquire message.
+ assert(msg != NULL);
+ assert(msg == last_msg_);
+
+ last_msg_ = NULL;
+
+ // Signal that the message can be freed.
+ read_ = (read_ + 1) % size_;
+}
diff --git a/native_client_sdk/src/libraries/ppapi_main/ppapi_queue.h b/native_client_sdk/src/libraries/ppapi_main/ppapi_queue.h
new file mode 100644
index 0000000..b40c3ec
--- /dev/null
+++ b/native_client_sdk/src/libraries/ppapi_main/ppapi_queue.h
@@ -0,0 +1,84 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+
+#ifndef PPAPI_MAIN_PPAPI_QUEUE_H
+#define PPAPI_MAIN_PPAPI_QUEUE_H
+
+#include <stdint.h>
+
+//
+// PPAPIQueue
+//
+// PPAPIQueue is a single producer/single consumer lockless queue. This
+// implementation is PPAPI friendly because it prevents the main thread from
+// ever needing to lock. In addition, allocation and destruction of messages
+// happens on the same thread, allowing for lockless message allocation as well.
+//
+// Messages pass through four states in order:
+// AddNewMessage - The message is added to the queue by the producer
+// and the memory is fenced to ensure it is visible. Once the fence
+// returns, the write pointer is incremented to signal it's available to
+// the consumer. NOTE: NULL messages are illegal.
+//
+// AcquireTopMessage - Next the message is acquired by the consumer thread.
+// At this point, the consumer is considered to be examining the payload so
+// we do not increment the read pointer yet to prevent deletion. NOTE: it
+// is illegal to acquire the next message until the previous one is released.
+//
+// ReleaseTopMessage - Now the consumer signals that it is no longer looking
+// at the message by incremented the read pointer. The producer is free to
+// release or reuse the payload.
+//
+// RemoveStaleMessage - The message is no longer visible to the consumer, so
+// it is returned to the producer to be reused or destroyed. It's location
+// in the queue is set to NULL to signal that a new message may be added in
+// that slot.
+//
+class PPAPIQueue {
+ public:
+ PPAPIQueue();
+ ~PPAPIQueue();
+
+ //
+ // Producer API
+ //
+ // First, the producer must set the queue size before any operation can
+ // take place. Next, before adding a message, clear space in the queue,
+ // by removing stale messages. Adding a new message will return TRUE if
+ // space is available, otherwise FALSE is returned and it's up to the
+ // application developer to decide what to do.
+ //
+ bool SetSize(uint32_t queue_size);
+ bool AddNewMessage(void* msg);
+ void* RemoveStaleMessage();
+
+ //
+ // Consumer API
+ //
+ // The reader will attempt to Acquire the top message, if one is not
+ // available NULL will be returned. Once the consumer is done with the
+ // message, ReleaseTopMessage is called to signal that the payload is no
+ // longer visible to the consumer and can be recycled or destroyed.
+ // Since messages are freed in order, it is recquired that messages are
+ // consumed in order. For this reason, it is illegal to call Acquire again
+ // after a non-NULL message pointer is returned, until Release is called on
+ // the old message. This means the consumer can only look at one message
+ // at a time. To look at multiple messages at once, the consumer would
+ // need to make a copy and release the top message.
+ //
+ void* AcquireTopMessage();
+ void ReleaseTopMessage(void* msg);
+
+ private:
+ uint32_t read_;
+ uint32_t write_;
+ uint32_t freed_;
+ uint32_t size_;
+ void* last_msg_;
+ void** array_;
+};
+
+
+#endif // PPAPI_MAIN_PPAPI_QUEUE_H \ No newline at end of file