summaryrefslogtreecommitdiff
path: root/platform/nacl/pepper_main.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'platform/nacl/pepper_main.cpp')
-rw-r--r--platform/nacl/pepper_main.cpp541
1 files changed, 541 insertions, 0 deletions
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;");
+}