diff options
author | Juan Linietsky <reduzio@gmail.com> | 2014-02-09 22:10:30 -0300 |
---|---|---|
committer | Juan Linietsky <reduzio@gmail.com> | 2014-02-09 22:10:30 -0300 |
commit | 0b806ee0fc9097fa7bda7ac0109191c9c5e0a1ac (patch) | |
tree | 276c4d099e178eb67fbd14f61d77b05e3808e9e3 /platform/nacl | |
parent | 0e49da1687bc8192ed210947da52c9e5c5f301bb (diff) |
GODOT IS OPEN SOURCE
Diffstat (limited to 'platform/nacl')
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 Binary files differnew file mode 100644 index 0000000000..1793aa7e7a --- /dev/null +++ b/platform/nacl/html/icon_128.png diff --git a/platform/nacl/html/icon_16.png b/platform/nacl/html/icon_16.png Binary files differnew file mode 100644 index 0000000000..09de19e418 --- /dev/null +++ b/platform/nacl/html/icon_16.png 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 = '<none>'; + 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 Binary files differnew file mode 100644 index 0000000000..aac72c01b2 --- /dev/null +++ b/platform/nacl/logo.png 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> |