/*************************************************************************/ /* pepper_main.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2016 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 #include "os_nacl.h" #include #include #include #include #include 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(&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(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; iadd_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(value)) = "Pepper Test PlugIn"; break; case NPPVpluginDescriptionString: *(reinterpret_cast(value)) = "Simple Pepper plug-in for manual testing."; break; case NPPVpluginNeedsXEmbed: *(reinterpret_cast(value)) = 1; break; case NPPVpluginScriptableNPObject: { if (npobject == NULL) { npobject = NPN_CreateObject(instance, &GodotClass); } else { NPN_RetainObject(npobject); }; void** v = reinterpret_cast(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(instance), variable, value); } char* NP_GetMIMEDescription() { return const_cast("pepper-application/x-pepper-test-plugin;"); }