summaryrefslogtreecommitdiff
path: root/platform/nacl
diff options
context:
space:
mode:
Diffstat (limited to 'platform/nacl')
-rw-r--r--platform/nacl/SCsub30
-rw-r--r--platform/nacl/audio_driver_nacl.cpp106
-rw-r--r--platform/nacl/audio_driver_nacl.h63
-rw-r--r--platform/nacl/context_gl_nacl.cpp67
-rw-r--r--platform/nacl/context_gl_nacl.h58
-rw-r--r--platform/nacl/detect.py71
-rw-r--r--platform/nacl/geturl_handler.cpp150
-rw-r--r--platform/nacl/geturl_handler.h115
-rw-r--r--platform/nacl/godot_module.cpp332
-rw-r--r--platform/nacl/godot_nacl.cpp80
-rw-r--r--platform/nacl/html/check_browser.js178
-rw-r--r--platform/nacl/html/godot_nacl.nmf6
-rw-r--r--platform/nacl/html/icon_128.pngbin0 -> 2255 bytes
-rw-r--r--platform/nacl/html/icon_16.pngbin0 -> 850 bytes
-rw-r--r--platform/nacl/html/index.html258
-rw-r--r--platform/nacl/html/manifest.json19
-rw-r--r--platform/nacl/logo.pngbin0 -> 2705 bytes
-rw-r--r--platform/nacl/nacl_keycodes.h422
-rw-r--r--platform/nacl/opengl_context.cpp123
-rw-r--r--platform/nacl/opengl_context.h124
-rw-r--r--platform/nacl/os_nacl.cpp529
-rw-r--r--platform/nacl/os_nacl.h156
-rw-r--r--platform/nacl/pepper_main.cpp541
-rw-r--r--platform/nacl/platform_config.h29
24 files changed, 3457 insertions, 0 deletions
diff --git a/platform/nacl/SCsub b/platform/nacl/SCsub
new file mode 100644
index 0000000000..ac01752dbb
--- /dev/null
+++ b/platform/nacl/SCsub
@@ -0,0 +1,30 @@
+Import('env')
+
+nacl_lib = [
+
+ 'os_nacl.cpp',
+ 'audio_driver_nacl.cpp',
+ 'godot_nacl.cpp',
+ #'pepper_main.cpp',
+ 'opengl_context.cpp',
+ 'godot_module.cpp',
+ 'geturl_handler.cpp',
+]
+
+nacl_posix = [
+
+ '#drivers/unix/thread_posix.cpp',
+ '#drivers/unix/mutex_posix.cpp',
+ '#drivers/unix/semaphore_posix.cpp',
+]
+
+posix_lib = []
+for f in nacl_posix:
+ posix_lib.append(env.Object(f, CPPFLAGS = env['CPPFLAGS']+['-DUNIX_ENABLED'], OBJSUFFIX = '.posix'+env['OBJSUFFIX']))
+
+prog = env.Program('#bin/godot_nacl', nacl_lib + posix_lib)
+
+if (env['nacl_arch'] == 'i686'):
+ env.Alias("nacl_32", prog)
+if (env['nacl_arch'] == 'x86_64'):
+ env.Alias("nacl_64", prog)
diff --git a/platform/nacl/audio_driver_nacl.cpp b/platform/nacl/audio_driver_nacl.cpp
new file mode 100644
index 0000000000..8f1861eee3
--- /dev/null
+++ b/platform/nacl/audio_driver_nacl.cpp
@@ -0,0 +1,106 @@
+/*************************************************************************/
+/* audio_driver_nacl.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#include "audio_driver_nacl.h"
+
+#include "ppapi/cpp/instance.h"
+
+extern pp::Instance* godot_instance;
+
+const char* AudioDriverNacl::get_name() const {
+
+ return "Nacl";
+}
+
+void AudioDriverNacl::output_callback(void* samples, uint32_t buffer_size, void* data) {
+
+ AudioDriverNacl* ad = (AudioDriverNacl*)data;
+ int16_t* out = (int16_t*)samples;
+
+ ad->lock();
+ ad->audio_server_process(ad->sample_frame_count_, ad->samples_in);
+ ad->unlock();
+
+ for (int i=0; i<ad->sample_count; i++) {
+
+ out[i] = ad->samples_in[i]>>16;
+ };
+
+};
+
+Error AudioDriverNacl::init(){
+
+ int frame_size = 4096;
+ sample_frame_count_ = pp::AudioConfig::RecommendSampleFrameCount(godot_instance,PP_AUDIOSAMPLERATE_44100, frame_size);
+ sample_count = sample_frame_count_ * 2;
+
+ audio_ = pp::Audio(godot_instance,
+ pp::AudioConfig(godot_instance,
+ PP_AUDIOSAMPLERATE_44100,
+ sample_frame_count_),
+ &AudioDriverNacl::output_callback,
+ this);
+
+ samples_in = memnew_arr(int32_t, sample_frame_count_ * 2);
+
+ return OK;
+}
+void AudioDriverNacl::start(){
+
+ audio_.StartPlayback();
+}
+int AudioDriverNacl::get_mix_rate() const {
+
+ return 44100;
+}
+AudioDriverSW::OutputFormat AudioDriverNacl::get_output_format() const{
+
+ return OUTPUT_STEREO;
+}
+void AudioDriverNacl::lock(){
+
+}
+void AudioDriverNacl::unlock() {
+
+
+}
+void AudioDriverNacl::finish(){
+
+ audio_.StopPlayback();
+}
+
+
+AudioDriverNacl::AudioDriverNacl() {
+}
+
+AudioDriverNacl::~AudioDriverNacl() {
+
+ memdelete_arr(samples_in);
+}
+
+
diff --git a/platform/nacl/audio_driver_nacl.h b/platform/nacl/audio_driver_nacl.h
new file mode 100644
index 0000000000..4a45d0bb4b
--- /dev/null
+++ b/platform/nacl/audio_driver_nacl.h
@@ -0,0 +1,63 @@
+/*************************************************************************/
+/* audio_driver_nacl.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#ifndef AUDIO_DRIVER_NACL_H
+#define AUDIO_DRIVER_NACL_H
+
+#include "servers/audio/audio_server_sw.h"
+
+#include "ppapi/cpp/audio.h"
+
+class AudioDriverNacl : public AudioDriverSW {
+
+ static void output_callback(void* samples, uint32_t buffer_size, void* data);
+
+ int32_t* samples_in;
+ int sample_frame_count_;
+ int sample_count;
+ pp::Audio audio_;
+
+public:
+
+ virtual const char* get_name() const;
+
+ virtual Error init();
+ virtual void start();
+ virtual int get_mix_rate() const ;
+ virtual OutputFormat get_output_format() const;
+ virtual void lock();
+ virtual void unlock();
+ virtual void finish();
+
+
+ AudioDriverNacl();
+ ~AudioDriverNacl();
+};
+
+#endif // AUDIO_DRIVER_NACL_H
+
diff --git a/platform/nacl/context_gl_nacl.cpp b/platform/nacl/context_gl_nacl.cpp
new file mode 100644
index 0000000000..70cf01a16e
--- /dev/null
+++ b/platform/nacl/context_gl_nacl.cpp
@@ -0,0 +1,67 @@
+/*************************************************************************/
+/* context_gl_nacl.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#include "context_gl_nacl.h"
+
+#include <nacl/npapi.h>
+#include <nacl/npruntime.h>
+#include <nacl/npapi_extensions.h>
+#include <nacl/npupp.h>
+#include <pgl/pgl.h>
+#include <GLES2/gl2.h>
+
+void ContextGLNacl::make_current() {
+
+};
+
+int ContextGLNacl::get_window_width() {
+
+};
+
+int ContextGLNacl::get_window_height() {
+
+};
+
+void ContextGLNacl::swap_buffers() {
+
+};
+
+Error ContextGLNacl::initialize() {
+
+};
+
+
+ContextGLNacl::ContextGLNacl() {
+
+
+};
+
+ContextGLNacl::~ContextGLNacl() {
+
+};
+
diff --git a/platform/nacl/context_gl_nacl.h b/platform/nacl/context_gl_nacl.h
new file mode 100644
index 0000000000..a5cf7a728c
--- /dev/null
+++ b/platform/nacl/context_gl_nacl.h
@@ -0,0 +1,58 @@
+/*************************************************************************/
+/* context_gl_nacl.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#ifndef CONTEXT_GL_NACL_H
+#define CONTEXT_GL_NACL_H
+
+#include "drivers/gl_context/context_gl.h"
+
+class NPDevice;
+
+class ContextGLNacl : public ContextGL {
+
+ enum {
+ COMMAND_BUFFER_SIZE = 1024 * 1024,
+ };
+
+ NPDevice* device3d_;
+
+public:
+
+ virtual void make_current();
+
+ virtual int get_window_width();
+ virtual int get_window_height();
+ virtual void swap_buffers();
+
+ virtual Error initialize();
+
+ ContextGLNacl();
+ ~ContextGLNacl();
+};
+
+#endif // CONTEXT_GL_NACL_H
diff --git a/platform/nacl/detect.py b/platform/nacl/detect.py
new file mode 100644
index 0000000000..f8849cfd25
--- /dev/null
+++ b/platform/nacl/detect.py
@@ -0,0 +1,71 @@
+import os
+import sys
+
+def is_active():
+ return True
+
+def get_name():
+ return "NaCl"
+
+def can_build():
+
+ import os
+ if not os.environ.has_key("NACLPATH"):
+ return False
+ return True
+
+def get_opts():
+
+ return [
+ ('NACLPATH', 'the path to nacl', os.environ.get("NACLPATH", 0)),
+ ('nacl_arch', 'The architecture for Nacl build (can be i686 or x86_64', 'i686'),
+ ]
+
+def get_flags():
+
+ return [
+ ('nedmalloc', 'no'),
+ ('tools', 'no'),
+ ]
+
+
+
+def configure(env):
+
+ env.Append(CPPPATH=['#platform/nacl'])
+
+ env['OBJSUFFIX'] = ".nacl.${nacl_arch}.o"
+ env['LIBSUFFIX'] = ".nacl.${nacl_arch}.a"
+ env['PROGSUFFIX'] = ".${nacl_arch}.nexe"
+
+ env['ENV']['PATH'] = env['ENV']['PATH']+":"+env['NACLPATH']+"/toolchain/linux_x86_newlib/bin"
+
+ env['CC'] = '${nacl_arch}-nacl-gcc'
+ env['CXX'] = '${nacl_arch}-nacl-g++'
+ env['AR'] = '${nacl_arch}-nacl-ar'
+
+ env.Append(CCFLAGS=['-fexceptions', '-Wno-long-long', '-pthread', '-DXP_UNIX'])
+
+ env.Append(CPPPATH=env['NACLPATH'])
+
+ if (env["target"]=="release"):
+
+ env.Append(CCFLAGS=['-O2','-ffast-math','-fomit-frame-pointer', '-ffunction-sections', '-fdata-sections', '-fno-default-inline'])
+
+ elif (env["target"]=="debug"):
+
+ env.Append(CCFLAGS=['-g', '-O0', '-Wall','-DDEBUG_ENABLED'])
+
+
+ elif (env["target"]=="profile"):
+
+ env.Append(CCFLAGS=['-g','-pg'])
+ env.Append(LINKFLAGS=['-pg'])
+
+ env.Append(CCFLAGS=['-DNACL_ENABLED', '-DGLES2_ENABLED'])
+
+ env.Append(LIBFLAGS=['m32'])
+ env.Append(LIBS=env.Split('ppapi ppapi_cpp pthread srpc ppapi_gles22'))
+
+ import methods
+ env.Append( BUILDERS = { 'GLSL120GLES' : env.Builder(action = methods.build_gles2_headers, suffix = 'glsl.h',src_suffix = '.glsl') } )
diff --git a/platform/nacl/geturl_handler.cpp b/platform/nacl/geturl_handler.cpp
new file mode 100644
index 0000000000..4873d691ce
--- /dev/null
+++ b/platform/nacl/geturl_handler.cpp
@@ -0,0 +1,150 @@
+/*************************************************************************/
+/* geturl_handler.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#include "geturl_handler.h"
+
+#include "core/os/copymem.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/c/ppb_instance.h"
+#include "ppapi/cpp/module.h"
+#include "ppapi/cpp/var.h"
+
+void GetURLHandler::Start() {
+ pp::CompletionCallback cc =
+ cc_factory_.NewCallback(&GetURLHandler::OnOpen);
+ url_loader_.Open(url_request_, cc);
+}
+
+void GetURLHandler::OnOpen(int32_t result) {
+ if (result != PP_OK) {
+ status = STATUS_ERROR;
+ return;
+ }
+ // Here you would process the headers. A real program would want to at least
+ // check the HTTP code and potentially cancel the request.
+ // pp::URLResponseInfo response = loader_.GetResponseInfo();
+
+ // Start streaming.
+ ReadBody();
+}
+
+void GetURLHandler::AppendDataBytes(const char* buffer, int32_t num_bytes) {
+ if (num_bytes <= 0)
+ return;
+ // Make sure we don't get a buffer overrun.
+ num_bytes = std::min(READ_BUFFER_SIZE, num_bytes);
+ int ofs = data.size();
+ data.resize(ofs + num_bytes);
+ copymem(&data[ofs], buffer, num_bytes);
+}
+
+void GetURLHandler::OnRead(int32_t result) {
+ if (result == PP_OK) {
+ // Streaming the file is complete.
+ status = STATUS_COMPLETED;
+ instance_->HandleMessage("package_finished");
+ instance_->HandleMessage(0);
+ printf("completed!\n");
+ } else if (result > 0) {
+ // The URLLoader just filled "result" number of bytes into our buffer.
+ // Save them and perform another read.
+ AppendDataBytes(buffer_, result);
+ ReadBody();
+ } else {
+ // A read error occurred.
+ status = STATUS_ERROR;
+ ERR_FAIL_COND(result < 0);
+ }
+}
+
+void GetURLHandler::ReadBody() {
+ // Note that you specifically want an "optional" callback here. This will
+ // allow ReadBody() to return synchronously, ignoring your completion
+ // callback, if data is available. For fast connections and large files,
+ // reading as fast as we can will make a large performance difference
+ // However, in the case of a synchronous return, we need to be sure to run
+ // the callback we created since the loader won't do anything with it.
+ pp::CompletionCallback cc =
+ cc_factory_.NewOptionalCallback(&GetURLHandler::OnRead);
+ int32_t result = PP_OK;
+ do {
+ result = url_loader_.ReadResponseBody(buffer_, sizeof(buffer_), cc);
+ // Handle streaming data directly. Note that we *don't* want to call
+ // OnRead here, since in the case of result > 0 it will schedule
+ // another call to this function. If the network is very fast, we could
+ // end up with a deeply recursive stack.
+ if (result > 0) {
+ AppendDataBytes(buffer_, result);
+ }
+ } while (result > 0);
+
+ if (result != PP_OK_COMPLETIONPENDING) {
+ // Either we reached the end of the stream (result == PP_OK) or there was
+ // an error. We want OnRead to get called no matter what to handle
+ // that case, whether the error is synchronous or asynchronous. If the
+ // result code *is* COMPLETIONPENDING, our callback will be called
+ // asynchronously.
+ cc.Run(result);
+ }
+}
+
+GetURLHandler::Status GetURLHandler::get_status() const {
+
+ return status;
+};
+
+Vector<uint8_t> GetURLHandler::get_data() const {
+
+ return data;
+};
+
+int GetURLHandler::get_bytes_read() const {
+
+ return data.size();
+};
+
+GetURLHandler::GetURLHandler(pp::Instance* instance,
+ const String& url)
+ : instance_(instance),
+ url_(url),
+ url_request_(instance),
+ url_loader_(instance),
+ cc_factory_(this) {
+ url_request_.SetURL(std::string(url.utf8().get_data()));
+ url_request_.SetMethod("GET");
+ status = STATUS_NONE;
+ printf("url handler for url %ls!\n", url.c_str());
+}
+
+GetURLHandler::~GetURLHandler() {
+}
+
+
diff --git a/platform/nacl/geturl_handler.h b/platform/nacl/geturl_handler.h
new file mode 100644
index 0000000000..44086ae7c1
--- /dev/null
+++ b/platform/nacl/geturl_handler.h
@@ -0,0 +1,115 @@
+/*************************************************************************/
+/* geturl_handler.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#ifndef EXAMPLES_GETURL_GETURL_HANDLER_H_
+#define EXAMPLES_GETURL_GETURL_HANDLER_H_
+
+#include "core/ustring.h"
+#include "core/vector.h"
+#include "ppapi/cpp/completion_callback.h"
+#include "ppapi/cpp/url_loader.h"
+#include "ppapi/cpp/url_request_info.h"
+#include "ppapi/cpp/instance.h"
+#include "ppapi/utility/completion_callback_factory.h"
+
+#define READ_BUFFER_SIZE 32768
+
+// GetURLHandler is used to download data from |url|. When download is
+// finished or when an error occurs, it posts a message back to the browser
+// with the results encoded in the message as a string and self-destroys.
+//
+// EXAMPLE USAGE:
+// GetURLHandler* handler* = GetURLHandler::Create(instance,url);
+// handler->Start();
+//
+class GetURLHandler {
+
+public:
+
+ enum Status {
+
+ STATUS_NONE,
+ STATUS_IN_PROGRESS,
+ STATUS_COMPLETED,
+ STATUS_ERROR,
+ };
+
+private:
+
+ Status status;
+
+ // Callback fo the pp::URLLoader::Open().
+ // Called by pp::URLLoader when response headers are received or when an
+ // error occurs (in response to the call of pp::URLLoader::Open()).
+ // Look at <ppapi/c/ppb_url_loader.h> and
+ // <ppapi/cpp/url_loader.h> for more information about pp::URLLoader.
+ void OnOpen(int32_t result);
+
+ // Callback fo the pp::URLLoader::ReadResponseBody().
+ // |result| contains the number of bytes read or an error code.
+ // Appends data from this->buffer_ to this->url_response_body_.
+ void OnRead(int32_t result);
+
+ // Reads the response body (asynchronously) into this->buffer_.
+ // OnRead() will be called when bytes are received or when an error occurs.
+ void ReadBody();
+
+ // Append data bytes read from the URL onto the internal buffer. Does
+ // nothing if |num_bytes| is 0.
+ void AppendDataBytes(const char* buffer, int32_t num_bytes);
+
+ pp::Instance* instance_; // Weak pointer.
+ String url_; // URL to be downloaded.
+ pp::URLRequestInfo url_request_;
+ pp::URLLoader url_loader_; // URLLoader provides an API to download URLs.
+ char buffer_[READ_BUFFER_SIZE]; // Temporary buffer for reads.
+ Vector<uint8_t> data; // Contains accumulated downloaded data.
+ pp::CompletionCallbackFactory<GetURLHandler> cc_factory_;
+ bool complete;
+
+ GetURLHandler(const GetURLHandler&);
+ void operator=(const GetURLHandler&);
+
+public:
+ // Creates instance of GetURLHandler on the heap.
+ // GetURLHandler objects shall be created only on the heap (they
+ // self-destroy when all data is in).
+ // Initiates page (URL) download.
+ void Start();
+
+ Status get_status() const;
+ Vector<uint8_t> get_data() const;
+
+ int get_bytes_read() const;
+
+ GetURLHandler(pp::Instance* instance_, const String& url);
+ ~GetURLHandler();
+};
+
+#endif // EXAMPLES_GETURL_GETURL_HANDLER_H_
+
diff --git a/platform/nacl/godot_module.cpp b/platform/nacl/godot_module.cpp
new file mode 100644
index 0000000000..b5a049d9bf
--- /dev/null
+++ b/platform/nacl/godot_module.cpp
@@ -0,0 +1,332 @@
+/*************************************************************************/
+/* godot_module.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#include "opengl_context.h"
+
+#include <cstdlib>
+#include <cstring>
+#include <string>
+#include <vector>
+
+#include "ppapi/cpp/instance.h"
+#include "ppapi/cpp/module.h"
+#include "ppapi/gles2/gl2ext_ppapi.h"
+
+#include "ppapi/cpp/rect.h"
+#include "ppapi/cpp/size.h"
+#include "ppapi/cpp/var.h"
+#include "geturl_handler.h"
+
+#include "core/variant.h"
+#include "os_nacl.h"
+
+extern int nacl_main(int argc, const char** argn, const char** argv);
+extern void nacl_cleanup();
+
+static String pkg_url;
+
+pp::Instance* godot_instance = NULL;
+
+struct StateData {
+ int arg_count;
+ Array args;
+ String method;
+};
+
+extern OSNacl* os_nacl;
+
+class GodotInstance : public pp::Instance {
+
+ enum State {
+ STATE_METHOD,
+ STATE_PARAM_COUNT,
+ STATE_PARAMS,
+ STATE_CALL,
+ };
+
+ State state;
+ StateData* sd;
+ SharedOpenGLContext opengl_context_;
+ int width;
+ int height;
+
+ #define MAX_ARGS 64
+ uint32_t init_argc;
+ char* init_argn[MAX_ARGS];
+ char* init_argv[MAX_ARGS];
+
+ bool package_loaded;
+ GetURLHandler* package_pending;
+
+public:
+ explicit GodotInstance(PP_Instance instance) : pp::Instance(instance) {
+ printf("GodotInstance!\n");
+ state = STATE_METHOD;
+ RequestInputEvents(PP_INPUTEVENT_CLASS_MOUSE | PP_INPUTEVENT_CLASS_KEYBOARD | PP_INPUTEVENT_CLASS_WHEEL | PP_INPUTEVENT_CLASS_TOUCH);
+ sd = NULL;
+ package_pending = NULL;
+ package_loaded = false;
+ godot_instance = this;
+ }
+ virtual ~GodotInstance() {
+
+ nacl_cleanup();
+ }
+
+ /// Called by the browser to handle the postMessage() call in Javascript.
+ /// Detects which method is being called from the message contents, and
+ /// calls the appropriate function. Posts the result back to the browser
+ /// asynchronously.
+ /// @param[in] var_message The message posted by the browser. The possible
+ /// messages are 'fortyTwo' and 'reverseText:Hello World'. Note that
+ /// the 'reverseText' form contains the string to reverse following a ':'
+ /// separator.
+ virtual void HandleMessage(const pp::Var& var_message);
+
+ bool HandleInputEvent(const pp::InputEvent& event);
+
+ bool Init(uint32_t argc, const char* argn[], const char* argv[]) {
+
+ printf("******* init! %i, %p, %p\n", argc, argn, argv);
+ fflush(stdout);
+ if (opengl_context_ == NULL) {
+ opengl_context_.reset(new OpenGLContext(this));
+ };
+ opengl_context_->InvalidateContext(this);
+ opengl_context_->ResizeContext(pp::Size(0, 0));
+ int current = opengl_context_->MakeContextCurrent(this);
+ printf("current is %i\n", current);
+
+ os_nacl = new OSNacl;
+
+ pkg_url = "";
+ for (uint32_t i=0; i<argc; i++) {
+ if (strcmp(argn[i], "package") == 0) {
+ pkg_url = argv[i];
+ };
+ };
+
+ sd = memnew(StateData);
+
+ if (pkg_url == "") {
+ nacl_main(argc, argn, argv);
+ } else {
+ printf("starting package %ls\n", pkg_url.c_str());
+ init_argc = MIN(argc, MAX_ARGS-1);
+ for (uint32_t i=0; i<argc; i++) {
+
+ int nlen = strlen(argn[i]);
+ init_argn[i] = (char*)memalloc(nlen+1);
+ strcpy(init_argn[i], argn[i]);
+ init_argn[i+1] = NULL;
+
+ int len = strlen(argv[i]);
+ init_argv[i] = (char*)memalloc(len+1);
+ strcpy(init_argv[i], argv[i]);
+ init_argv[i+1] = NULL;
+ };
+ package_pending = memnew(GetURLHandler(this, pkg_url));
+ package_pending->Start();
+ };
+ return true;
+ };
+
+ // Called whenever the in-browser window changes size.
+ virtual void DidChangeView(const pp::Rect& position, const pp::Rect& clip) {
+
+ if (position.size().width() == width &&
+ position.size().height() == height)
+ return; // Size didn't change, no need to update anything.
+
+ if (opengl_context_ == NULL) {
+ opengl_context_.reset(new OpenGLContext(this));
+ };
+ opengl_context_->InvalidateContext(this);
+ opengl_context_->ResizeContext(position.size());
+ if (!opengl_context_->MakeContextCurrent(this))
+ return;
+
+ width = position.size().width();
+ height = position.size().height();
+ // init gl here?
+ OS::VideoMode vm;
+ vm.width = width;
+ vm.height = height;
+ vm.resizable = false;
+ vm.fullscreen = true;
+ OS::get_singleton()->set_video_mode(vm, 0);
+
+ DrawSelf();
+ };
+
+ // Called to draw the contents of the module's browser area.
+ void DrawSelf() {
+
+ if (opengl_context_ == NULL)
+ return;
+
+ opengl_context_->FlushContext();
+ };
+};
+
+static Variant to_variant(const pp::Var& p_var) {
+
+ if (p_var.is_undefined() || p_var.is_null())
+ return Variant();
+ if (p_var.is_bool())
+ return Variant(p_var.AsBool());
+ if (p_var.is_double())
+ return Variant(p_var.AsDouble());
+ if (p_var.is_int())
+ return Variant((int64_t)p_var.AsInt());
+ if (p_var.is_string())
+ return Variant(String::utf8(p_var.AsString().c_str()));
+
+ return Variant();
+};
+
+void GodotInstance::HandleMessage(const pp::Var& var_message) {
+
+ switch (state) {
+
+ case STATE_METHOD: {
+
+ ERR_FAIL_COND(!var_message.is_string());
+ sd->method = var_message.AsString().c_str();
+ state = STATE_PARAM_COUNT;
+ } break;
+ case STATE_PARAM_COUNT: {
+
+ ERR_FAIL_COND(!var_message.is_number());
+ sd->arg_count = var_message.AsInt();
+ state = sd->arg_count>0?STATE_PARAMS:STATE_CALL;
+
+ } break;
+ case STATE_PARAMS: {
+
+ Variant p = to_variant(var_message);
+ sd->args.push_back(p);
+ if (sd->args.size() >= sd->arg_count)
+ state = STATE_CALL;
+ } break;
+ default:
+ break;
+ };
+
+ if (state == STATE_CALL) {
+
+ // call
+ state = STATE_METHOD;
+
+
+ if (sd->method == "package_finished") {
+
+ GetURLHandler::Status status = package_pending->get_status();
+ printf("status is %i, %i, %i\n", status, GetURLHandler::STATUS_ERROR, GetURLHandler::STATUS_COMPLETED);
+ if (status == GetURLHandler::STATUS_ERROR) {
+ printf("Error fetching package!\n");
+ };
+ if (status == GetURLHandler::STATUS_COMPLETED) {
+
+ OSNacl* os = (OSNacl*)OS::get_singleton();
+ os->add_package(pkg_url, package_pending->get_data());
+ };
+ memdelete(package_pending);
+ package_pending = NULL;
+
+ package_loaded = true;
+
+ opengl_context_->MakeContextCurrent(this);
+ nacl_main(init_argc, (const char**)init_argn, (const char**)init_argv);
+ for (uint32_t i=0; i<init_argc; i++) {
+ memfree(init_argn[i]);
+ memfree(init_argv[i]);
+ };
+ };
+
+ if (sd->method == "get_package_status") {
+
+ if (package_loaded) {
+ // post "loaded"
+ PostMessage("loaded");
+ } else if (package_pending == NULL) {
+ // post "none"
+ PostMessage("none");
+ } else {
+ // post package_pending->get_bytes_read();
+ PostMessage(package_pending->get_bytes_read());
+ };
+ };
+ };
+}
+
+bool GodotInstance::HandleInputEvent(const pp::InputEvent& event) {
+
+ OSNacl* os = (OSNacl*)OS::get_singleton();
+ os->handle_event(event);
+ return true;
+};
+
+class GodotModule : public pp::Module {
+ public:
+ GodotModule() : pp::Module() {}
+ virtual ~GodotModule() {
+ glTerminatePPAPI();
+ }
+
+ /// Create and return a GodotInstance object.
+ /// @param[in] instance a handle to a plug-in instance.
+ /// @return a newly created GodotInstance.
+ /// @note The browser is responsible for calling @a delete when done.
+ virtual pp::Instance* CreateInstance(PP_Instance instance) {
+ printf("CreateInstance! %x\n", instance);
+ return new GodotInstance(instance);
+ }
+
+ /// Called by the browser when the module is first loaded and ready to run.
+ /// This is called once per module, not once per instance of the module on
+ /// the page.
+ virtual bool Init() {
+ printf("GodotModule::init!\n");
+ return glInitializePPAPI(get_browser_interface());
+ }
+};
+
+namespace pp {
+/// Factory function called by the browser when the module is first loaded.
+/// The browser keeps a singleton of this module. It calls the
+/// CreateInstance() method on the object you return to make instances. There
+/// is one instance per <embed> tag on the page. This is the main binding
+/// point for your NaCl module with the browser.
+/// @return new GodotModule.
+/// @note The browser is responsible for deleting returned @a Module.
+Module* CreateModule() {
+ printf("CreateModule!\n");
+ return new GodotModule();
+}
+} // namespace pp
diff --git a/platform/nacl/godot_nacl.cpp b/platform/nacl/godot_nacl.cpp
new file mode 100644
index 0000000000..753f4124f8
--- /dev/null
+++ b/platform/nacl/godot_nacl.cpp
@@ -0,0 +1,80 @@
+/*************************************************************************/
+/* godot_nacl.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#include "os_nacl.h"
+#include "main/main.h"
+
+#include <stdio.h>
+#include <string.h>
+
+OSNacl* os_nacl = NULL;
+
+int nacl_main(int argc, const char** argn, const char** argv) {
+
+ // os is created in GodotModule::Init for the nacl module
+ printf("called with %i args, %p, %p\n", argc, argn, argv);
+ char* nargv[64];
+ int nargc = 1;
+ nargv[0] = (char*)argv[0];
+ for (int i=1; i<argc; i++) {
+
+ printf("arg %i is %s, %s\n", i, argn[i], argv[i]);
+ if (strncmp(argn[i], "arg", 3) == 0) {
+
+ printf("using arg %i, %s\n", nargc, argv[i]);
+ nargv[nargc++] = (char*)argv[i];
+ };
+ };
+ printf("total %i\n", nargc);
+ nargv[nargc] = 0;
+
+ printf("godot_nacl\n");
+ for (int i=0; i<argc; i++) {
+ printf("arg %i: %s\n", i, argv[i]);
+ };
+
+ printf("os created\n");
+ Error err = Main::setup("", nargc-1, &nargv[1]);
+ printf("setup %i\n", err);
+ if (err!=OK)
+ return 255;
+
+ printf("calling start\n");
+ Main::start();
+
+ return 0;
+};
+
+
+void nacl_cleanup() {
+
+ Main::cleanup();
+ delete os_nacl;
+};
+
+
diff --git a/platform/nacl/html/check_browser.js b/platform/nacl/html/check_browser.js
new file mode 100644
index 0000000000..9636ad0384
--- /dev/null
+++ b/platform/nacl/html/check_browser.js
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2011 The Native Client Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/**
+ * @fileoverview This file provides a BrowserChecker Javascript class.
+ * Users can create a BrowserChecker object, invoke checkBrowser(|version|),
+ * and then use getIsValidBrowser() and getBrowserSupportStatus()
+ * to determine if the browser version is greater than |version|
+ * and if the Native Client plugin is found.
+ */
+
+// Create a namespace object
+var browser_version = browser_version || {};
+
+/**
+ * Class to provide checking for version and NativeClient.
+ * @param {integer} arg1 An argument that indicates major version of Chrome we
+ * require, such as 14.
+ */
+
+/**
+ * Constructor for the BrowserChecker. Sets the major version of
+ * Chrome that is required to |minChromeVersion|.
+ * @param minChromeVersion The earliest major version of chrome that
+ * is supported. If the Chrome browser version is less than
+ * |minChromeVersion| then |isValidBrowswer| will be set to false.
+ * @param opt_maxChromeVersion Ignored. Retained for backwards compatibility.
+ * @param appVersion The application version string.
+ * @param plugins The plugins that exist in the browser.
+ * @constructor
+ */
+browser_version.BrowserChecker = function(minChromeVersion,
+ appVersion, plugins,
+ opt_maxChromeVersion) {
+ /**
+ * Version specified by the user. This class looks to see if the browser
+ * version is >= |minChromeVersion_|.
+ * @type {integer}
+ * @private
+ */
+ this.minChromeVersion_ = minChromeVersion;
+
+ /**
+ * List of Browser plugin objects.
+ * @type {Ojbect array}
+ * @private
+ */
+ this.plugins_ = plugins;
+
+ /**
+ * Application version string from the Browser.
+ * @type {integer}
+ * @private
+ */
+ this.appVersion_ = appVersion;
+
+ /**
+ * Flag used to indicate if the browser has Native Client and is if the
+ * browser version is recent enough.
+ * @type {boolean}
+ * @private
+ */
+ this.isValidBrowser_ = false;
+
+ /**
+ * Actual major version of Chrome -- found by querying the browser.
+ * @type {integer}
+ * @private
+ */
+ this.chromeVersion_ = null;
+
+ /**
+ * Browser support status. This allows the user to get a detailed status
+ * rather than using this.browserSupportMessage.
+ */
+ this.browserSupportStatus_ =
+ browser_version.BrowserChecker.StatusValues.UNKNOWN;
+}
+
+/**
+ * The values used for BrowserChecker status to indicate success or
+ * a specific error.
+ * @enum {id}
+ */
+browser_version.BrowserChecker.StatusValues = {
+ UNKNOWN: 0,
+ NACL_ENABLED: 1,
+ UNKNOWN_BROWSER: 2,
+ CHROME_VERSION_TOO_OLD: 3,
+ NACL_NOT_ENABLED: 4,
+ NOT_USING_SERVER: 5
+};
+
+/**
+ * Determines if the plugin with name |name| exists in the browser.
+ * @param {string} name The name of the plugin.
+ * @param {Object array} plugins The plugins in this browser.
+ * @return {bool} |true| if the plugin is found.
+ */
+browser_version.BrowserChecker.prototype.pluginExists = function(name,
+ plugins) {
+ for (var index=0; index < plugins.length; index++) {
+ var plugin = this.plugins_[index];
+ var plugin_name = plugin['name'];
+ // If the plugin is not found, you can use the Javascript console
+ // to see the names of the plugins that were found when debugging.
+ if (plugin_name.indexOf(name) != -1) {
+ return true;
+ }
+ }
+ return false;
+}
+
+/**
+ * Returns browserSupportStatus_ which indicates if the browser supports
+ * Native Client. Values are defined as literals in
+ * browser_version.BrowserChecker.StatusValues.
+ * @ return {int} Level of NaCl support.
+ */
+browser_version.BrowserChecker.prototype.getBrowserSupportStatus = function() {
+ return this.browserSupportStatus_;
+}
+
+/**
+ * Returns isValidBrowser (true/false) to indicate if the browser supports
+ * Native Client.
+ * @ return {bool} If this browser has NativeClient and correct version.
+ */
+browser_version.BrowserChecker.prototype.getIsValidBrowser = function() {
+ return this.isValidBrowser_;
+}
+
+/**
+ * Checks to see if this browser can support Native Client applications.
+ * For Chrome browsers, checks to see if the "Native Client" plugin is
+ * enabled.
+ */
+browser_version.BrowserChecker.prototype.checkBrowser = function() {
+ var versionPatt = /Chrome\/(\d+)\.(\d+)\.(\d+)\.(\d+)/;
+ var result = this.appVersion_.match(versionPatt);
+
+ // |result| stores the Chrome version number.
+ if (!result) {
+ this.isValidBrowser_ = false;
+ this.browserSupportStatus_ =
+ browser_version.BrowserChecker.StatusValues.UNKNOWN_BROWSER;
+ } else {
+ this.chromeVersion_ = result[1];
+ // We know we have Chrome, check version and/or plugin named Native Client
+ if (this.chromeVersion_ >= this.minChromeVersion_) {
+ var found_nacl = this.pluginExists('Native Client', this.plugins_);
+ if (found_nacl) {
+ this.isValidBrowser_ = true;
+ this.browserSupportStatus_ =
+ browser_version.BrowserChecker.StatusValues.NACL_ENABLED;
+ } else {
+ this.isValidBrowser_ = false;
+ this.browserSupportStatus_ =
+ browser_version.BrowserChecker.StatusValues.NACL_NOT_ENABLED;
+ }
+ } else {
+ // We are in a version that is less than |minChromeVersion_|
+ this.isValidBrowser_ = false;
+ this.browserSupportStatus_ =
+ browser_version.BrowserChecker.StatusValues.CHROME_VERSION_TOO_OLD;
+ }
+ }
+ var my_protocol = window.location.protocol;
+ if (my_protocol.indexOf('file') == 0) {
+ this.isValidBrowser_ = false;
+ this.browserSupportStatus_ =
+ browser_version.BrowserChecker.StatusValues.NOT_USING_SERVER;
+ }
+}
+
diff --git a/platform/nacl/html/godot_nacl.nmf b/platform/nacl/html/godot_nacl.nmf
new file mode 100644
index 0000000000..eca039ec1e
--- /dev/null
+++ b/platform/nacl/html/godot_nacl.nmf
@@ -0,0 +1,6 @@
+{
+ "program": {
+ "x86-64": {"url": "godot_nacl.x86_64.nexe"},
+ "x86-32": {"url": "godot_nacl.i686.nexe"}
+ }
+}
diff --git a/platform/nacl/html/icon_128.png b/platform/nacl/html/icon_128.png
new file mode 100644
index 0000000000..1793aa7e7a
--- /dev/null
+++ b/platform/nacl/html/icon_128.png
Binary files differ
diff --git a/platform/nacl/html/icon_16.png b/platform/nacl/html/icon_16.png
new file mode 100644
index 0000000000..09de19e418
--- /dev/null
+++ b/platform/nacl/html/icon_16.png
Binary files differ
diff --git a/platform/nacl/html/index.html b/platform/nacl/html/index.html
new file mode 100644
index 0000000000..e8be6f69b9
--- /dev/null
+++ b/platform/nacl/html/index.html
@@ -0,0 +1,258 @@
+<!DOCTYPE html>
+<html>
+ <!--
+ Copyright (c) 2011 The Native Client 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>
+ <title>Load Progress Example</title>
+ <script type="text/javascript" src="check_browser.js"></script>
+ <script type="text/javascript">
+ // Check for Native Client support in the browser before the DOM loads.
+ var isValidBrowser = false;
+ var browserSupportStatus = 0;
+ var checker = new browser_version.BrowserChecker(
+ 14, // Minumum Chrome version.
+ navigator["appVersion"],
+ navigator["plugins"]);
+ checker.checkBrowser();
+
+ loadProgressModule = null; // Global application object.
+ statusText = 'NO-STATUS';
+
+ isValidBrowser = checker.getIsValidBrowser();
+ browserSupportStatus = checker.getBrowserSupportStatus();
+
+ // Handler that gets called when the NaCl module starts loading. This
+ // event is always triggered when an <EMBED> tag has a MIME type of
+ // application/x-nacl.
+ function moduleDidStartLoad() {
+ appendToEventLog('loadstart');
+ }
+
+ // Progress event handler. |event| contains a couple of interesting
+ // properties that are used in this example:
+ // total The size of the NaCl module in bytes. Note that this value
+ // is 0 until |lengthComputable| is true. In particular, this
+ // value is 0 for the first 'progress' event.
+ // loaded The number of bytes loaded so far.
+ // lengthComputable A boolean indicating that the |total| field
+ // represents a valid length.
+ //
+ // event The ProgressEvent that triggered this handler.
+ function moduleLoadProgress(event) {
+ var loadPercent = 0.0;
+ var loadPercentString;
+ if (event.lengthComputable && event.total > 0) {
+ loadPercent = event.loaded / event.total * 100.0;
+ loadPercentString = loadPercent + '%';
+ } else {
+ // The total length is not yet known.
+ loadPercent = -1.0;
+ loadPercentString = 'Computing...';
+ }
+ //appendToEventLog('progress: ' + loadPercentString + ' (' + event.loaded + ' of ' + event.total + ' bytes)');
+ updateStatus("Loading module : "+ Math.floor(event.loaded / event.total * 100.0) + "% complete");
+ }
+
+ // Handler that gets called if an error occurred while loading the NaCl
+ // module. Note that the event does not carry any meaningful data about
+ // the error, you have to check lastError on the <EMBED> element to find
+ // out what happened.
+ function moduleLoadError() {
+ appendToEventLog('error: ' + loadProgressModule.lastError);
+ }
+
+ // Handler that gets called if the NaCl module load is aborted.
+ function moduleLoadAbort() {
+ appendToEventLog('abort');
+ }
+
+ // When the NaCl module has loaded indicate success.
+ function moduleDidLoad() {
+ loadProgressModule = document.getElementById('load_progress');
+ appendToEventLog('load');
+ updateStatus('SUCCESS');
+ }
+
+ function check_dl_status() {
+ var module = document.getElementById('load_progress');
+ module.postMessage("get_package_status");
+ module.postMessage(0);
+ };
+
+ // Handler that gets called when the NaCl module loading has completed.
+ // You will always get one of these events, regardless of whether the NaCl
+ // module loaded successfully or not. For example, if there is an error
+ // during load, you will get an 'error' event and a 'loadend' event. Note
+ // that if the NaCl module loads successfully, you will get both a 'load'
+ // event and a 'loadend' event.
+ function moduleDidEndLoad() {
+ appendToEventLog('loadend');
+ var lastError = event.target.lastError;
+ if (lastError == undefined || lastError.length == 0) {
+ lastError = '&lt;none&gt;';
+ window.setTimeout(check_dl_status, 1000);
+ }
+ appendToEventLog('lastError: ' + lastError);
+ }
+
+
+ // Handle a message coming from the NaCl module.
+ function handleMessage(message_event) {
+ var data = message_event.data;
+ if (data == "loaded") {
+ updateStatus("Data Loaded!");
+ } else if (data == "none") {
+ // nothing
+ updateStatus("Downloading package: connecting");
+ window.setTimeout(check_dl_status, 1000);
+ } else {
+ updateStatus("Downloading package: " + data + " bytes");
+ window.setTimeout(check_dl_status, 1000);
+ };
+ }
+
+ // Set the global status message. Updates the 'status_field' element with
+ // the new text.
+ // opt_message The message text. If this is null or undefined, then
+ // attempt to set the element with id 'status_field' to the value of
+ // |statusText|.
+ function updateStatus(opt_message) {
+ if (opt_message)
+ statusText = opt_message;
+ var statusField = document.getElementById('status_field');
+ if (statusField) {
+ statusField.innerHTML = statusText;
+ }
+ }
+
+ // Append an event name to the 'event_log_field' element. Event names
+ // are separated by a <br> tag so they get listed one per line.
+ // logMessage The message to append to the log.
+ function appendToEventLog(logMessage) {
+ var eventLogField = document.getElementById('event_log_field');
+ if (eventLogField.innerHTML.length == 0) {
+ eventLogField.innerHTML = logMessage;
+ } else {
+ eventLogField.innerHTML = eventLogField.innerHTML +
+ '<br />' +
+ logMessage;
+ }
+ }
+
+ </script>
+</head>
+<body bgcolor=#000000>
+
+<font color=#FFFFFF>
+
+<h1>Native Client Load Event Example</h1>
+
+<h2>Status</h2>
+<div id="status_field">NO-STATUS</div>
+
+<div id="listener">
+ <script type="text/javascript">
+ var listener = document.getElementById('listener');
+ listener.addEventListener('loadstart', moduleDidStartLoad, true);
+ listener.addEventListener('progress', moduleLoadProgress, true);
+ listener.addEventListener('error', moduleLoadError, true);
+ listener.addEventListener('abort', moduleLoadAbort, true);
+ listener.addEventListener('load', moduleDidLoad, true);
+ listener.addEventListener('loadend', moduleDidEndLoad, true);
+ listener.addEventListener('message', handleMessage, true);
+
+ switch (browserSupportStatus) {
+ case browser_version.BrowserChecker.StatusValues.NACL_ENABLED:
+ appendToEventLog('Native Client plugin enabled.');
+ break;
+ case browser_version.BrowserChecker.StatusValues.UNKNOWN_BROWSER:
+ updateStatus('UNKNOWN BROWSER');
+ break;
+ case browser_version.BrowserChecker.StatusValues.CHROME_VERSION_TOO_OLD:
+ appendToEventLog(
+ 'Chrome too old: You must use Chrome version 14 or later.');
+ updateStatus('NEED CHROME 14 OR LATER');
+ break;
+ case browser_version.BrowserChecker.StatusValues.NACL_NOT_ENABLED:
+ appendToEventLog(
+ 'NaCl disabled: Native Client is not enabled.<br>' +
+ 'Please go to <b>chrome://plugins</b> and enable Native Client ' +
+ 'plugin.');
+ updateStatus('NaCl NOT ENABLED');
+ break;
+ case browser_version.BrowserChecker.StatusValues.NOT_USING_SERVER:
+ appendToEventLog(
+ 'file: URL detected, please use a web server to host Native ' +
+ 'Client applications.');
+ updateStatus('NaCl NOT ENABLED');
+ default:
+ appendToEventLog('Unknown error: Unable to detect browser and/or ' +
+ 'Native Client support.');
+ updateStatus('UNKNOWN ERROR');
+ break;
+ }
+ </script>
+
+ <!-- Load the published .nexe. This includes the 'src' attribute which
+ shows how to load multi-architecture modules. Each entry in the "nexes"
+ object in the .nmf manifest file is a key-value pair: the key is the runtime
+ ('x86-32', 'x86-64', etc.); the value is a URL for the desired NaCl module.
+ To load the debug versions of your .nexes, set the 'src' attribute to the
+ _dbg.nmf version of the manifest file.
+
+ Note: The <EMBED> element is wrapped inside a <DIV>, which has both a 'load'
+ and a 'message' event listener attached. This wrapping method is used
+ instead of attaching the event listeners directly to the <EMBED> element to
+ ensure that the listeners are active before the NaCl module 'load' event
+ fires. This also allows you to use PPB_Messaging.PostMessage() (in C) or
+ pp::Instance.PostMessage() (in C++) from within the initialization code in
+ your NaCl module.
+ -->
+ <embed name="nacl_module"
+ id="load_progress"
+ width=1024 height=600
+ src="godot_nacl.nmf"
+ type="application/x-nacl"
+ package="data.pcz"
+ arg1="-path" arg2="."
+ no_arg1="-test" no_arg2="gui" />
+
+ <script type="text/javascript">
+ loadProgressModule = document.getElementById('load_progress');
+ // Futher diagnose NaCl loading.
+ if (loadProgressModule == null ||
+ typeof loadProgressModule.readyState == 'undefined') {
+ switch (browserSupportStatus) {
+ case browser_version.BrowserChecker.StatusValues.NACL_ENABLED:
+ // The NaCl plugin is enabled and running, it's likely that the flag
+ // isn't set.
+ appendToEventLog(
+ 'NaCl flag disabled: The Native Client flag is not enabled.<br>' +
+ 'Please go to <b>chrome://flags</b> enable Native Client and ' +
+ 'relaunch your browser. See also: ' +
+ '<a href="http://code.google.com/chrome/nativeclient/docs/' +
+ 'running.html">Running Web Applications that Use Native Client' +
+ '</a>');
+ updateStatus('NaCl NOT ENABLED');
+ break;
+ case browser_version.BrowserChecker.StatusValues.UNKNOWN_BROWSER:
+ appendToEventLog('Native Client applications are not supported by ' +
+ 'this browser.');
+ break;
+ default:
+ appendToEventLog('Unknown error when loading Native Client ' +
+ 'application.');
+ }
+ }
+ </script>
+</div>
+
+<h2>Event Log</h2>
+<div id="event_log_field">event log?</div>
+
+</body>
+</html>
+
diff --git a/platform/nacl/html/manifest.json b/platform/nacl/html/manifest.json
new file mode 100644
index 0000000000..6e271507a9
--- /dev/null
+++ b/platform/nacl/html/manifest.json
@@ -0,0 +1,19 @@
+{
+ "name": "Capsuleman's Castle Adventure",
+ "description": "Capsuleman's Castle Adventure",
+ "version": "1",
+ "app": {
+ "launch": {
+ "local_path": "index.html"
+ }
+ },
+ "icons": {
+ "16": "icon_16.png",
+ "128": "icon_128.png"
+ },
+ "permissions": [
+ "unlimitedStorage",
+ "notifications",
+ "experimental"
+ ]
+}
diff --git a/platform/nacl/logo.png b/platform/nacl/logo.png
new file mode 100644
index 0000000000..aac72c01b2
--- /dev/null
+++ b/platform/nacl/logo.png
Binary files differ
diff --git a/platform/nacl/nacl_keycodes.h b/platform/nacl/nacl_keycodes.h
new file mode 100644
index 0000000000..1cbf379078
--- /dev/null
+++ b/platform/nacl/nacl_keycodes.h
@@ -0,0 +1,422 @@
+/*************************************************************************/
+/* nacl_keycodes.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+ * Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com. All rights reserved.
+ * Copyright (C) 2008, 2009 Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, LOSS OF USE, DATA, OR
+ * PROFITS, OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef BASE_KEYBOARD_CODES_POSIX_H_
+#define BASE_KEYBOARD_CODES_POSIX_H_
+#pragma once
+
+#include "core/os/keyboard.h"
+
+enum {
+ VKEY_BACK = 0x08,
+ VKEY_TAB = 0x09,
+ VKEY_CLEAR = 0x0C,
+ VKEY_RETURN = 0x0D,
+ VKEY_SHIFT = 0x10,
+ VKEY_CONTROL = 0x11,
+ VKEY_MENU = 0x12,
+ VKEY_PAUSE = 0x13,
+ VKEY_CAPITAL = 0x14,
+ VKEY_KANA = 0x15,
+ VKEY_HANGUL = 0x15,
+ VKEY_JUNJA = 0x17,
+ VKEY_FINAL = 0x18,
+ VKEY_HANJA = 0x19,
+ VKEY_KANJI = 0x19,
+ VKEY_ESCAPE = 0x1B,
+ VKEY_CONVERT = 0x1C,
+ VKEY_NONCONVERT = 0x1D,
+ VKEY_ACCEPT = 0x1E,
+ VKEY_MODECHANGE = 0x1F,
+ VKEY_SPACE = 0x20,
+ VKEY_PRIOR = 0x21,
+ VKEY_NEXT = 0x22,
+ VKEY_END = 0x23,
+ VKEY_HOME = 0x24,
+ VKEY_LEFT = 0x25,
+ VKEY_UP = 0x26,
+ VKEY_RIGHT = 0x27,
+ VKEY_DOWN = 0x28,
+ VKEY_SELECT = 0x29,
+ VKEY_PRINT = 0x2A,
+ VKEY_EXECUTE = 0x2B,
+ VKEY_SNAPSHOT = 0x2C,
+ VKEY_INSERT = 0x2D,
+ VKEY_DELETE = 0x2E,
+ VKEY_HELP = 0x2F,
+ VKEY_0 = 0x30,
+ VKEY_1 = 0x31,
+ VKEY_2 = 0x32,
+ VKEY_3 = 0x33,
+ VKEY_4 = 0x34,
+ VKEY_5 = 0x35,
+ VKEY_6 = 0x36,
+ VKEY_7 = 0x37,
+ VKEY_8 = 0x38,
+ VKEY_9 = 0x39,
+ VKEY_A = 0x41,
+ VKEY_B = 0x42,
+ VKEY_C = 0x43,
+ VKEY_D = 0x44,
+ VKEY_E = 0x45,
+ VKEY_F = 0x46,
+ VKEY_G = 0x47,
+ VKEY_H = 0x48,
+ VKEY_I = 0x49,
+ VKEY_J = 0x4A,
+ VKEY_K = 0x4B,
+ VKEY_L = 0x4C,
+ VKEY_M = 0x4D,
+ VKEY_N = 0x4E,
+ VKEY_O = 0x4F,
+ VKEY_P = 0x50,
+ VKEY_Q = 0x51,
+ VKEY_R = 0x52,
+ VKEY_S = 0x53,
+ VKEY_T = 0x54,
+ VKEY_U = 0x55,
+ VKEY_V = 0x56,
+ VKEY_W = 0x57,
+ VKEY_X = 0x58,
+ VKEY_Y = 0x59,
+ VKEY_Z = 0x5A,
+ VKEY_LWIN = 0x5B,
+ VKEY_COMMAND = VKEY_LWIN, // Provide the Mac name for convenience.
+ VKEY_RWIN = 0x5C,
+ VKEY_APPS = 0x5D,
+ VKEY_SLEEP = 0x5F,
+ VKEY_NUMPAD0 = 0x60,
+ VKEY_NUMPAD1 = 0x61,
+ VKEY_NUMPAD2 = 0x62,
+ VKEY_NUMPAD3 = 0x63,
+ VKEY_NUMPAD4 = 0x64,
+ VKEY_NUMPAD5 = 0x65,
+ VKEY_NUMPAD6 = 0x66,
+ VKEY_NUMPAD7 = 0x67,
+ VKEY_NUMPAD8 = 0x68,
+ VKEY_NUMPAD9 = 0x69,
+ VKEY_MULTIPLY = 0x6A,
+ VKEY_ADD = 0x6B,
+ VKEY_SEPARATOR = 0x6C,
+ VKEY_SUBTRACT = 0x6D,
+ VKEY_DECIMAL = 0x6E,
+ VKEY_DIVIDE = 0x6F,
+ VKEY_F1 = 0x70,
+ VKEY_F2 = 0x71,
+ VKEY_F3 = 0x72,
+ VKEY_F4 = 0x73,
+ VKEY_F5 = 0x74,
+ VKEY_F6 = 0x75,
+ VKEY_F7 = 0x76,
+ VKEY_F8 = 0x77,
+ VKEY_F9 = 0x78,
+ VKEY_F10 = 0x79,
+ VKEY_F11 = 0x7A,
+ VKEY_F12 = 0x7B,
+ VKEY_F13 = 0x7C,
+ VKEY_F14 = 0x7D,
+ VKEY_F15 = 0x7E,
+ VKEY_F16 = 0x7F,
+ VKEY_F17 = 0x80,
+ VKEY_F18 = 0x81,
+ VKEY_F19 = 0x82,
+ VKEY_F20 = 0x83,
+ VKEY_F21 = 0x84,
+ VKEY_F22 = 0x85,
+ VKEY_F23 = 0x86,
+ VKEY_F24 = 0x87,
+ VKEY_NUMLOCK = 0x90,
+ VKEY_SCROLL = 0x91,
+ VKEY_LSHIFT = 0xA0,
+ VKEY_RSHIFT = 0xA1,
+ VKEY_LCONTROL = 0xA2,
+ VKEY_RCONTROL = 0xA3,
+ VKEY_LMENU = 0xA4,
+ VKEY_RMENU = 0xA5,
+ VKEY_BROWSER_BACK = 0xA6,
+ VKEY_BROWSER_FORWARD = 0xA7,
+ VKEY_BROWSER_REFRESH = 0xA8,
+ VKEY_BROWSER_STOP = 0xA9,
+ VKEY_BROWSER_SEARCH = 0xAA,
+ VKEY_BROWSER_FAVORITES = 0xAB,
+ VKEY_BROWSER_HOME = 0xAC,
+ VKEY_VOLUME_MUTE = 0xAD,
+ VKEY_VOLUME_DOWN = 0xAE,
+ VKEY_VOLUME_UP = 0xAF,
+ VKEY_MEDIA_NEXT_TRACK = 0xB0,
+ VKEY_MEDIA_PREV_TRACK = 0xB1,
+ VKEY_MEDIA_STOP = 0xB2,
+ VKEY_MEDIA_PLAY_PAUSE = 0xB3,
+ VKEY_MEDIA_LAUNCH_MAIL = 0xB4,
+ VKEY_MEDIA_LAUNCH_MEDIA_SELECT = 0xB5,
+ VKEY_MEDIA_LAUNCH_APP1 = 0xB6,
+ VKEY_MEDIA_LAUNCH_APP2 = 0xB7,
+ VKEY_OEM_1 = 0xBA,
+ VKEY_OEM_PLUS = 0xBB,
+ VKEY_OEM_COMMA = 0xBC,
+ VKEY_OEM_MINUS = 0xBD,
+ VKEY_OEM_PERIOD = 0xBE,
+ VKEY_OEM_2 = 0xBF,
+ VKEY_OEM_3 = 0xC0,
+ VKEY_OEM_4 = 0xDB,
+ VKEY_OEM_5 = 0xDC,
+ VKEY_OEM_6 = 0xDD,
+ VKEY_OEM_7 = 0xDE,
+ VKEY_OEM_8 = 0xDF,
+ VKEY_OEM_102 = 0xE2,
+ VKEY_PROCESSKEY = 0xE5,
+ VKEY_PACKET = 0xE7,
+ VKEY_ATTN = 0xF6,
+ VKEY_CRSEL = 0xF7,
+ VKEY_EXSEL = 0xF8,
+ VKEY_EREOF = 0xF9,
+ VKEY_PLAY = 0xFA,
+ VKEY_ZOOM = 0xFB,
+ VKEY_NONAME = 0xFC,
+ VKEY_PA1 = 0xFD,
+ VKEY_OEM_CLEAR = 0xFE,
+ VKEY_UNKNOWN = 0
+};
+
+static uint32_t godot_key(uint32_t p_key, bool& is_char) {
+
+ is_char = false;
+
+ switch (p_key) {
+
+ case VKEY_BACK: return KEY_BACKSPACE;
+ case VKEY_TAB: return KEY_TAB;
+ case VKEY_CLEAR: return KEY_CLEAR;
+ case VKEY_RETURN: return KEY_RETURN;
+ case VKEY_SHIFT: return KEY_SHIFT;
+ case VKEY_CONTROL: return KEY_CONTROL;
+ case VKEY_MENU: return KEY_MENU;
+ case VKEY_PAUSE: return KEY_PAUSE;
+// case VKEY_CAPITAL: return KEY_CAPITAL;
+// case VKEY_KANA: return KEY_KANA;
+// case VKEY_HANGUL: return KEY_HANGUL;
+// case VKEY_JUNJA: return KEY_JUNJA;
+// case VKEY_FINAL: return KEY_FINAL;
+// case VKEY_HANJA: return KEY_HANJA;
+// case VKEY_KANJI: return KEY_KANJI;
+ case VKEY_ESCAPE: return KEY_ESCAPE;
+// case VKEY_CONVERT: return KEY_CONVERT;
+// case VKEY_NONCONVERT: return KEY_NONCONVERT;
+// case VKEY_ACCEPT: return KEY_ACCEPT;
+// case VKEY_MODECHANGE: return KEY_MODECHANGE;
+// case VKEY_PRIOR: return KEY_PRIOR;
+// case VKEY_NEXT: return KEY_NEXT;
+ case VKEY_END: return KEY_END;
+ case VKEY_HOME: return KEY_HOME;
+ case VKEY_LEFT: return KEY_LEFT;
+ case VKEY_UP: return KEY_UP;
+ case VKEY_RIGHT: return KEY_RIGHT;
+ case VKEY_DOWN: return KEY_DOWN;
+// case VKEY_SELECT: return KEY_SELECT;
+ case VKEY_PRINT: return KEY_PRINT;
+// case VKEY_EXECUTE: return KEY_EXECUTE;
+// case VKEY_SNAPSHOT: return KEY_SNAPSHOT;
+ case VKEY_INSERT: return KEY_INSERT;
+ case VKEY_DELETE: return KEY_DELETE;
+ case VKEY_HELP: return KEY_HELP;
+// case VKEY_LWIN: return KEY_LWIN;
+// case VKEY_RWIN: return KEY_RWIN;
+// case VKEY_APPS: return KEY_APPS;
+// case VKEY_SLEEP: return KEY_SLEEP;
+ case VKEY_NUMPAD0: return KEY_KP_0;
+ case VKEY_NUMPAD1: return KEY_KP_1;
+ case VKEY_NUMPAD2: return KEY_KP_2;
+ case VKEY_NUMPAD3: return KEY_KP_3;
+ case VKEY_NUMPAD4: return KEY_KP_4;
+ case VKEY_NUMPAD5: return KEY_KP_5;
+ case VKEY_NUMPAD6: return KEY_KP_6;
+ case VKEY_NUMPAD7: return KEY_KP_7;
+ case VKEY_NUMPAD8: return KEY_KP_8;
+ case VKEY_NUMPAD9: return KEY_KP_9;
+ case VKEY_MULTIPLY: return KEY_KP_MULTIPLY;
+ case VKEY_ADD: return KEY_KP_ADD;
+// case VKEY_SEPARATOR: return KEY_SEPARATOR;
+ case VKEY_SUBTRACT: return KEY_KP_SUBSTRACT;
+ case VKEY_DECIMAL: return KEY_KP_PERIOD;
+ case VKEY_DIVIDE: return KEY_KP_DIVIDE;
+ case VKEY_F1: return KEY_F1;
+ case VKEY_F2: return KEY_F2;
+ case VKEY_F3: return KEY_F3;
+ case VKEY_F4: return KEY_F4;
+ case VKEY_F5: return KEY_F5;
+ case VKEY_F6: return KEY_F6;
+ case VKEY_F7: return KEY_F7;
+ case VKEY_F8: return KEY_F8;
+ case VKEY_F9: return KEY_F9;
+ case VKEY_F10: return KEY_F10;
+ case VKEY_F11: return KEY_F11;
+ case VKEY_F12: return KEY_F12;
+ case VKEY_F13: return KEY_F13;
+ case VKEY_F14: return KEY_F14;
+ case VKEY_F15: return KEY_F15;
+ case VKEY_F16: return KEY_F16;
+ /*
+ case VKEY_F17: return KEY_F17;
+ case VKEY_F18: return KEY_F18;
+ case VKEY_F19: return KEY_F19;
+ case VKEY_F20: return KEY_F20;
+ case VKEY_F21: return KEY_F21;
+ case VKEY_F22: return KEY_F22;
+ case VKEY_F23: return KEY_F23;
+ case VKEY_F24: return KEY_F24;
+ */
+ case VKEY_NUMLOCK: return KEY_NUMLOCK;
+ case VKEY_SCROLL: return KEY_SCROLLLOCK;
+ case VKEY_LSHIFT: return KEY_SHIFT;
+ case VKEY_RSHIFT: return KEY_SHIFT;
+ case VKEY_LCONTROL: return KEY_CONTROL;
+ case VKEY_RCONTROL: return KEY_CONTROL;
+ case VKEY_LMENU: return KEY_MENU;
+ case VKEY_RMENU: return KEY_MENU;
+ case VKEY_BROWSER_BACK: return KEY_BACK;
+ case VKEY_BROWSER_FORWARD: return KEY_FORWARD;
+ case VKEY_BROWSER_REFRESH: return KEY_REFRESH;
+ case VKEY_BROWSER_STOP: return KEY_STOP;
+ case VKEY_BROWSER_SEARCH: return KEY_SEARCH;
+ case VKEY_BROWSER_FAVORITES: return KEY_FAVORITES;
+ case VKEY_BROWSER_HOME: return KEY_HOMEPAGE;
+ case VKEY_VOLUME_MUTE: return KEY_VOLUMEMUTE;
+ case VKEY_VOLUME_DOWN: return KEY_VOLUMEDOWN;
+ case VKEY_VOLUME_UP: return KEY_VOLUMEUP;
+ case VKEY_MEDIA_NEXT_TRACK: return KEY_MEDIANEXT;
+ case VKEY_MEDIA_PREV_TRACK: return KEY_MEDIAPREVIOUS;
+ case VKEY_MEDIA_STOP: return KEY_MEDIASTOP;
+ case VKEY_MEDIA_PLAY_PAUSE: return KEY_MEDIAPLAY;
+ case VKEY_MEDIA_LAUNCH_MAIL: return KEY_LAUNCHMAIL;
+ case VKEY_MEDIA_LAUNCH_MEDIA_SELECT: return KEY_LAUNCHMEDIA; // FUCKING USELESS KEYS, HOW DO THEY WORK?
+ case VKEY_MEDIA_LAUNCH_APP1: return KEY_LAUNCH0;
+ case VKEY_MEDIA_LAUNCH_APP2: return KEY_LAUNCH0;
+// case VKEY_OEM_102: return KEY_OEM_102;
+// case VKEY_PROCESSKEY: return KEY_PROCESSKEY;
+// case VKEY_PACKET: return KEY_PACKET;
+// case VKEY_ATTN: return KEY_ATTN;
+// case VKEY_CRSEL: return KEY_CRSEL;
+// case VKEY_EXSEL: return KEY_EXSEL;
+// case VKEY_EREOF: return KEY_EREOF;
+// case VKEY_PLAY: return KEY_PLAY;
+// case VKEY_ZOOM: return KEY_ZOOM;
+// case VKEY_NONAME: return KEY_NONAME;
+// case VKEY_PA1: return KEY_PA1;
+// case VKEY_OEM_CLEAR: return KEY_OEM_CLEAR;
+
+ default: break;
+ };
+
+ is_char = true;
+
+ switch (p_key) {
+
+ case VKEY_SPACE: return KEY_SPACE;
+ case VKEY_0: return KEY_0;
+ case VKEY_1: return KEY_1;
+ case VKEY_2: return KEY_2;
+ case VKEY_3: return KEY_3;
+ case VKEY_4: return KEY_4;
+ case VKEY_5: return KEY_5;
+ case VKEY_6: return KEY_6;
+ case VKEY_7: return KEY_7;
+ case VKEY_8: return KEY_8;
+ case VKEY_9: return KEY_9;
+ case VKEY_A: return KEY_A;
+ case VKEY_B: return KEY_B;
+ case VKEY_C: return KEY_C;
+ case VKEY_D: return KEY_D;
+ case VKEY_E: return KEY_E;
+ case VKEY_F: return KEY_F;
+ case VKEY_G: return KEY_G;
+ case VKEY_H: return KEY_H;
+ case VKEY_I: return KEY_I;
+ case VKEY_J: return KEY_J;
+ case VKEY_K: return KEY_K;
+ case VKEY_L: return KEY_L;
+ case VKEY_M: return KEY_M;
+ case VKEY_N: return KEY_N;
+ case VKEY_O: return KEY_O;
+ case VKEY_P: return KEY_P;
+ case VKEY_Q: return KEY_Q;
+ case VKEY_R: return KEY_R;
+ case VKEY_S: return KEY_S;
+ case VKEY_T: return KEY_T;
+ case VKEY_U: return KEY_U;
+ case VKEY_V: return KEY_V;
+ case VKEY_W: return KEY_W;
+ case VKEY_X: return KEY_X;
+ case VKEY_Y: return KEY_Y;
+ case VKEY_Z: return KEY_Z;
+ /*
+ case VKEY_OEM_PLUS: return KEY_PLUS;
+ case VKEY_OEM_COMMA: return KEY_COMMA;
+ case VKEY_OEM_MINUS: return KEY_MINUS;
+ case VKEY_OEM_PERIOD: return KEY_PERIOD;
+ case VKEY_OEM_1: return KEY_OEM_1;
+ case VKEY_OEM_2: return KEY_OEM_2;
+ case VKEY_OEM_3: return KEY_OEM_3;
+ case VKEY_OEM_4: return KEY_OEM_4;
+ case VKEY_OEM_5: return KEY_OEM_5;
+ case VKEY_OEM_6: return KEY_OEM_6;
+ case VKEY_OEM_7: return KEY_OEM_7;
+ case VKEY_OEM_8: return KEY_OEM_8;
+ */
+ default: break;
+
+ };
+
+ return 0;
+};
+
+#endif // BASE_KEYBOARD_CODES_POSIX_H_
diff --git a/platform/nacl/opengl_context.cpp b/platform/nacl/opengl_context.cpp
new file mode 100644
index 0000000000..8dafe959a3
--- /dev/null
+++ b/platform/nacl/opengl_context.cpp
@@ -0,0 +1,123 @@
+/*************************************************************************/
+/* opengl_context.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#include "opengl_context.h"
+
+#include <pthread.h>
+#include "ppapi/gles2/gl2ext_ppapi.h"
+#include "os_nacl.h"
+#include "ppapi/cpp/instance.h"
+#include "ppapi/cpp/module.h"
+#include "ppapi/cpp/completion_callback.h"
+#include "ppapi/utility/completion_callback_factory.h"
+
+
+namespace {
+// This is called by the brower when the 3D context has been flushed to the
+// browser window.
+void FlushCallback(void* data, int32_t result) {
+ static_cast<OpenGLContext*>(data)->set_flush_pending(false);
+ static_cast<OpenGLContext*>(data)->FlushContext();
+}
+} // namespace
+
+OpenGLContext::OpenGLContext(pp::Instance* p_instance)
+ : pp::Graphics3DClient(p_instance),
+ flush_pending_(false) {
+
+ instance = p_instance;
+ pp::Module* module = pp::Module::Get();
+ assert(module);
+ gles2_interface_ = static_cast<const struct PPB_OpenGLES2_Dev*>(
+ module->GetBrowserInterface(PPB_OPENGLES2_INTERFACE));
+ assert(gles2_interface_);
+}
+
+OpenGLContext::~OpenGLContext() {
+ glSetCurrentContextPPAPI(0);
+}
+
+bool OpenGLContext::MakeContextCurrent(pp::Instance* instance) {
+
+ if (instance == NULL) {
+ glSetCurrentContextPPAPI(0);
+ return false;
+ }
+ // Lazily create the Pepper context.
+ if (context_.is_null()) {
+ int32_t attribs[] = {
+ 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_WIDTH, width,
+ PP_GRAPHICS3DATTRIB_HEIGHT, height,
+ PP_GRAPHICS3DATTRIB_NONE
+ };
+
+ context_ = pp::Graphics3D(instance, pp::Graphics3D(), attribs);
+ if (context_.is_null()) {
+ glSetCurrentContextPPAPI(0);
+ return false;
+ }
+ instance->BindGraphics(context_);
+ }
+ glSetCurrentContextPPAPI(context_.pp_resource());
+ return true;
+}
+
+void OpenGLContext::ResizeContext(const pp::Size& size) {
+
+ width = size.width();
+ height = size.height();
+
+ if (!context_.is_null()) {
+ context_.ResizeBuffers(size.width(), size.height());
+ }
+}
+
+
+void OpenGLContext::InvalidateContext(pp::Instance* instance) {
+ glSetCurrentContextPPAPI(0);
+}
+
+void OpenGLContext::FlushContext() {
+ if (flush_pending()) {
+ // A flush is pending so do nothing; just drop this flush on the floor.
+ return;
+ }
+ set_flush_pending(true);
+
+ OSNacl* os = (OSNacl*)OS::get_singleton();
+ MakeContextCurrent(instance);
+ os->iterate();
+
+ context_.SwapBuffers(pp::CompletionCallback(&FlushCallback, this));
+}
+
diff --git a/platform/nacl/opengl_context.h b/platform/nacl/opengl_context.h
new file mode 100644
index 0000000000..b0431f29bf
--- /dev/null
+++ b/platform/nacl/opengl_context.h
@@ -0,0 +1,124 @@
+/*************************************************************************/
+/* opengl_context.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#ifndef EXAMPLES_TUMBLER_OPENGL_CONTEXT_H_
+#define EXAMPLES_TUMBLER_OPENGL_CONTEXT_H_
+
+///
+/// @file
+/// OpenGLContext manages the OpenGL context in the browser that is associated
+/// with a @a pp::Instance instance.
+///
+
+#include <pthread.h>
+
+#include <algorithm>
+#include <string>
+
+#include "ppapi/c/ppb_opengles2.h"
+//#include "ppapi/cpp/dev/context_3d_dev.h"
+#include "ppapi/cpp/graphics_3d_client.h"
+#include "ppapi/cpp/graphics_3d.h"
+//#include "ppapi/cpp/dev/surface_3d_dev.h"
+#include "ppapi/cpp/instance.h"
+#include "ppapi/cpp/size.h"
+
+// A convenience wrapper for a shared OpenGLContext pointer type. As other
+// smart pointer types are needed, add them here.
+
+#include <tr1/memory>
+
+class OpenGLContext;
+
+typedef std::tr1::shared_ptr<OpenGLContext> SharedOpenGLContext;
+
+/// OpenGLContext manages an OpenGL rendering context in the browser.
+///
+class OpenGLContext : public pp::Graphics3DClient {
+ public:
+ explicit OpenGLContext(pp::Instance* instance);
+
+ /// Release all the in-browser resources used by this context, and make this
+ /// context invalid.
+ virtual ~OpenGLContext();
+
+ /// The Graphics3DClient interfcace.
+ virtual void Graphics3DContextLost() {
+ assert(!"Unexpectedly lost graphics context");
+ }
+
+ /// Make @a this the current 3D context in @a instance.
+ /// @param instance The instance of the NaCl module that will receive the
+ /// the current 3D context.
+ /// @return success.
+ bool MakeContextCurrent(pp::Instance* instance);
+
+ /// Flush the contents of this context to the browser's 3D device.
+ void FlushContext();
+
+ /// Make the underlying 3D device invalid, so that any subsequent rendering
+ /// commands will have no effect. The next call to MakeContextCurrent() will
+ /// cause the underlying 3D device to get rebound and start receiving
+ /// receiving rendering commands again. Use InvalidateContext(), for
+ /// example, when resizing the context's viewing area.
+ void InvalidateContext(pp::Instance* instance);
+
+ void ResizeContext(const pp::Size& size);
+
+ /// The OpenGL ES 2.0 interface.
+ const struct PPB_OpenGLES2_Dev* gles2() const {
+ return gles2_interface_;
+ }
+
+ /// The PP_Resource needed to make GLES2 calls through the Pepper interface.
+ const PP_Resource gl_context() const {
+ return context_.pp_resource();
+ }
+
+ /// Indicate whether a flush is pending. This can only be called from the
+ /// main thread; it is not thread safe.
+ bool flush_pending() const {
+ return flush_pending_;
+ }
+ void set_flush_pending(bool flag) {
+ flush_pending_ = flag;
+ }
+
+ private:
+ pp::Graphics3D context_;
+ bool flush_pending_;
+
+ int width, height;
+
+ pp::Instance* instance;
+
+ const struct PPB_OpenGLES2_Dev* gles2_interface_;
+};
+
+#endif // EXAMPLES_TUMBLER_OPENGL_CONTEXT_H_
+
diff --git a/platform/nacl/os_nacl.cpp b/platform/nacl/os_nacl.cpp
new file mode 100644
index 0000000000..d97195c50d
--- /dev/null
+++ b/platform/nacl/os_nacl.cpp
@@ -0,0 +1,529 @@
+/*************************************************************************/
+/* os_nacl.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#include "os_nacl.h"
+
+#include "drivers/unix/memory_pool_static_malloc.h"
+#include "os/memory_pool_dynamic_static.h"
+#include "main/main.h"
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <time.h>
+
+#include "io/file_access_memory.h"
+#include "core/io/file_access_pack.h"
+#include "scene/io/scene_loader.h"
+#include "scene/main/scene_main_loop.h"
+
+#include "servers/visual/visual_server_raster.h"
+
+#include "drivers/gles2/rasterizer_gles2.h"
+#include "nacl_keycodes.h"
+
+#include "core/globals.h"
+#include "core/input_map.h"
+
+#include <ppapi/cpp/point.h>
+#include <ppapi/cpp/var.h>
+
+#define UNIX_ENABLED
+#include "drivers/unix/thread_posix.h"
+#include "drivers/unix/semaphore_posix.h"
+#include "drivers/unix/mutex_posix.h"
+
+
+int OSNacl::get_video_driver_count() const {
+
+ return 1;
+};
+const char * OSNacl::get_video_driver_name(int p_driver) const {
+
+ return "gles2";
+};
+
+OS::VideoMode OSNacl::get_default_video_mode() const {
+
+ return OS::VideoMode(800,600,false);
+};
+
+int OSNacl::get_audio_driver_count() const {
+
+ return 1;
+};
+
+const char * OSNacl::get_audio_driver_name(int p_driver) const {
+
+ return "nacl_audio";
+};
+
+static MemoryPoolStaticMalloc *mempool_static=NULL;
+static MemoryPoolDynamicStatic *mempool_dynamic=NULL;
+
+void OSNacl::initialize_core() {
+
+ ticks_start=0;
+ ticks_start=get_ticks_usec();
+};
+
+void OSNacl::initialize(const VideoMode& p_desired,int p_video_driver,int p_audio_driver) {
+
+ rasterizer = memnew( RasterizerGLES2 );
+ visual_server = memnew( VisualServerRaster(rasterizer) );
+ visual_server->init();
+ visual_server->cursor_set_visible(false, 0);
+
+ audio_driver = memnew(AudioDriverNacl);
+ audio_driver->set_singleton();
+ audio_driver->init();
+
+ sample_manager = memnew( SampleManagerMallocSW );
+ audio_server = memnew( AudioServerSW(sample_manager) );
+ audio_server->set_mixer_params(AudioMixerSW::INTERPOLATION_LINEAR,false);
+ audio_server->init();
+
+ spatial_sound_server = memnew( SpatialSoundServerSW );
+ spatial_sound_server->init();
+
+ spatial_sound_2d_server = memnew( SpatialSound2DServerSW );
+ spatial_sound_2d_server->init();
+
+ //
+ physics_server = memnew( PhysicsServerSW );
+ physics_server->init();
+
+ physics_2d_server = memnew( Physics2DServerSW );
+ physics_2d_server->init();
+
+ input = memnew(InputDefault);
+};
+
+void OSNacl::set_main_loop( MainLoop * p_main_loop ) {
+
+ main_loop = p_main_loop;
+ input->set_main_loop(p_main_loop);
+ main_loop->init();
+};
+
+void OSNacl::delete_main_loop() {
+
+ if (main_loop)
+ memdelete(main_loop);
+};
+
+void OSNacl::finalize() {
+
+
+};
+void OSNacl::finalize_core() {
+
+ if (mempool_dynamic)
+ memdelete( mempool_dynamic );
+ if (mempool_static)
+ delete mempool_static;
+
+};
+
+void OSNacl::alert(const String& p_alert,const String& p_title) {
+
+ fprintf(stderr,"ERROR: %s\n",p_alert.utf8().get_data());
+};
+
+void OSNacl::vprint(const char* p_format, va_list p_list, bool p_strerr) {
+
+ vprintf(p_format,p_list);
+ fflush(stdout);
+}
+
+
+String OSNacl::get_stdin_string(bool p_block) {
+
+ char buff[1024];
+ return fgets(buff,1024,stdin);
+};
+
+void OSNacl::set_mouse_show(bool p_show) {
+
+};
+
+void OSNacl::set_mouse_grab(bool p_grab) {
+
+};
+
+bool OSNacl::is_mouse_grab_enabled() const {
+
+ return false;
+};
+
+int OSNacl::get_mouse_button_state() const {
+
+ return mouse_mask;
+};
+
+
+Point2 OSNacl::get_mouse_pos() const {
+
+ return Point2();
+};
+
+void OSNacl::set_window_title(const String& p_title) {
+};
+
+void OSNacl::set_video_mode(const VideoMode& p_video_mode, int p_screen) {
+
+ video_mode = p_video_mode;
+};
+
+OS::VideoMode OSNacl::get_video_mode(int p_screen) const {
+
+ return video_mode;
+};
+
+void OSNacl::get_fullscreen_mode_list(List<VideoMode> *p_list,int p_screen) const {
+
+};
+
+Error OSNacl::execute(const String& p_path, const List<String>& p_arguments,bool p_blocking, OS::ProcessID *r_child_id, String* r_pipe, int *r_exitcode) {
+
+ return ERR_UNAVAILABLE;
+};
+
+Error OSNacl::kill(const ProcessID& p_pid) {
+
+ return ERR_UNAVAILABLE;
+};
+
+bool OSNacl::has_environment(const String& p_var) const {
+
+ return getenv(p_var.utf8().get_data())!=NULL;
+};
+
+String OSNacl::get_environment(const String& p_var) const {
+
+ if (getenv(p_var.utf8().get_data()))
+ return getenv(p_var.utf8().get_data());
+ return "";
+};
+
+String OSNacl::get_name() {
+
+ return "NaCl";
+};
+
+MainLoop *OSNacl::get_main_loop() const {
+
+ return main_loop;
+};
+
+OS::Date OSNacl::get_date() const {
+
+ time_t t=time(NULL);
+ struct tm *lt=localtime(&t);
+ Date ret;
+ ret.year=lt->tm_year;
+ ret.month=(Month)lt->tm_mon;
+ ret.day=lt->tm_mday;
+ ret.weekday=(Weekday)lt->tm_wday;
+ ret.dst=lt->tm_isdst;
+
+ return ret;
+};
+
+OS::Time OSNacl::get_time() const {
+
+ time_t t=time(NULL);
+ struct tm *lt=localtime(&t);
+ Time ret;
+ ret.hour=lt->tm_hour;
+ ret.min=lt->tm_min;
+ ret.sec=lt->tm_sec;
+ return ret;
+};
+
+void OSNacl::delay_usec(uint32_t p_usec) const {
+
+ //usleep(p_usec);
+};
+
+uint64_t OSNacl::get_ticks_usec() const {
+
+ struct timeval tv_now;
+ gettimeofday(&tv_now,NULL);
+
+ uint64_t longtime = (uint64_t)tv_now.tv_usec + (uint64_t)tv_now.tv_sec*1000000L;
+ longtime-=ticks_start;
+
+ return longtime;
+};
+
+bool OSNacl::can_draw() const {
+
+ return minimized != true;
+};
+
+void OSNacl::queue_event(const InputEvent& p_event) {
+
+ ERR_FAIL_INDEX( event_count, MAX_EVENTS );
+
+ event_queue[event_count++] = p_event;
+};
+
+void OSNacl::add_package(String p_name, Vector<uint8_t> p_data) {
+
+ FileAccessMemory::register_file(p_name, p_data);
+ FileAccess::make_default<FileAccessMemory>(FileAccess::ACCESS_RESOURCES);
+ FileAccess::make_default<FileAccessMemory>(FileAccess::ACCESS_USERDATA);
+ FileAccess::make_default<FileAccessMemory>(FileAccess::ACCESS_FILESYSTEM);
+
+ if (!PackedData::get_singleton())
+ memnew(PackedData);
+
+ printf("adding package %ls, %x\n", p_name.c_str(), PackedData::get_singleton());
+ PackedData::get_singleton()->set_disabled(true);
+ PackedData::get_singleton()->add_pack(p_name);
+ PackedData::get_singleton()->set_disabled(false);
+ printf("added\n");
+};
+
+void OSNacl::set_cursor_shape(CursorShape p_shape) {
+
+
+};
+
+String OSNacl::get_resource_dir() const {
+
+ return ".";
+};
+
+static int mouse_button(int p_nacl_but) {
+
+ switch (p_nacl_but) {
+
+ case PP_INPUTEVENT_MOUSEBUTTON_LEFT:
+ return BUTTON_LEFT;
+ case PP_INPUTEVENT_MOUSEBUTTON_MIDDLE:
+ return BUTTON_MIDDLE;
+ case PP_INPUTEVENT_MOUSEBUTTON_RIGHT:
+ return BUTTON_RIGHT;
+ };
+
+ return 0;
+};
+
+static InputModifierState modifier(uint32_t p_mod) {
+
+ InputModifierState mod_mask;
+
+ mod_mask.shift = p_mod & PP_INPUTEVENT_MODIFIER_SHIFTKEY;
+ mod_mask.alt = p_mod & PP_INPUTEVENT_MODIFIER_ALTKEY;
+ mod_mask.control = p_mod & PP_INPUTEVENT_MODIFIER_CONTROLKEY;
+ mod_mask.meta = p_mod & PP_INPUTEVENT_MODIFIER_METAKEY;
+
+ return mod_mask;
+};
+
+
+
+void OSNacl::handle_event(const pp::InputEvent& p_event) {
+
+ int type = p_event.GetType();
+ switch (type) {
+
+ case PP_INPUTEVENT_TYPE_MOUSEDOWN:
+ case PP_INPUTEVENT_TYPE_MOUSEUP:
+ case PP_INPUTEVENT_TYPE_WHEEL: {
+
+ InputEvent event;
+ event.ID=++event_id;
+ event.type = InputEvent::MOUSE_BUTTON;
+ event.device=0;
+
+ pp::MouseInputEvent mevent(p_event);
+ if (type == PP_INPUTEVENT_TYPE_WHEEL) {
+
+ pp::WheelInputEvent wevent(p_event);;
+ float ticks = wevent.GetTicks().y();
+ if (ticks == 0)
+ break; // whut?
+
+ event.mouse_button.pressed = true;
+ event.mouse_button.button_index = ticks > 0 ? BUTTON_WHEEL_UP : BUTTON_WHEEL_DOWN;
+ event.mouse_button.doubleclick = false;
+
+ } else {
+
+ event.mouse_button.pressed = (type == PP_INPUTEVENT_TYPE_MOUSEDOWN);
+ event.mouse_button.button_index = mouse_button(mevent.GetButton());
+ event.mouse_button.doubleclick = (mevent.GetClickCount() % 2) == 0;
+
+ mouse_mask &= ~(1<< (event.mouse_button.button_index - 1));
+ mouse_mask |= (event.mouse_button.pressed << (event.mouse_button.button_index - 1));
+ };
+ pp::Point pos = mevent.GetPosition();
+ event.mouse_button.button_mask = mouse_mask;
+ event.mouse_button.global_x = pos.x();
+ event.mouse_button.x = pos.x();
+ event.mouse_button.global_y = pos.y();
+ event.mouse_button.y = pos.y();
+ event.mouse_button.pointer_index = 0;
+ event.mouse_button.mod = modifier(p_event.GetModifiers());
+ queue_event(event);
+
+ } break;
+
+ case PP_INPUTEVENT_TYPE_MOUSEMOVE: {
+
+ pp::MouseInputEvent mevent(p_event);
+ pp::Point pos = mevent.GetPosition();
+
+ InputEvent event;
+ event.ID=++event_id;
+ event.type = InputEvent::MOUSE_MOTION;
+ event.mouse_motion.pointer_index = 0;
+ event.mouse_motion.global_x = pos.x();
+ event.mouse_motion.global_y = pos.y();
+ event.mouse_motion.x = pos.x();
+ event.mouse_motion.y = pos.y();
+ event.mouse_motion.button_mask = mouse_mask;
+ event.mouse_motion.mod = modifier(p_event.GetModifiers());
+
+ event.mouse_motion.relative_x = pos.x() - mouse_last_x;
+ event.mouse_motion.relative_y = pos.y() - mouse_last_y;
+ mouse_last_x = pos.x();
+ mouse_last_y = pos.y();
+
+ queue_event(event);
+
+ } break;
+
+ case PP_INPUTEVENT_TYPE_RAWKEYDOWN:
+ case PP_INPUTEVENT_TYPE_KEYDOWN:
+ case PP_INPUTEVENT_TYPE_KEYUP: {
+
+ pp::KeyboardInputEvent kevent(p_event);
+ bool is_char;
+ uint32_t key = godot_key(kevent.GetKeyCode(), is_char);
+ if (type != PP_INPUTEVENT_TYPE_KEYUP && is_char) {
+
+ last_scancode = key;
+ break;
+ };
+
+ InputEvent event;
+ event.ID=++event_id;
+ event.type = InputEvent::KEY;
+ event.key.pressed = (type != PP_INPUTEVENT_TYPE_KEYUP);
+ event.key.scancode = key;
+ event.key.unicode = key;
+
+ event.key.echo = p_event.GetModifiers() & PP_INPUTEVENT_MODIFIER_ISAUTOREPEAT;
+ event.key.mod = modifier(p_event.GetModifiers());
+ queue_event(event);
+ } break;
+
+ case PP_INPUTEVENT_TYPE_CHAR: {
+
+ pp::KeyboardInputEvent kevent(p_event);
+ InputEvent event;
+ event.ID = ++event_id;
+ event.type = InputEvent::KEY;
+ event.key.pressed = true;
+ event.key.scancode = last_scancode;
+ event.key.unicode = kevent.GetCharacterText().AsString().c_str()[0];
+ event.key.mod = modifier(p_event.GetModifiers());
+ event.key.echo = p_event.GetModifiers() & PP_INPUTEVENT_MODIFIER_ISAUTOREPEAT;
+ queue_event(event);
+
+ } break;
+
+ /*
+ case NPEventType_Minimize: {
+
+ minimized = p_event->u.minimize.value == 1;
+
+ } break;
+
+
+ case NPEventType_Focus: {
+
+ if (p_event->u.focus.value == 1) {
+ main_loop->notification(MainLoop::NOTIFICATION_WM_FOCUS_IN);
+ } else {
+ main_loop->notification(MainLoop::NOTIFICATION_WM_FOCUS_OUT);
+ };
+ } break;
+
+ */
+
+ default:
+ ;
+ };
+};
+
+bool OSNacl::iterate() {
+
+ if (!main_loop) {
+ event_count = 0;
+ return true;
+ };
+
+ for (int i=0; i<event_count; i++) {
+
+ input->parse_input_event(event_queue[i]);
+ };
+
+ event_count = 0;
+
+ return Main::iteration();
+};
+
+
+OSNacl::OSNacl() {
+
+ main_loop=NULL;
+ mempool_dynamic = NULL;
+ mempool_static = NULL;
+ mouse_last_x = 0;
+ mouse_last_y = 0;
+ event_count = 0;
+ event_id = 0;
+ mouse_mask = 0;
+ video_mode = get_default_video_mode();
+ last_scancode = 0;
+ minimized = false;
+
+ ThreadPosix::make_default();
+ SemaphorePosix::make_default();
+ MutexPosix::make_default();
+ mempool_static = new MemoryPoolStaticMalloc;
+ mempool_dynamic = memnew( MemoryPoolDynamicStatic );
+};
+
+OSNacl::~OSNacl() {
+
+};
diff --git a/platform/nacl/os_nacl.h b/platform/nacl/os_nacl.h
new file mode 100644
index 0000000000..b8173ef61c
--- /dev/null
+++ b/platform/nacl/os_nacl.h
@@ -0,0 +1,156 @@
+/*************************************************************************/
+/* os_nacl.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#ifndef OS_NACL_H
+#define OS_NACL_H
+
+#include "core/os/os.h"
+
+#include "servers/visual_server.h"
+#include "servers/visual/rasterizer.h"
+#include "servers/physics/physics_server_sw.h"
+#include "servers/spatial_sound/spatial_sound_server_sw.h"
+#include "servers/spatial_sound_2d/spatial_sound_2d_server_sw.h"
+#include "servers/audio/audio_server_sw.h"
+#include "servers/physics_2d/physics_2d_server_sw.h"
+#include "audio_driver_nacl.h"
+#include "os/input.h"
+
+
+#include <ppapi/cpp/input_event.h>
+
+class OSNacl : OS {
+
+ uint64_t ticks_start;
+
+protected:
+
+ enum {
+ MAX_EVENTS = 64,
+ };
+
+ MainLoop *main_loop;
+
+ Rasterizer *rasterizer;
+ VisualServer *visual_server;
+ PhysicsServer *physics_server;
+ SpatialSoundServerSW *spatial_sound_server;
+
+ AudioServerSW *audio_server;
+ SampleManagerMallocSW *sample_manager;
+ SpatialSound2DServerSW *spatial_sound_2d_server;
+ Physics2DServer *physics_2d_server;
+ AudioDriverNacl* audio_driver;
+
+
+ // functions used by main to initialize/deintialize the OS
+ virtual int get_video_driver_count() const;
+ virtual const char * get_video_driver_name(int p_driver) const;
+
+ virtual VideoMode get_default_video_mode() const;
+
+ virtual int get_audio_driver_count() const;
+ virtual const char * get_audio_driver_name(int p_driver) const;
+
+ void vprint(const char* p_format, va_list p_list, bool p_stderr);
+
+ virtual void initialize_core();
+ virtual void initialize(const VideoMode& p_desired,int p_video_driver,int p_audio_driver);
+
+ virtual void set_main_loop( MainLoop * p_main_loop );
+ virtual void delete_main_loop();
+
+ virtual void finalize();
+ virtual void finalize_core();
+
+ int mouse_last_x, mouse_last_y;
+
+ InputEvent event_queue[MAX_EVENTS];
+ int event_count;
+ void queue_event(const InputEvent& p_event);
+
+ int event_id;
+ uint32_t mouse_mask;
+
+ uint32_t last_scancode;
+
+ bool minimized;
+
+ VideoMode video_mode;
+
+ InputDefault *input;
+
+public:
+
+ void add_package(String p_name, Vector<uint8_t> p_data);
+
+ void handle_event(const pp::InputEvent& p_event);
+
+ virtual void alert(const String& p_alert,const String& p_title);
+ virtual String get_stdin_string(bool p_block);
+
+ virtual void set_mouse_show(bool p_show);
+ virtual void set_mouse_grab(bool p_grab);
+ virtual bool is_mouse_grab_enabled() const;
+ virtual Point2 get_mouse_pos() const;
+ virtual int get_mouse_button_state() const;
+ virtual void set_window_title(const String& p_title);
+
+ virtual void set_video_mode(const VideoMode& p_video_mode,int p_screen);
+ virtual VideoMode get_video_mode(int p_screen) const;
+ virtual void get_fullscreen_mode_list(List<VideoMode> *p_list,int p_screen) const;
+
+ virtual Error execute(const String& p_path, const List<String>& p_arguments,bool p_blocking,ProcessID *r_child_id=NULL,String* r_pipe=NULL,int *r_exitcode=NULL);
+ virtual Error kill(const ProcessID& p_pid);
+
+ virtual bool has_environment(const String& p_var) const;
+ virtual String get_environment(const String& p_var) const;
+
+ virtual void set_cursor_shape(CursorShape p_shape);
+
+ virtual String get_name();
+
+ virtual MainLoop *get_main_loop() const;
+
+ virtual Date get_date() const;
+ virtual Time get_time() const;
+
+ virtual void delay_usec(uint32_t p_usec) const;
+ virtual uint64_t get_ticks_usec() const;
+
+ virtual String get_resource_dir() const;
+
+ virtual bool can_draw() const;
+
+ bool iterate();
+
+ OSNacl();
+ ~OSNacl();
+};
+
+#endif // OS_NACL_H
diff --git a/platform/nacl/pepper_main.cpp b/platform/nacl/pepper_main.cpp
new file mode 100644
index 0000000000..6a1f4acbe7
--- /dev/null
+++ b/platform/nacl/pepper_main.cpp
@@ -0,0 +1,541 @@
+/*************************************************************************/
+/* pepper_main.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+ IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
+ ("Apple") in consideration of your agreement to the following terms, and
+ your use, installation, modification or redistribution of this Apple software
+ constitutes acceptance of these terms. If you do not agree with these terms,
+ please do not use, install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive license,
+ under Apple's copyrights in this original Apple software
+ (the "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following text and
+ disclaimers in all such redistributions of the Apple Software. Neither the
+ name, trademarks, service marks or logos of Apple Computer, Inc. may be used
+ to endorse or promote products derived from the Apple Software without
+ specific prior written permission from Apple. Except as expressly stated in
+ this notice, no other rights or licenses, express or implied, are granted by
+ Apple herein, including but not limited to any patent rights that may be
+ infringed by your derivative works or by other works in which the Apple
+ Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
+ WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+ WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
+ COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION
+ AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER
+ THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR
+ OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdlib.h>
+
+#include "os_nacl.h"
+#include <GLES2/gl2.h>
+
+#include <nacl/npupp.h>
+#include <pgl/pgl.h>
+#include <string.h>
+#include <stdint.h>
+
+static NPNetscapeFuncs kBrowserFuncs = { 0 };
+static NPNetscapeFuncs* browser = &kBrowserFuncs;
+
+static NPDevice* device3d_ = NULL;
+static PGLContext pgl_context_;
+static NPDeviceContext3D context3d_;
+static int width_;
+static int height_;
+
+extern int nacl_main(int argc, char** argn, char** argv);
+extern void nacl_cleanup();
+
+NPExtensions* extensions = NULL;
+static NPP npp_;
+
+const int32_t kCommandBufferSize = 1024 * 1024;
+
+// Plugin entry points
+extern "C" {
+
+// Plugin entry points
+
+// Entrypoints -----------------------------------------------------------------
+
+NPError NP_GetEntryPoints(NPPluginFuncs* plugin_funcs) {
+ plugin_funcs->version = 11;
+ plugin_funcs->size = sizeof(plugin_funcs);
+ plugin_funcs->newp = NPP_New;
+ plugin_funcs->destroy = NPP_Destroy;
+ plugin_funcs->setwindow = NPP_SetWindow;
+ plugin_funcs->newstream = NPP_NewStream;
+ plugin_funcs->destroystream = NPP_DestroyStream;
+ plugin_funcs->asfile = NPP_StreamAsFile;
+ plugin_funcs->writeready = NPP_WriteReady;
+ plugin_funcs->write = (NPP_WriteUPP)NPP_Write;
+ plugin_funcs->print = NPP_Print;
+ plugin_funcs->event = NPP_HandleEvent;
+ plugin_funcs->urlnotify = NPP_URLNotify;
+ plugin_funcs->getvalue = NPP_GetValue;
+ plugin_funcs->setvalue = NPP_SetValue;
+
+ return NPERR_NO_ERROR;
+}
+
+NPError NP_Shutdown() {
+ pglTerminate();
+ return NPERR_NO_ERROR;
+}
+
+NPError NP_GetValue(void* instance, NPPVariable variable, void* value);
+char* NP_GetMIMEDescription();
+
+NPError NP_Initialize(NPNetscapeFuncs* browser_funcs,
+ NPPluginFuncs* plugin_funcs) {
+ printf("NPP_Initialize\n");
+ memcpy(&kBrowserFuncs, browser_funcs, sizeof(kBrowserFuncs));
+ pglInitialize();
+ return NP_GetEntryPoints(plugin_funcs);
+}
+
+
+} // extern "C"
+
+void Initialize3D() {
+ // Initialize a 3D context.
+ NPDeviceContext3DConfig config;
+ config.commandBufferSize = kCommandBufferSize;
+ NPError err = device3d_->initializeContext(npp_, &config, &context3d_);
+ if (err != NPERR_NO_ERROR) {
+ printf("Failed to initialize 3D context\n");
+ exit(1);
+ }
+
+ // Create a PGL context.
+ pgl_context_ = pglCreateContext(npp_, device3d_, &context3d_);
+
+ // Initialize the demo GL state.
+ //pglMakeCurrent(pgl_context_);
+ //GLFromCPPInit();
+ //pglMakeCurrent(NULL);
+}
+
+NPError NPP_New(NPMIMEType pluginType,
+ NPP instance,
+ uint16_t mode,
+ int16_t argc, char* argn[], char* argv[],
+ NPSavedData* saved) {
+ printf("NPP_New\n");
+ if (browser->version >= 14) {
+
+ npp_ = instance;
+ if (!extensions) {
+ browser->getvalue(npp_, NPNVPepperExtensions,
+ reinterpret_cast<void*>(&extensions));
+ // CHECK(extensions);
+ }
+
+ printf("%s: %i\n", __FUNCTION__, __LINE__);
+
+ device3d_ = extensions->acquireDevice(npp_, NPPepper3DDevice);
+ if (device3d_ == NULL) {
+ printf("Failed to acquire 3DDevice\n");
+ exit(1);
+ }
+ printf("%s: %i\n", __FUNCTION__, __LINE__);
+
+ /*
+ deviceaudio_ = extensions->acquireDevice(npp_, NPPepperAudioDevice);
+ if (deviceaudio_ == NULL) {
+ printf("Failed to acquire AudioDevice\n");
+ exit(1);
+ }
+ */
+ Initialize3D();
+ pglMakeCurrent(pgl_context_);
+ nacl_main(argc, argn, argv);
+ pglMakeCurrent(NULL);
+ };
+
+ return NPERR_NO_ERROR;
+}
+
+NPError NPP_Destroy(NPP instance, NPSavedData** save) {
+
+ nacl_cleanup();
+
+ return NPERR_NO_ERROR;
+}
+
+void Destroy3D() {
+ printf("destroy 3d\n");
+ // Destroy the PGL context.
+ pglDestroyContext(pgl_context_);
+ pgl_context_ = NULL;
+
+ // Destroy the Device3D context.
+ device3d_->destroyContext(npp_, &context3d_);
+}
+
+static void iteration(void* data) {
+
+ (void)data;
+ OSNacl* os = (OSNacl*)OS::get_singleton();
+
+ if (!pglMakeCurrent(pgl_context_) && pglGetError() == PGL_CONTEXT_LOST) {
+ printf("******* Lost context! :O\n");
+ Destroy3D();
+ Initialize3D();
+ pglMakeCurrent(pgl_context_);
+ }
+
+ glViewport(0, 0, width_, height_);
+
+ os->iterate();
+
+ pglSwapBuffers();
+ pglMakeCurrent(NULL);
+
+ browser->pluginthreadasynccall(npp_, iteration, NULL);
+};
+
+NPError NPP_SetWindow(NPP instance, NPWindow* window) {
+
+ width_ = window->width;
+ height_ = window->height;
+
+ if (!pgl_context_)
+ Initialize3D();
+
+ // Schedule the first call to Draw.
+ OSNacl* os = (OSNacl*)OS::get_singleton();
+ OS::VideoMode vm;
+ vm.width = width_;
+ vm.height = height_;
+ vm.resizable = false;
+ vm.fullscreen = false;
+ os->set_video_mode(vm);
+
+ browser->pluginthreadasynccall(npp_, iteration, NULL);
+
+ return NPERR_NO_ERROR;
+}
+
+NPError NPP_NewStream(NPP instance,
+ NPMIMEType type,
+ NPStream* stream,
+ NPBool seekable,
+ uint16_t* stype) {
+ *stype = NP_ASFILEONLY;
+ return NPERR_NO_ERROR;
+}
+
+NPError NPP_DestroyStream(NPP instance, NPStream* stream, NPReason reason) {
+ return NPERR_NO_ERROR;
+}
+
+void NPP_StreamAsFile(NPP instance, NPStream* stream, const char* fname) {
+}
+
+int32_t NPP_Write(NPP instance,
+ NPStream* stream,
+ int32_t offset,
+ int32_t len,
+ void* buffer) {
+ return 0;
+}
+
+int32_t NPP_WriteReady(NPP instance, NPStream* stream) {
+ return 0;
+}
+
+void NPP_Print(NPP instance, NPPrint* platformPrint) {
+}
+
+int16_t NPP_HandleEvent(NPP instance, void* event) {
+
+ OSNacl* os = (OSNacl*)OS::get_singleton();
+ os->handle_event(event);
+ return 1;
+}
+
+void NPP_URLNotify(NPP instance,
+ const char* url,
+ NPReason reason,
+ void* notify_data) {
+ // PluginObject* obj = static_cast<PluginObject*>(instance->pdata);
+}
+
+static NPObject* Allocate(NPP npp, NPClass* npclass) {
+ return new NPObject;
+}
+
+static void Deallocate(NPObject* object) {
+ delete object;
+}
+
+// Return |true| if |method_name| is a recognized method.
+static bool HasMethod(NPObject* obj, NPIdentifier method_name) {
+
+ char *name = NPN_UTF8FromIdentifier(method_name);
+ bool is_method = false;
+ if (strcmp((const char *)name, "start_package") == 0) {
+ is_method = true;
+ } else if (strcmp((const char*)name, "add_package_chunk") == 0) {
+ is_method = true;
+ } else if (strcmp((const char*)name, "end_package") == 0) {
+ is_method = true;
+ } else if (strcmp((const char*)name, "start_scene") == 0) {
+ is_method = true;
+ }
+ NPN_MemFree(name);
+ return is_method;
+}
+
+// I don't know what this is
+static bool InvokeDefault(NPObject *obj, const NPVariant *args,
+ uint32_t argCount, NPVariant *result) {
+ if (result) {
+ NULL_TO_NPVARIANT(*result);
+ }
+ return true;
+}
+
+static uint8_t* mem = NULL;
+static int pkg_size = 0;
+static String pkgname;
+
+static bool variant_is_number(const NPVariant& v) {
+
+ switch (v.type) {
+
+ case NPVariantType_Int32:
+ case NPVariantType_Double:
+ return true;
+
+ default:
+ return false;
+ }
+ return false;
+};
+
+static double variant_as_number(const NPVariant& v) {
+
+ switch (v.type) {
+
+ case NPVariantType_Int32:
+ return (double)v.value.intValue;
+ case NPVariantType_Double:
+ return (double)v.value.doubleValue;
+ default:
+ return 0;
+ }
+
+ return 0;
+};
+
+// Invoke() is called by the browser to invoke a function object whose name
+// is |method_name|.
+static bool Invoke(NPObject* obj,
+ NPIdentifier method_name,
+ const NPVariant *args,
+ uint32_t arg_count,
+ NPVariant *result) {
+ NULL_TO_NPVARIANT(*result);
+ char *name = NPN_UTF8FromIdentifier(method_name);
+ if (name == NULL)
+ return false;
+ bool rval = false;
+
+ OSNacl* os = (OSNacl*)OS::get_singleton();
+
+ if (strcmp(name, "start_package") == 0) {
+
+ printf("arg count is %i\n", arg_count);
+ for (int i=0; i<arg_count; i++) {
+ printf("type for %i is %i\n", i, args[i].type);
+ }
+ if (arg_count != 2) {
+ return false; // assuming "false" means error
+ };
+
+ if (args[0].type != NPVariantType_String) {
+ printf("arg 0 not string type %i\n", args[1].type);
+ return false;
+ };
+
+ if (!variant_is_number(args[1])) {
+
+ printf("arg 1 not number, type %i\n", args[1].type);
+ return false;
+ };
+
+ pkgname = String::utf8(args[0].value.stringValue.UTF8Characters, args[0].value.stringValue.UTF8Length);
+ pkg_size = (int)variant_as_number(args[1]);
+ mem = (uint8_t*)malloc(pkg_size);
+
+ printf("args %ls, %lf\n", pkgname.c_str(), variant_as_number(args[1]));
+
+ return true;
+ };
+
+ if (strcmp(name, "add_package_chunk") == 0) {
+
+ if (arg_count != 3) { // assuming arg_count starts from 1
+ return false; // assuming "false" means error
+ };
+
+ if (!variant_is_number(args[0])) return false;
+ if (args[1].type != NPVariantType_String) return false;
+ if (!variant_is_number(args[2])) return false;
+
+ if (!mem)
+ return false;
+
+ int ofs = variant_as_number(args[0]);
+ int len = variant_as_number(args[2]);
+
+ String s;
+ if (s.parse_utf8(args[1].value.stringValue.UTF8Characters, args[1].value.stringValue.UTF8Length)) {
+ printf("error parsing?\n");
+ };
+ uint8_t* dst = mem + ofs;
+ for (int i=0; i<len; i++) {
+
+ dst[i] = s[i];
+ };
+
+ //memcpy(mem + ofs, args[1].value.stringValue.UTF8Characters, len);
+ return true;
+ };
+
+ if (strcmp(name, "end_package") == 0) {
+
+ os->add_package(pkgname, mem, pkg_size);
+ return true;
+ };
+
+
+ if (strcmp(name, "start_scene") == 0) {
+printf("start_scene!\n");
+ if (arg_count != 1) {
+ return false;
+ };
+
+ if (args[0].type != NPVariantType_String) return false;
+printf("calling with param %s\n", args[0].value.stringValue.UTF8Characters);
+
+ printf("pepper iteration\n");
+ if (!pglMakeCurrent(pgl_context_) && pglGetError() == PGL_CONTEXT_LOST) {
+ printf("******* Lost context! :O\n");
+ Destroy3D();
+ Initialize3D();
+ pglMakeCurrent(pgl_context_);
+ }
+ os->start_scene(String::utf8(args[0].value.stringValue.UTF8Characters));
+ pglSwapBuffers();
+ pglMakeCurrent(NULL);
+
+printf("returning true\n");
+ return true;
+ };
+
+ NPN_MemFree(name);
+
+ return rval;
+}
+
+
+static NPClass GodotClass = {
+ NP_CLASS_STRUCT_VERSION,
+ Allocate,
+ Deallocate,
+ NULL, // Invalidate is not implemented
+ HasMethod,
+ Invoke,
+ InvokeDefault,
+ NULL, // HasProperty is not implemented
+ NULL, // GetProperty is not implemented
+ NULL, // SetProperty is not implemented
+};
+
+static NPObject* npobject = NULL;
+
+NPError NPP_GetValue(NPP instance, NPPVariable variable, void* value) {
+ NPError err = NPERR_NO_ERROR;
+
+ switch (variable) {
+ case NPPVpluginNameString:
+ *(reinterpret_cast<const char**>(value)) = "Pepper Test PlugIn";
+ break;
+ case NPPVpluginDescriptionString:
+ *(reinterpret_cast<const char**>(value)) =
+ "Simple Pepper plug-in for manual testing.";
+ break;
+ case NPPVpluginNeedsXEmbed:
+ *(reinterpret_cast<NPBool*>(value)) = 1;
+ break;
+ case NPPVpluginScriptableNPObject: {
+ if (npobject == NULL) {
+ npobject = NPN_CreateObject(instance, &GodotClass);
+ } else {
+ NPN_RetainObject(npobject);
+ };
+ void** v = reinterpret_cast<void**>(value);
+ *v = npobject;
+ } break;
+ default:
+ fprintf(stderr, "Unhandled variable to NPP_GetValue\n");
+ err = NPERR_GENERIC_ERROR;
+ break;
+ }
+
+ return err;
+}
+
+NPError NPP_SetValue(NPP instance, NPNVariable variable, void* value) {
+ return NPERR_GENERIC_ERROR;
+}
+
+NPError NP_GetValue(void* instance, NPPVariable variable, void* value) {
+ return NPP_GetValue(reinterpret_cast<NPP>(instance), variable, value);
+}
+
+char* NP_GetMIMEDescription() {
+ return const_cast<char*>("pepper-application/x-pepper-test-plugin;");
+}
diff --git a/platform/nacl/platform_config.h b/platform/nacl/platform_config.h
new file mode 100644
index 0000000000..38fc934ae4
--- /dev/null
+++ b/platform/nacl/platform_config.h
@@ -0,0 +1,29 @@
+/*************************************************************************/
+/* platform_config.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#include <alloca.h>