From f4f5219f0017d36e1b14fc4b88e9006b59c75b3f Mon Sep 17 00:00:00 2001 From: Svenn-Arne Dragly Date: Thu, 25 Feb 2016 15:36:22 +0100 Subject: Update support for Emscripten MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I5d696f0dbc188acb4faad83240f7b1aa7177dc48 Reviewed-by: Svenn-Arne Dragly Reviewed-by: Morten Johan Sørvig --- mkspecs/features/qt.prf | 25 ++ mkspecs/unsupported/nacl-emscripten/qmake.conf | 22 +- nacl-configure | 5 +- src/corelib/global/qsystemdetection.h | 2 + src/corelib/kernel/qeventdispatcher_unix.cpp | 5 +- src/corelib/kernel/qfunctions_nacl.cpp | 13 +- src/corelib/kernel/qfunctions_nacl.h | 4 +- src/corelib/plugin/qlibrary.cpp | 2 +- src/corelib/plugin/qplugin.h | 16 +- src/corelib/thread/qmutex.cpp | 6 + src/corelib/thread/qmutex_unix.cpp | 4 + src/corelib/thread/qwaitcondition_unix.cpp | 17 + src/corelib/tools/qsimd.cpp | 4 + src/gui/opengl/qopenglfunctions.h | 2 +- src/gui/opengl/qopengltexturehelper.cpp | 56 +++ .../platforms/pepper/3rdparty/pepper.js/audio.js | 5 + .../platforms/pepper/3rdparty/pepper.js/base.js | 64 ++++ .../platforms/pepper/3rdparty/pepper.js/common.js | 415 +++++++++++++++++++++ .../platforms/pepper/3rdparty/pepper.js/file.js | 5 + .../platforms/pepper/3rdparty/pepper.js/gles.js | 79 +++- .../pepper/3rdparty/pepper.js/gles_ext.js | 28 ++ .../pepper/3rdparty/pepper.js/graphics_2d.js | 5 + .../pepper/3rdparty/pepper.js/graphics_3d.js | 10 +- .../pepper/3rdparty/pepper.js/input_events.js | 39 +- .../pepper/3rdparty/pepper.js/mouse_lock.js | 5 + .../pepper/3rdparty/pepper.js/ppapi_preamble.js | 21 +- .../platforms/pepper/3rdparty/pepper.js/testing.js | 5 + .../pepper/3rdparty/pepper.js/url_loader.js | 5 + .../platforms/pepper/3rdparty/pepper.js/view.js | 16 + .../pepper/3rdparty/pepper.js/web_socket.js | 5 + src/plugins/platforms/pepper/pepper.js.pri | 52 ++- .../platforms/pepper/qpeppereventdispatcher.cpp | 35 +- .../platforms/pepper/qpeppereventdispatcher.h | 1 + .../platforms/pepper/qpepperfontdatabase.cpp | 2 + src/plugins/platforms/pepper/qpepperglcontext.cpp | 14 +- src/plugins/platforms/pepper/qpepperpluginmain.cpp | 75 ++-- src/tools/nacldeployqt/main.cpp | 16 +- src/tools/nacldeployqt/template_qtloader.cpp | 25 +- 38 files changed, 1000 insertions(+), 110 deletions(-) create mode 100644 src/plugins/platforms/pepper/3rdparty/pepper.js/common.js diff --git a/mkspecs/features/qt.prf b/mkspecs/features/qt.prf index f62b6bb139..06d1afe5ea 100644 --- a/mkspecs/features/qt.prf +++ b/mkspecs/features/qt.prf @@ -278,6 +278,31 @@ contains(qt_module_deps, qml): \ "rsync -r --exclude='*.a' --exclude='*.prl' --exclude='*.qmltypes' " macx-xcode: QMAKE_POST_LINK += "$p/ $$qmlTargetPath; done" else: QMAKE_POST_LINK += "\$\$p/ $$qmlTargetPath; done" + } else:emscripten { + isEmpty(QMAKE_QML_BUNDLE_PATH):QMAKE_QML_BUNDLE_PATH = "qt_qml" + qmlTargetPath = $$OUT_PWD/$$QMAKE_QML_BUNDLE_PATH + qtconfTargetPath = $$OUT_PWD/qt.conf + + # set import path in qt.conf to point to the bundeled qml: + QT_CONF_CONTENTS = \ + "[Paths]" \ + "Imports = $$QMAKE_QML_BUNDLE_PATH" \ + "Qml2Imports = $$QMAKE_QML_BUNDLE_PATH" + write_file("$$OUT_PWD/qt.conf", QT_CONF_CONTENTS)|error("Aborting.") + + # write qt.conf and copy each qml import dir into the bundle. + # But strip away archives and other files that are not needed: + !isEmpty(QMAKE_POST_LINK): QMAKE_POST_LINK += ";" + QMAKE_POST_LINK += \ + "test -d $$qmlTargetPath && rm -r $$qmlTargetPath; " \ + "mkdir -p $$qmlTargetPath && " \ + "for p in $$QMLPATHS; do" \ + "rsync -r --exclude='*.a' --exclude='*.so' --exclude='*.prl' --exclude='*.qmltypes' " \ + "\$\$p/ $$qmlTargetPath; done" + + # Add the folder and qt.conf to be preloaded by emscripten + QMAKE_LFLAGS += --preload-file qt_qml + QMAKE_LFLAGS += --preload-file qt.conf } } } diff --git a/mkspecs/unsupported/nacl-emscripten/qmake.conf b/mkspecs/unsupported/nacl-emscripten/qmake.conf index 8b28a753a4..819ab58b72 100644 --- a/mkspecs/unsupported/nacl-emscripten/qmake.conf +++ b/mkspecs/unsupported/nacl-emscripten/qmake.conf @@ -2,6 +2,8 @@ # qmake configuration for building with nacl-emscripten # +QMAKE_INCDIR += $$(EMSCRIPTEN)/system/include + include(../../common/unix.conf) include(../../common/gcc-base-unix.conf) include(../../common/g++-unix.conf) @@ -16,22 +18,30 @@ QMAKE_LINK = em++ QMAKE_LINK_SHLIB = em++ QMAKE_AR = emar r -CONFIG += emscripten +CONFIG *= emscripten # Uset default NaCl setting QMAKE_LIBS_OPENGL_ES2= -# Qt adds -I/path/to/qt/include, which triggers a "may be host include" -# warning. It isn't: silence the warning. -QMAKE_CXXFLAGS += -Wno-warn-absolute-paths -QMAKE_LFLAGS += -Wl,-Wno-warn-absolute-paths +emscripten_pthreads { + CONFIG += emscripten_pthreads + QMAKE_CXXFLAGS += -s USE_PTHREADS=1 \ + + QMAKE_LFLAGS += -s USE_PTHREADS=1 \ + -s PTHREAD_POOL_SIZE=4\ + +} + +QMAKE_LFLAGS += -Wl # Add link-time pepper platform plugin javascript dependencies and # required emscripten linker options. PEPPER_JS_PATH=$$PWD/../../../src/plugins/platforms/pepper/3rdparty/pepper.js + QMAKE_LFLAGS += \ -s RESERVED_FUNCTION_POINTERS=400\ - -s TOTAL_MEMORY=512000000\ + -s TOTAL_MEMORY=1280000000\ + -s FULL_ES2=1 \ -s EXPORTED_FUNCTIONS=\"[\'_DoPostMessage\', \'_DoChangeView\', \'_DoChangeFocus\', \'_NativeCreateInstance\', \'_HandleInputEvent\']\"\ --pre-js $${PEPPER_JS_PATH}/ppapi_preamble.js\ --pre-js $${PEPPER_JS_PATH}/base.js\ diff --git a/nacl-configure b/nacl-configure index 3dbd9fda9c..d53bc6bec0 100755 --- a/nacl-configure +++ b/nacl-configure @@ -229,6 +229,10 @@ fi if [[ $TOOLCHAIN == emscripten ]] then NACL_CONFIGURE_LINE="$NACL_CONFIGURE_LINE -no-xlib -no-xcb-xlib -no-eglfs" + # emscripten needs to enforce OpenGL ES 2 + NACL_CONFIGURE_LINE="$NACL_CONFIGURE_LINE -opengl es2" + # emscripten needs a static build for plugins to work properly + NACL_CONFIGURE_LINE="$NACL_CONFIGURE_LINE -static" fi # set release/debug build @@ -247,4 +251,3 @@ echo $NACL_CONFIGURE_LINE # Run configure $NACL_CONFIGURE_LINE - diff --git a/src/corelib/global/qsystemdetection.h b/src/corelib/global/qsystemdetection.h index 250f186926..74c734e245 100644 --- a/src/corelib/global/qsystemdetection.h +++ b/src/corelib/global/qsystemdetection.h @@ -330,7 +330,9 @@ # define Q_OS_PNACL #endif #ifdef __EMSCRIPTEN__ +# ifndef Q_OS_NACL_EMSCRIPTEN # define Q_OS_NACL_EMSCRIPTEN +# endif #endif #endif diff --git a/src/corelib/kernel/qeventdispatcher_unix.cpp b/src/corelib/kernel/qeventdispatcher_unix.cpp index 58164dba47..60b46a35f5 100644 --- a/src/corelib/kernel/qeventdispatcher_unix.cpp +++ b/src/corelib/kernel/qeventdispatcher_unix.cpp @@ -190,12 +190,15 @@ int QEventDispatcherUNIXPrivate::doSelect(QEventLoop::ProcessEventsFlags flags, int wakeUpFd = initThreadWakeUp(); highest = qMax(highest, wakeUpFd); #endif - +#ifdef Q_OS_NACL_EMSCRIPTEN + nsel = 0; +#else nsel = q->select(highest + 1, &sn_vec[0].select_fds, &sn_vec[1].select_fds, &sn_vec[2].select_fds, timeout); +#endif } while (nsel == -1 && (errno == EINTR || errno == EAGAIN)); if (nsel == -1) { diff --git a/src/corelib/kernel/qfunctions_nacl.cpp b/src/corelib/kernel/qfunctions_nacl.cpp index 5234452581..1c66ea5b23 100644 --- a/src/corelib/kernel/qfunctions_nacl.cpp +++ b/src/corelib/kernel/qfunctions_nacl.cpp @@ -82,7 +82,6 @@ void pthread_testcancel(void) } - int pthread_cancel(pthread_t) { return 0; @@ -140,10 +139,12 @@ int sigaction(int, const struct sigaction *, struct sigaction *) return 0; } +#ifndef Q_OS_NACL_EMSCRIPTEN int open(const char *, int, ...) { return 0; } +#endif int open64(const char *, int, ...) { @@ -155,12 +156,12 @@ long pathconf(const char *, int) return 0; } +#ifndef Q_OS_NACL_EMSCRIPTEN int access(const char *, int) { return 0; } -#ifndef Q_OS_NACL_EMSCRIPTEN typedef long off64_t; off64_t ftello64(void *) { @@ -197,8 +198,6 @@ int unsetenv(const char *name) } #endif -} // Extern C - int select(int, fd_set *, fd_set *, fd_set *, struct timeval *) { return 0; @@ -209,10 +208,9 @@ int pselect(int nfds, fd_set * readfds, fd_set * writefds, fd_set * errorfds, co return 0; } -#ifdef Q_OS_NACL_EMSCRIPTEN - -// pthread stubs (no thrading support in emscripten) +} // Extern C +#if defined(Q_OS_NACL_EMSCRIPTEN) && !defined(__EMSCRIPTEN_PTHREADS__) int pthread_setcancelstate(int state, int *oldstate) { return 0; @@ -332,7 +330,6 @@ int sched_get_priority_min(int policy) { return 0; } - #endif // Several Qt components (such at the QtCore event dispatcher and networking) diff --git a/src/corelib/kernel/qfunctions_nacl.h b/src/corelib/kernel/qfunctions_nacl.h index 34e0efda1d..915f9c4220 100644 --- a/src/corelib/kernel/qfunctions_nacl.h +++ b/src/corelib/kernel/qfunctions_nacl.h @@ -128,11 +128,11 @@ int setenv(const char *name, const char *value, int overwrite) __attribute__((we int unsetenv(const char *name) __attribute__((weak)); #endif -} - int select(int nfds, fd_set * readfds, fd_set * writefds, fd_set * errorfds, struct timeval * timeout) __attribute__((weak)); int pselect(int nfds, fd_set * readfds, fd_set * writefds, fd_set * errorfds, const struct timespec * timeout, const sigset_t * sigmask) __attribute__((weak)); +} + QT_END_NAMESPACE #endif //Q_OS_NACL diff --git a/src/corelib/plugin/qlibrary.cpp b/src/corelib/plugin/qlibrary.cpp index 2df48cff34..0d0a97f82e 100644 --- a/src/corelib/plugin/qlibrary.cpp +++ b/src/corelib/plugin/qlibrary.cpp @@ -712,7 +712,7 @@ void QLibraryPrivate::updatePluginState() } #endif -#if !defined (Q_OS_NACL) +#if !defined (Q_OS_NACL) || defined (Q_OS_NACL_EMSCRIPTEN) if (!pHnd) { // scan for the plugin metadata without loading success = findPatternUnloaded(fileName, this); diff --git a/src/corelib/plugin/qplugin.h b/src/corelib/plugin/qplugin.h index 9b3725a718..9af1629a13 100644 --- a/src/corelib/plugin/qplugin.h +++ b/src/corelib/plugin/qplugin.h @@ -40,7 +40,6 @@ QT_BEGIN_NAMESPACE - #ifndef Q_EXTERN_C # ifdef __cplusplus # define Q_EXTERN_C extern "C" @@ -71,7 +70,20 @@ Q_DECLARE_TYPEINFO(QStaticPlugin, Q_PRIMITIVE_TYPE); void Q_CORE_EXPORT qRegisterStaticPluginFunction(QStaticPlugin staticPlugin); -#ifdef Q_OS_PNACL +#if defined(Q_OS_NACL_EMSCRIPTEN) +// It is important that the metadata is aligned in Emscripten because we are +// not allowed to read unaligned data in JS/Emscripten. +// Without this, importing static plugins will randomly fail because reading +// the offset 'size' value in QLibraryPrivate::fromRawMetaData is undefined behavior. +// For this purpose, aligning to 32 bits would suffice. +// Using 64 bits is probably overkill, but should ensure that this problem doesn't +// surface in other parts of the code. + +// TODO Do we need "section" and "used" attributes on Emscripten? +// TODO Should we reduce alignment to 32 bits? +# define QT_PLUGIN_METADATA_SECTION \ + __attribute__ ((section (".qtmetadata"))) __attribute__((used)) __attribute__((aligned(64))) +#elif defined(Q_OS_PNACL) // PNaCl does not support "section": // "Variable _ZL17qt_pluginMetaData has disallowed "section" attribute" // PNaCl is Q_CC_CLANG. TODO: should it not set Q_OF_ELF? diff --git a/src/corelib/thread/qmutex.cpp b/src/corelib/thread/qmutex.cpp index 14dc72a1f5..6e93e3b0d7 100644 --- a/src/corelib/thread/qmutex.cpp +++ b/src/corelib/thread/qmutex.cpp @@ -271,6 +271,12 @@ bool QMutex::tryLock(int timeout) QT_MUTEX_LOCK_NOEXCEPT */ void QMutex::unlock() Q_DECL_NOTHROW { + // TODO replace this with using pthread stubs instead + // Note: Defining QT_NO_THREAD won't work because too many + // Qt internals (QFuture, QThreadPool, etc.) depend on threads +#if defined(Q_OS_NACL_EMSCRIPTEN) && !defined(Q_OS_NACL_EMSCRIPTEN_PTHREADS) + return; +#endif QMutexData *current; if (fastTryUnlock(current)) return; diff --git a/src/corelib/thread/qmutex_unix.cpp b/src/corelib/thread/qmutex_unix.cpp index 74e0d68f94..abb02d77ae 100644 --- a/src/corelib/thread/qmutex_unix.cpp +++ b/src/corelib/thread/qmutex_unix.cpp @@ -70,6 +70,10 @@ QMutexPrivate::~QMutexPrivate() bool QMutexPrivate::wait(int timeout) { + // TODO Emscripten specialization could perhaps be replaced with pthread stubs +#if defined(Q_OS_NACL_EMSCRIPTEN) && !defined(Q_OS_NACL_EMSCRIPTEN_PTHREADS) + return false; +#endif report_error(pthread_mutex_lock(&mutex), "QMutex::lock", "mutex lock"); int errorCode = 0; while (!wakeup) { diff --git a/src/corelib/thread/qwaitcondition_unix.cpp b/src/corelib/thread/qwaitcondition_unix.cpp index b531707dd2..19c816475e 100644 --- a/src/corelib/thread/qwaitcondition_unix.cpp +++ b/src/corelib/thread/qwaitcondition_unix.cpp @@ -114,6 +114,10 @@ public: int wait_relative(unsigned long time) { + // TODO Emscripten specialization could perhaps be replaced with pthread stubs +#if defined(Q_OS_NACL_EMSCRIPTEN) && !defined(Q_OS_NACL_EMSCRIPTEN_PTHREADS) + return 0; +#endif timespec ti; #ifdef Q_OS_ANDROID if (local_cond_timedwait_relative) { @@ -128,6 +132,10 @@ public: bool wait(unsigned long time) { + // TODO Emscripten specialization could perhaps be replaced with pthread stubs +#if defined(Q_OS_NACL_EMSCRIPTEN) && !defined(Q_OS_NACL_EMSCRIPTEN_PTHREADS) + return true; +#endif int code; forever { if (time != ULONG_MAX) { @@ -194,6 +202,11 @@ void QWaitCondition::wakeAll() bool QWaitCondition::wait(QMutex *mutex, unsigned long time) { + // TODO Emscripten specialization could perhaps be replaced with pthread stubs +#if defined(Q_OS_NACL_EMSCRIPTEN) && !defined(Q_OS_NACL_EMSCRIPTEN_PTHREADS) + return true; +#endif + if (! mutex) return false; if (mutex->isRecursive()) { @@ -214,6 +227,10 @@ bool QWaitCondition::wait(QMutex *mutex, unsigned long time) bool QWaitCondition::wait(QReadWriteLock *readWriteLock, unsigned long time) { + // TODO Emscripten specialization could perhaps be replaced with pthread stubs +#if defined(Q_OS_NACL_EMSCRIPTEN) && !defined(Q_OS_NACL_EMSCRIPTEN_PTHREADS) + return true; +#endif if (!readWriteLock || readWriteLock->d->accessCount == 0) return false; if (readWriteLock->d->accessCount < -1) { diff --git a/src/corelib/tools/qsimd.cpp b/src/corelib/tools/qsimd.cpp index 971d0c0cec..137988ce39 100644 --- a/src/corelib/tools/qsimd.cpp +++ b/src/corelib/tools/qsimd.cpp @@ -640,6 +640,10 @@ int ffsll(quint64 i) # define ffsll __builtin_ffsll #endif +#if defined(Q_OS_NACL_NEWLIB) || defined(Q_OS_NACL_EMSCRIPTEN) +# define ffsll __builtin_ffsll +#endif + #ifdef Q_ATOMIC_INT64_IS_SUPPORTED Q_CORE_EXPORT QBasicAtomicInteger qt_cpu_features[1] = { Q_BASIC_ATOMIC_INITIALIZER(0) }; #else diff --git a/src/gui/opengl/qopenglfunctions.h b/src/gui/opengl/qopenglfunctions.h index ca002642d8..6699b38b39 100644 --- a/src/gui/opengl/qopenglfunctions.h +++ b/src/gui/opengl/qopenglfunctions.h @@ -565,7 +565,7 @@ struct QOpenGLFunctionsPrivate // GLES2 + OpenGL1 common subset -#ifdef Q_OS_NACL +#if defined(Q_OS_NACL) && !defined(Q_OS_NACL_EMSCRIPTEN) #include "qopenglfunctions_nacl.h" #else inline void QOpenGLFunctions::glBindTexture(GLenum target, GLuint texture) diff --git a/src/gui/opengl/qopengltexturehelper.cpp b/src/gui/opengl/qopengltexturehelper.cpp index 1ef0b3ef17..6089a3ed27 100644 --- a/src/gui/opengl/qopengltexturehelper.cpp +++ b/src/gui/opengl/qopengltexturehelper.cpp @@ -167,6 +167,62 @@ QOpenGLTextureHelper::QOpenGLTextureHelper(QOpenGLContext *context) TexSubImage2D = reinterpret_cast(GetProcAddress(handle, QByteArrayLiteral("glTexSubImage2D"))); TexSubImage1D = reinterpret_cast(GetProcAddress(handle, QByteArrayLiteral("glTexSubImage1D"))); +#elif defined(Q_OS_NACL_EMSCRIPTEN) + GetIntegerv = ::glGetIntegerv; + GetBooleanv = ::glGetBooleanv; + PixelStorei = ::glPixelStorei; + GetTexLevelParameteriv = 0; + GetTexLevelParameterfv = 0; + GetTexParameteriv = ::glGetTexParameteriv; + GetTexParameterfv = ::glGetTexParameterfv; + GetTexImage = 0; + TexImage2D = reinterpret_cast(::glTexImage2D); + TexImage1D = 0; + TexParameteriv = ::glTexParameteriv; + TexParameteri = ::glTexParameteri; + TexParameterfv = ::glTexParameterfv; + TexParameterf = ::glTexParameterf; + + // OpenGL 1.1 + GenTextures = ::glGenTextures; + DeleteTextures = ::glDeleteTextures; + BindTexture = ::glBindTexture; + TexSubImage2D = ::glTexSubImage2D; + TexSubImage1D = 0; + + // OpenGL 1.3 + GetCompressedTexImage = 0; + CompressedTexSubImage1D = 0; + CompressedTexSubImage2D = ::glCompressedTexSubImage2D; + CompressedTexImage1D = 0; + CompressedTexImage2D = ::glCompressedTexImage2D; + ActiveTexture = ::glActiveTexture; + + // OpenGL 3.0 + GenerateMipmap = ::glGenerateMipmap; + + // OpenGL 3.2 + TexImage3DMultisample = 0; + TexImage2DMultisample = 0; + + // OpenGL 4.2 + QOpenGLContext *ctx = QOpenGLContext::currentContext(); + if (ctx->format().majorVersion() >= 3) { + // OpenGL ES 3.0+ has immutable storage for 2D and 3D at least. + QOpenGLES3Helper *es3 = static_cast(ctx->functions())->gles3Helper(); + TexStorage3D = es3->TexStorage3D; + TexStorage2D = es3->TexStorage2D; + } else { + TexStorage3D = 0; + TexStorage2D = 0; + } + TexStorage1D = 0; + + // OpenGL 4.3 + TexStorage3DMultisample = 0; + TexStorage2DMultisample = 0; + TexBufferRange = 0; + TextureView = 0; #elif defined(QT_OPENGL_ES_2) // Here we are targeting OpenGL ES 2.0+ only. This is likely using EGL, where, // similarly to WGL, non-extension functions (i.e. any function that is part of the diff --git a/src/plugins/platforms/pepper/3rdparty/pepper.js/audio.js b/src/plugins/platforms/pepper/3rdparty/pepper.js/audio.js index 96b21e99f3..5538088eca 100644 --- a/src/plugins/platforms/pepper/3rdparty/pepper.js/audio.js +++ b/src/plugins/platforms/pepper/3rdparty/pepper.js/audio.js @@ -2,6 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +var ENVIRONMENT_IS_PTHREAD; // is set to true in pthread-main.js if we are in a worker +if(!ENVIRONMENT_IS_PTHREAD) { + (function() { var isAudioSupported = function() { @@ -186,3 +189,5 @@ ], isAudioSupported); })(); + +} diff --git a/src/plugins/platforms/pepper/3rdparty/pepper.js/base.js b/src/plugins/platforms/pepper/3rdparty/pepper.js/base.js index 4da0eb52d0..e8b2049e6a 100644 --- a/src/plugins/platforms/pepper/3rdparty/pepper.js/base.js +++ b/src/plugins/platforms/pepper/3rdparty/pepper.js/base.js @@ -2,6 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +var ENVIRONMENT_IS_PTHREAD; // is set to true in pthread-main.js if we are in a worker +if(!ENVIRONMENT_IS_PTHREAD) { + (function() { var DoLog = function(level, value) { // TODO enum? @@ -111,6 +114,65 @@ Messaging_PostMessage ]); + registerInterface("PPB_Messaging;1.2", [ + Messaging_PostMessage + ]); + + var MessageLoop_InstanceHandle = function(instance) { + // console.warn("MessageLoop_InstanceHandle is not implemented") + console.log("Returning MessageLoop instance") + return 1; + }; + + var MessageLoop_GetForMainThread = function() { + // console.warn("MessageLoop_GetForMainThread is not implemented") + console.log("Returning MessageLoop instance main") + return 1; + }; + + var MessageLoop_GetCurrent = function() { + // console.warn("MessageLoop_GetCurrent is not implemented") + console.log("Returning MessageLoop instance current") + return 1; + }; + + var MessageLoop_Run = function(resource) { + // console.warn("MessageLoop_Run is not implemented " + resource) + console.log("MessageLoop_Run called") + return 1; + }; + + var MessageLoop_AttachToCurrentThread = function(resource) { + // console.warn("MessageLoop_Run is not implemented " + resource) + console.log("Attach!") + return 1; + }; + + var MessageLoop_PostWork = function(resource, callback, delay_ms) { + // console.log("MessageLoop_PostWork received") + var c = glue.getCompletionCallback(callback); + Module.requestAnimationFrame(function() { + // console.log("MessageLoop_PostWork callback being called!") + c(0); + }); + return 0; + }; + + var MessageLoop_PostQuit = function(resource, should_destroy) { + console.warn("MessageLoop_PostQuit is not implemented " + resource) + return 0; + }; + + registerInterface("PPB_MessageLoop;1.0", [ + MessageLoop_InstanceHandle, + MessageLoop_GetForMainThread, + MessageLoop_GetCurrent, + MessageLoop_AttachToCurrentThread, + MessageLoop_Run, + MessageLoop_PostWork, + MessageLoop_PostQuit, + ]); + var Var_AddRef = function(v) { if (glue.isRefCountedVarType(glue.getVarType(v))) { resources.addRef(glue.getVarUID(v)); @@ -407,3 +469,5 @@ ]); })(); + +} diff --git a/src/plugins/platforms/pepper/3rdparty/pepper.js/common.js b/src/plugins/platforms/pepper/3rdparty/pepper.js/common.js new file mode 100644 index 0000000000..caf4f54733 --- /dev/null +++ b/src/plugins/platforms/pepper/3rdparty/pepper.js/common.js @@ -0,0 +1,415 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Javascript module pattern: +// see http://en.wikipedia.org/wiki/Unobtrusive_JavaScript#Namespaces +// In essence, we define an anonymous function which is immediately called and +// returns a new object. The new object contains only the exported definitions; +// all other definitions in the anonymous function are inaccessible to external +// code. +var common = (function () { + + var addListener = function(elt, event_name, callback) { + if (elt.addEventListener) { + elt.addEventListener(event_name, callback, false); + } else { + elt.attachEvent('on' + event_name, callback); + } + }; + + var getImageDataBuffer = function(imageData) { + var buffer = imageData.data.buffer; + // IE support + if(buffer === undefined) { + buffer = new ArrayBuffer(imageData.data.length); + view = new Uint8Array(buffer); + for (var i = 0; i < imageData.data.length; i++) { + view[i] = imageData.data[i]; + } + } + return buffer; + } + + nacl.createInstance = function(config) { + var variant = config.module; + var e; + var width = config.width; + var height = config.height; + var type = variant.type; + if (type == "pnacl") { + e = nacl.createEmbedInstance(variant.url, nacl.pnaclMimeType, width, height); + } else if (type == "emscripten") { + e = nacl.createEmscriptenInstance(variant.url, width, height); + } else if (type == "nacl") { + e = nacl.createEmbedInstance(variant.url, nacl.naclMimeType, width, height); + } else if (type == "host") { + e = nacl.createEmbedInstance("bogusURL", nacl.mimetype, width, height); + } else { + throw new Error("Unknown variant type " + type); + } + if (config.init) { + config.init(e); + } + if (config.progress) { + e.addEventListener('progress', config.progress); + } + if (config.load) { + e.addEventListener('load', config.load); + } + if (config.error) { + e.addEventListener('error', config.error); + } + config.insert.appendChild(e); + e.load(); + return e; + }; + + var loadStart; + + /** + * Create the Native Client element as a child of the DOM element + * named "listener". + * + * @param {string} name The name of the example. + * @param {string} tool The name of the toolchain, e.g. "glibc", "newlib" etc. + * @param {string} path Directory name where .nmf file can be found. + * @param {number} width The width to create the plugin. + * @param {number} height The height to create the plugin. + * @param {Object} optional dictionary of args to send to DidCreateInstance + */ + function createNaClModule(name, tool, path, width, height, args) { + loadStart = new Date(); + + var isRelease = path.toLowerCase().indexOf('release') != -1; + + var progress = document.createElement('progress'); + progress.style.width = '480px'; + + var modules = { + "pnacl": { + type: "pnacl", + url: path + '/' + name + '.nmf', + }, + "nacl": { + type: "nacl", + url: path + '/' + name + '.nmf', + }, + "emscripten": { + type: "emscripten", + url: path + '/' + name + '.js', + }, + "host": { + type: "host", + mimetype: 'application/x-ppapi-' + (isRelease ? 'release' : 'debug'), + } + }; + + var moduleEl = nacl.createInstance({ + module: modules[tool], + width: width, + height: height, + insert: document.getElementById('listener'), + init: function(e) { + e.setAttribute('name', 'nacl_module'); + e.setAttribute('id', 'nacl_module'); + e.setAttribute('path', path); + // Add any optional arguments + if (args) { + for (var key in args) { + e.setAttribute(key, args[key]) + } + } + }, + progress: function(evt) { + var loadPercent = -1.0; + progress.max = 100; + if (evt.lengthComputable && evt.total > 0) { + loadPercent = evt.loaded / evt.total * 100.0; + } + progress.value = loadPercent; + }, + load: function(evt) { + progress.value = 100; + document.getElementById('listener').removeChild(progress); + }, + error: function(evt) { + progress.value = 100; + document.getElementById('listener').removeChild(progress); + }, + }); + + if (tool == 'pnacl' && !nacl.hasPNaCl()) { + updateStatus('PNaCl requires Chrome 31 or newer.'); + } else if (tool == 'nacl' && !nacl.hasNaCl()) { + updateStatus('NaCl requires Chrome.'); + } else { + document.getElementById('listener').appendChild(progress); + } + + // Host plugins don't send a moduleDidLoad message. We'll fake it + // here. + var isHost = tool == 'win' || tool == 'linux' || tool == 'mac' || tool == 'host'; + if (isHost) { + window.setTimeout(function () { + var evt = document.createEvent('Event'); + evt.initEvent('load', true, true); // bubbles, cancelable + moduleEl.dispatchEvent(evt); + }, 100); // 100 ms + } + return moduleEl; + } + + /** + * Add the default "load" and "message" event listeners to the element with + * id "listener". + * + * The "load" event is sent when the module is successfully loaded. The + * "message" event is sent when the naclModule posts a message using + * PPB_Messaging.PostMessage() (in C) or pp::Instance().PostMessage() (in + * C++). + */ + function attachDefaultListeners() { + var listenerDiv = document.getElementById('listener'); + listenerDiv.addEventListener('load', moduleDidLoad, true); + listenerDiv.addEventListener('message', handleMessage, true); + listenerDiv.addEventListener('crash', handleCrash, true); + if (typeof window.attachListeners !== 'undefined') { + window.attachListeners(); + } + } + + + /** + * Called when the Browser can not communicate with the Module + * + * This event listener is registered in attachDefaultListeners above. + */ + function handleCrash(event) { + updateStatus('module crashed') + if (typeof window.handleCrash !== 'undefined') { + window.handleCrash(common.naclModule.lastError); + } + } + + /** + * Called when the NaCl module is loaded. + * + * This event listener is registered in attachDefaultListeners above. + */ + function moduleDidLoad() { + common.naclModule = document.getElementById('nacl_module'); + updateStatus('loaded'); + console.log("Create instance: " + (new Date()-loadStart) + " ms"); + + if (typeof window.moduleDidLoad !== 'undefined') { + window.moduleDidLoad(); + } + } + + /** + * Hide the NaCl module's embed element. + * + * We don't want to hide by default; if we do, it is harder to determine that + * a plugin failed to load. Instead, call this function inside the example's + * "moduleDidLoad" function. + * + */ + function hideModule() { + // Setting common.naclModule.style.display = "None" doesn't work; the + // module will no longer be able to receive postMessages. + common.naclModule.style.height = "0"; + } + + /** + * Return true when |s| starts with the string |prefix|. + * + * @param {string} s The string to search. + * @param {string} prefix The prefix to search for in |s|. + */ + function startsWith(s, prefix) { + // indexOf would search the entire string, lastIndexOf(p, 0) only checks at + // the first index. See: http://stackoverflow.com/a/4579228 + return s.lastIndexOf(prefix, 0) === 0; + } + + /** Maximum length of logMessageArray. */ + var kMaxLogMessageLength = 20; + + /** An array of messages to display in the element with id "log". */ + var logMessageArray = []; + + /** + * Add a message to an element with id "log". + * + * This function is used by the default "log:" message handler. + * + * @param {string} message The message to log. + */ + function logMessage(message) { + logMessageArray.push(message); + if (logMessageArray.length > kMaxLogMessageLength) + logMessageArray.shift(); + + document.getElementById('log').textContent = logMessageArray.join(''); + console.log(message) + } + + /** + */ + var defaultMessageTypes = { + 'alert': alert, + 'log': logMessage + }; + + /** + * Called when the NaCl module sends a message to JavaScript (via + * PPB_Messaging.PostMessage()) + * + * This event listener is registered in createNaClModule above. + * + * @param {Event} message_event A message event. message_event.data contains + * the data sent from the NaCl module. + */ + function handleMessage(message_event) { + if (typeof message_event.data === 'string') { + for (var type in defaultMessageTypes) { + if (defaultMessageTypes.hasOwnProperty(type)) { + if (startsWith(message_event.data, type + ':')) { + func = defaultMessageTypes[type]; + func(message_event.data.slice(type.length + 1)); + return; + } + } + } + } + + if (typeof window.handleMessage !== 'undefined') { + window.handleMessage(message_event); + } + } + + /** + * Called when the DOM content has loaded; i.e. the page's document is fully + * parsed. At this point, we can safely query any elements in the document via + * document.querySelector, document.getElementById, etc. + * + * @param {string} name The name of the example. + * @param {string} tool The name of the toolchain, e.g. "glibc", "newlib" etc. + * @param {string} path Directory name where .nmf file can be found. + * @param {number} width The width to create the plugin. + * @param {number} height The height to create the plugin. + */ + function domContentLoaded(name, tool, path, width, height) { + // If the page loads before the Native Client module loads, then set the + // status message indicating that the module is still loading. Otherwise, + // do not change the status message. + updateStatus('page loaded'); + if (common.naclModule == null) { + updateStatus('creating ' + tool + ' embed') + + // We use a non-zero sized embed to give Chrome space to place the bad + // plug-in graphic, if there is a problem. + width = typeof width !== 'undefined' ? width : 200; + height = typeof height !== 'undefined' ? height : 200; + attachDefaultListeners(); + createNaClModule(name, tool, path, width, height); + } else { + // It's possible that the Native Client module onload event fired + // before the page's onload event. In this case, the status message + // will reflect 'SUCCESS', but won't be displayed. This call will + // display the current message. + updateStatus('waiting'); + } + } + + /** Saved text to display in the element with id 'statusField'. */ + var statusText = 'NO-STATUSES'; + + /** + * Set the global status message. If the element with id 'statusField' + * exists, then set its HTML to the status message as well. + * + * @param {string} opt_message The message to set. If null or undefined, then + * set element 'statusField' to the message from the last call to + * updateStatus. + */ + function updateStatus(opt_message) { + if (opt_message) { + statusText = opt_message; + } + var statusField = document.getElementById('statusField'); + if (statusField) { + statusField.innerHTML = statusText; + } + } + + // The symbols to export. + return { + /** A reference to the NaCl module, once it is loaded. */ + naclModule: null, + + addListener: addListener, + getImageDataBuffer: getImageDataBuffer, + attachDefaultListeners: attachDefaultListeners, + domContentLoaded: domContentLoaded, + createNaClModule: createNaClModule, + hideModule: hideModule, + logMessage: logMessage, + updateStatus: updateStatus + }; + +}()); + +// Listen for the DOM content to be loaded. This event is fired when parsing of +// the page's document has finished. +//common.addListener(document, 'DOMContentLoaded', function() { +window.onload = function() { + var body = document.querySelector('body'); + + var loadFunction = common.domContentLoaded; + // The data-* attributes on the body can be referenced via body.dataset. + if (body.dataset && body.dataset.customLoad && typeof window.domContentLoaded !== 'undefined') { + loadFunction = window.domContentLoaded; + } + + // From https://developer.mozilla.org/en-US/docs/DOM/window.location + var searchVars = {}; + if (window.location.search.length > 1) { + var pairs = window.location.search.substr(1).split("&"); + for (var key_ix = 0; key_ix < pairs.length; key_ix++) { + var keyValue = pairs[key_ix].split("="); + searchVars[unescape(keyValue[0])] = + keyValue.length > 1 ? unescape(keyValue[1]) : ""; + } + } + if (loadFunction) { + var name = body.getAttribute("data-name"); + var tc = body.getAttribute("data-tc"); + var path = body.getAttribute("data-path"); + var width = body.getAttribute("data-width") || undefined; + var height = body.getAttribute("data-height") || undefined; + + var toolchains = (body.getAttribute("data-tools") || tc || "emscripten newlib pnacl").split(' '); + var configs = (body.getAttribute("data-configs") || "Debug Release").split(' '); + + var tc = toolchains.indexOf(searchVars.tc) !== -1 ? + searchVars.tc : toolchains[0]; + var config = configs.indexOf(searchVars.config) !== -1 ? + searchVars.config : configs[0]; + path = path.replace('{tc}', tc).replace('{config}', config); + + // The SDK uses the pnacl toolchain to compile nexes in Debug mode. + if (tc == 'pnacl' && config == 'Debug') { + tc = 'nacl'; + } + if (tc == 'newlib') { + tc = 'nacl'; + } + if (tc == 'win' || tc == 'linux' || tc == 'mac') { + tc = 'host'; + } + loadFunction(name, tc, path, width, height); + } +}; +//}); diff --git a/src/plugins/platforms/pepper/3rdparty/pepper.js/file.js b/src/plugins/platforms/pepper/3rdparty/pepper.js/file.js index ceb66652ac..c9faa1a5f4 100644 --- a/src/plugins/platforms/pepper/3rdparty/pepper.js/file.js +++ b/src/plugins/platforms/pepper/3rdparty/pepper.js/file.js @@ -2,6 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +var ENVIRONMENT_IS_PTHREAD; // is set to true in pthread-main.js if we are in a worker +if(!ENVIRONMENT_IS_PTHREAD) { + (function() { var PP_FILESYSTEMTYPE_INVALID = 0; @@ -381,3 +384,5 @@ ]); })(); + +} diff --git a/src/plugins/platforms/pepper/3rdparty/pepper.js/gles.js b/src/plugins/platforms/pepper/3rdparty/pepper.js/gles.js index 8ae4deeb5e..f675c10195 100644 --- a/src/plugins/platforms/pepper/3rdparty/pepper.js/gles.js +++ b/src/plugins/platforms/pepper/3rdparty/pepper.js/gles.js @@ -2,6 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +var ENVIRONMENT_IS_PTHREAD; // is set to true in pthread-main.js if we are in a worker +if(!ENVIRONMENT_IS_PTHREAD) { + (function() { // (GLenum) => void @@ -53,6 +56,10 @@ if (_context === undefined) { return; } + if(buffer == 0) { + // TODO buffer = 0 should release previously bound buffers + return; + } var _buffer = resources.resolve(buffer, BUFFER_RESOURCE); if (_buffer === undefined) { return; @@ -67,6 +74,12 @@ if (_context === undefined) { return; } + if(framebuffer == 0) { + // framebuffer = 0 is the default framebuffer provided by the system + // and is translated to null in WebGL + _context.ctx.bindFramebuffer(target, null); + return; + } var _framebuffer = coerceFramebuffer(framebuffer); _context.ctx.bindFramebuffer(target, _framebuffer); } @@ -561,7 +574,48 @@ } var OpenGLES2_GetProgramiv = function(context, program, pname, params) { - throw "OpenGLES2_GetProgramiv not implemented"; + if(pname == 35716 || pname == 35720) { + // 35716 = GL_INFO_LOG_LENGTH (0x8B84) + // 35720 = GL_SHADER_SOURCE_LENGTH (0x8B88) + // These are not allowed in WebGL, but are allowed in GLES. + // Return 0 so that legacy code thinks there is no log or source to print + var result = 0 + setValue(params, result, 'i32'); + return + } + var _context = resources.resolve(context, GRAPHICS_3D_RESOURCE); + if (_context === undefined) { + return 0; + } + var _program = resources.resolve(program, PROGRAM_RESOURCE); + if (_program === undefined) { + return 0; + } + var result = _context.ctx.getProgramParameter(_program.native, pname); + switch(pname) { + case _context.ctx.DELETE_STATUS: + setValue(params, result, 'i8'); + break; + case _context.ctx.LINK_STATUS: + setValue(params, result, 'i8'); + break; + case _context.ctx.VALIDATE_STATUS: + setValue(params, result, 'i8'); + break; + case _context.ctx.ATTACHED_SHADERS: + setValue(params, result, 'i32'); + break; + case _context.ctx.ACTIVE_ATTRIBUTES: + setValue(params, result, 'i32'); + break; + case _context.ctx.ACTIVE_UNIFORMS: + setValue(params, result, 'i32'); + break; + default: + console.warn("OpenGLES2_GetProgramiv unknown parameter type, assume i32") + setValue(params, result, 'i32'); + break; + } } var OpenGLES2_GetProgramInfoLog = function(context, program, bufsize, length, infolog) { @@ -573,7 +627,16 @@ } var OpenGLES2_GetShaderiv = function(context, shader, pname, params) { - throw "OpenGLES2_GetShaderiv not implemented"; + var _context = resources.resolve(context, GRAPHICS_3D_RESOURCE); + if (_context === undefined) { + return 0; + } + var _shader = resources.resolve(shader, SHADER_RESOURCE); + if (_shader === undefined) { + return 0; + } + var result = _context.ctx.getShaderParameter(_shader.native, pname); + setValue(params, result, 'i32'); } var OpenGLES2_GetShaderInfoLog = function(context, shader, bufsize, length, infolog) { @@ -1091,11 +1154,21 @@ return; } var _value = HEAPF32.subarray((value>>2), (value>>2) + 16 * count); + // TODO: This is temporary to cast SharedFloat32Array to a Float32Array. Remove this once https://bugzilla.mozilla.org/show_bug.cgi?id=1205390 lands. + _value = new Float32Array(_value); _context.ctx.uniformMatrix4fv(_location.native, transpose, _value); } // ppapi (GLuint) => void // webgl (WebGLProgram) => void var OpenGLES2_UseProgram = function(context, program) { + if(program === 0) { + // TODO Is useprogram(0) okay to call? + // OpenGLES2_UseProgram: Requested to use program 0. " + // This is not a defined operation in WebGL, but in legacy + // code it is a request to release the program. + // Here, nothing will be done when calling glUseProgram(0). + return + } var _context = resources.resolve(context, GRAPHICS_3D_RESOURCE); if (_context === undefined) { return; @@ -1386,3 +1459,5 @@ // UniformMatrix2fv: Cannot deal with overloads // UniformMatrix3fv: Cannot deal with overloads // 94:48 + +} diff --git a/src/plugins/platforms/pepper/3rdparty/pepper.js/gles_ext.js b/src/plugins/platforms/pepper/3rdparty/pepper.js/gles_ext.js index 9dfc7f4bf3..f35b6b038d 100644 --- a/src/plugins/platforms/pepper/3rdparty/pepper.js/gles_ext.js +++ b/src/plugins/platforms/pepper/3rdparty/pepper.js/gles_ext.js @@ -2,6 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +var ENVIRONMENT_IS_PTHREAD; // is set to true in pthread-main.js if we are in a worker +if(!ENVIRONMENT_IS_PTHREAD) { + (function() { // PPB_OpenGLES2InstancedArrays @@ -212,5 +215,30 @@ OpenGLES2Query_GetQueryivEXT, OpenGLES2Query_GetQueryObjectuivEXT, ]); + + var OpenGLES2VertexArrayObject_BindVertexArrayOES = function(context, x, y, width, height) { + throw "OpenGLES2_BindVertexArrayOES is not implemented" + } + var OpenGLES2VertexArrayObject_DeleteVertexArrayOES = function(context, x, y, width, height) { + throw "OpenGLES2_BindVertexArrayOES is not implemented" + } + var OpenGLES2VertexArrayObject_GenVertexArrayOES = function(context, x, y, width, height) { + throw "OpenGLES2_BindVertexArrayOES is not implemented" + } + var OpenGLES2VertexArrayObject_IsVertexArrayOES = function(context, x, y, width, height) { + throw "OpenGLES2_BindVertexArrayOES is not implemented" + } + + registerInterface("PPB_OpenGLES2VertexArrayObject;1.0", [ + OpenGLES2VertexArrayObject_BindVertexArrayOES, + OpenGLES2VertexArrayObject_DeleteVertexArrayOES, + OpenGLES2VertexArrayObject_GenVertexArrayOES, + OpenGLES2VertexArrayObject_IsVertexArrayOES + ]); + + registerInterface("PPB_OpenGLES2DrawBuffers(Dev);1.0", [ + ]); })(); + +} diff --git a/src/plugins/platforms/pepper/3rdparty/pepper.js/graphics_2d.js b/src/plugins/platforms/pepper/3rdparty/pepper.js/graphics_2d.js index e3d5918e04..e619eb2444 100644 --- a/src/plugins/platforms/pepper/3rdparty/pepper.js/graphics_2d.js +++ b/src/plugins/platforms/pepper/3rdparty/pepper.js/graphics_2d.js @@ -2,6 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +var ENVIRONMENT_IS_PTHREAD; // is set to true in pthread-main.js if we are in a worker +if(!ENVIRONMENT_IS_PTHREAD) { + (function() { var Graphics2D_Create = function(instance, size_ptr, is_always_opaque) { @@ -386,3 +389,5 @@ ImageData_Unmap ]); })(); + +} diff --git a/src/plugins/platforms/pepper/3rdparty/pepper.js/graphics_3d.js b/src/plugins/platforms/pepper/3rdparty/pepper.js/graphics_3d.js index 42e62d809d..ffc4c376d4 100644 --- a/src/plugins/platforms/pepper/3rdparty/pepper.js/graphics_3d.js +++ b/src/plugins/platforms/pepper/3rdparty/pepper.js/graphics_3d.js @@ -2,9 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +var ENVIRONMENT_IS_PTHREAD; // is set to true in pthread-main.js if we are in a worker +if(!ENVIRONMENT_IS_PTHREAD) { + (function() { var getContext = function(c, params) { + // TODO we bypass this with Browser.createContext, except for in the test return c.getContext('webgl', params) || c.getContext("experimental-webgl", params); }; @@ -94,7 +98,7 @@ return resources.register(GRAPHICS_3D_RESOURCE, { canvas: canvas, bound: false, - ctx: getContext(canvas, { + ctx: Browser.createContext(canvas, true, true, { "alpha": alpha_size > 0, "depth": depth_size > 0, "stencil": stencil_size > 0, @@ -143,8 +147,10 @@ var Graphics3D_SwapBuffers = function(context, callback) { // TODO double buffering. + // console.log("Graphics3D_SwapBuffers request received") var c = glue.getCompletionCallback(callback); Module.requestAnimationFrame(function() { + // console.log("Graphics3D_SwapBuffers calling back!") c(0); }); }; @@ -162,3 +168,5 @@ return !!getContext(document.createElement("canvas")); }); })(); + +} diff --git a/src/plugins/platforms/pepper/3rdparty/pepper.js/input_events.js b/src/plugins/platforms/pepper/3rdparty/pepper.js/input_events.js index 274212aa1f..1ce29bba3c 100644 --- a/src/plugins/platforms/pepper/3rdparty/pepper.js/input_events.js +++ b/src/plugins/platforms/pepper/3rdparty/pepper.js/input_events.js @@ -2,6 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +var ENVIRONMENT_IS_PTHREAD; // is set to true in pthread-main.js if we are in a worker +if(!ENVIRONMENT_IS_PTHREAD) { + (function() { //Enums copied from ppb_input_event.h @@ -191,7 +194,8 @@ movement: GetMovement(event), delta: GetWheelScroll(event), scrollByPage: event.deltaMode === 2, - keyCode: event.keyCode + keyCode: event.keyCode, + charCode: event.charCode }); var rval = _HandleInputEvent(instance, obj_uid); @@ -426,16 +430,33 @@ return res.keyCode; }; + var KeyboardInputEvent_GetCode = function(event) { + throw "KeyboardInputEvent_GetCode not implemented"; + }; + var KeyboardInputEvent_GetCharacterText = function(ptr, event) { - // TODO(grosse): Find way to implement this - glue.jsToMemoryVar(undefined, ptr); + var res = resources.resolve(event, INPUT_EVENT_RESOURCE); + if (res === undefined) { + return 0; + } + glue.jsToMemoryVar(String.fromCharCode(res.charCode), ptr); }; - registerInterface("PPB_KeyboardInputEvent;1.0", [ - KeyboardInputEvent_Create, - KeyboardInputEvent_IsKeyboardInputEvent, - KeyboardInputEvent_GetKeyCode, - KeyboardInputEvent_GetCharacterText - ]); + registerInterface("PPB_KeyboardInputEvent;1.0", [ + KeyboardInputEvent_Create, + KeyboardInputEvent_IsKeyboardInputEvent, + KeyboardInputEvent_GetKeyCode, + KeyboardInputEvent_GetCharacterText + ]); + + registerInterface("PPB_KeyboardInputEvent;1.2", [ + KeyboardInputEvent_Create, + KeyboardInputEvent_IsKeyboardInputEvent, + KeyboardInputEvent_GetKeyCode, + KeyboardInputEvent_GetCharacterText, + KeyboardInputEvent_GetCode, + ]); })(); + +} diff --git a/src/plugins/platforms/pepper/3rdparty/pepper.js/mouse_lock.js b/src/plugins/platforms/pepper/3rdparty/pepper.js/mouse_lock.js index fc25df1cbf..09442b8bef 100644 --- a/src/plugins/platforms/pepper/3rdparty/pepper.js/mouse_lock.js +++ b/src/plugins/platforms/pepper/3rdparty/pepper.js/mouse_lock.js @@ -2,6 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +var ENVIRONMENT_IS_PTHREAD; // is set to true in pthread-main.js if we are in a worker +if(!ENVIRONMENT_IS_PTHREAD) { + (function() { var MouseLock_LockMouse = function(instance, callback) { @@ -102,3 +105,5 @@ }); })(); + +} diff --git a/src/plugins/platforms/pepper/3rdparty/pepper.js/ppapi_preamble.js b/src/plugins/platforms/pepper/3rdparty/pepper.js/ppapi_preamble.js index 910eb70b30..ea856dfe41 100644 --- a/src/plugins/platforms/pepper/3rdparty/pepper.js/ppapi_preamble.js +++ b/src/plugins/platforms/pepper/3rdparty/pepper.js/ppapi_preamble.js @@ -5,6 +5,13 @@ // TODO(ncbray): re-enable once Emscripten stops including code with octal values. //"use strict"; +var doCreateInstance = doCreateInstance || function () { + console.log("Please call QtLoader.load() instead of loading your application script.") +} + +var ENVIRONMENT_IS_PTHREAD; // is set to true in pthread-main.js if we are in a worker +if(!ENVIRONMENT_IS_PTHREAD) { + var clamp = function(value, min, max) { if (value < min) { return min; @@ -96,6 +103,8 @@ var ARRAY_RESOURCE = 21; var DICTIONARY_RESOURCE = 22; var WEB_SOCKET_RESOURCE = 23; +var MESSAGE_LOOP_RESOURCE = 24; + var ResourceManager = function() { this.lut = {}; this.uid = 1; @@ -296,10 +305,10 @@ var createInterface = function(name, functions) { interfaces[name] = ptr; }; -var Module = { - "noInitialRun": true, - "noExitRuntime": true, - "preInit": function() { +var Module = Module || {}; +Module["noInitialRun"] = true; +Module["noExitRuntime"] = true; +Module["onRuntimeInitialized"] = function() { for (var i = 0; i < declaredInterfaces.length; i++) { var inf = declaredInterfaces[i]; if (inf.supported === undefined || inf.supported()) { @@ -309,7 +318,7 @@ var Module = { } } declaredInterfaces = []; - } + doCreateInstance(); }; var CreateInstance = function(width, height, shadow_instance) { @@ -983,3 +992,5 @@ var _GetBrowserInterface = function(interface_name) { } return inf; }; + +} diff --git a/src/plugins/platforms/pepper/3rdparty/pepper.js/testing.js b/src/plugins/platforms/pepper/3rdparty/pepper.js/testing.js index 79b4fc08c7..21ef601a5f 100644 --- a/src/plugins/platforms/pepper/3rdparty/pepper.js/testing.js +++ b/src/plugins/platforms/pepper/3rdparty/pepper.js/testing.js @@ -2,6 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +var ENVIRONMENT_IS_PTHREAD; // is set to true in pthread-main.js if we are in a worker +if(!ENVIRONMENT_IS_PTHREAD) { + (function() { var Testing_Dev_ReadImageData = function(device_context_2d, image, top_left) { @@ -53,3 +56,5 @@ Testing_Dev_SetMinimumArrayBufferSizeForShmem, ]); })(); + +} diff --git a/src/plugins/platforms/pepper/3rdparty/pepper.js/url_loader.js b/src/plugins/platforms/pepper/3rdparty/pepper.js/url_loader.js index af40696cc8..58f532c054 100644 --- a/src/plugins/platforms/pepper/3rdparty/pepper.js/url_loader.js +++ b/src/plugins/platforms/pepper/3rdparty/pepper.js/url_loader.js @@ -2,6 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +var ENVIRONMENT_IS_PTHREAD; // is set to true in pthread-main.js if we are in a worker +if(!ENVIRONMENT_IS_PTHREAD) { + (function() { // Canonicalize the URL using the DOM. @@ -369,3 +372,5 @@ ]); })(); + +} diff --git a/src/plugins/platforms/pepper/3rdparty/pepper.js/view.js b/src/plugins/platforms/pepper/3rdparty/pepper.js/view.js index 423539fc6b..8ceec3a321 100644 --- a/src/plugins/platforms/pepper/3rdparty/pepper.js/view.js +++ b/src/plugins/platforms/pepper/3rdparty/pepper.js/view.js @@ -2,6 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +var ENVIRONMENT_IS_PTHREAD; // is set to true in pthread-main.js if we are in a worker +if(!ENVIRONMENT_IS_PTHREAD) { + (function() { var View_IsView = function(resource) { return resources.is(resource, VIEW_RESOURCE); @@ -88,4 +91,17 @@ View_GetDeviceScale, View_GetCSSScale, ]); + + registerInterface("PPB_View;1.2", [ + View_IsView, + View_GetRect, + View_IsFullscreen, + View_IsVisible, + View_IsPageVisible, + View_GetClipRect, + View_GetDeviceScale, + View_GetCSSScale, + ]); })(); + +} diff --git a/src/plugins/platforms/pepper/3rdparty/pepper.js/web_socket.js b/src/plugins/platforms/pepper/3rdparty/pepper.js/web_socket.js index 732efd9f88..8eccb30e5b 100644 --- a/src/plugins/platforms/pepper/3rdparty/pepper.js/web_socket.js +++ b/src/plugins/platforms/pepper/3rdparty/pepper.js/web_socket.js @@ -2,6 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +var ENVIRONMENT_IS_PTHREAD; // is set to true in pthread-main.js if we are in a worker +if(!ENVIRONMENT_IS_PTHREAD) { + (function() { /* @@ -322,3 +325,5 @@ http://creativecommons.org/publicdomain/zero/1.0/legalcode ]); })(); + +} diff --git a/src/plugins/platforms/pepper/pepper.js.pri b/src/plugins/platforms/pepper/pepper.js.pri index 0b3a557f81..43472e3a76 100644 --- a/src/plugins/platforms/pepper/pepper.js.pri +++ b/src/plugins/platforms/pepper/pepper.js.pri @@ -2,8 +2,12 @@ PPAPI_CPP_SOURCE= $$(NACL_SDK_ROOT)/src/ppapi_cpp SOURCES += \ $${PPAPI_CPP_SOURCE}/array_output.cc \ - $${PPAPI_CPP_SOURCE}/audio.cc \ + $${PPAPI_CPP_SOURCE}/audio_buffer.cc \ $${PPAPI_CPP_SOURCE}/audio_config.cc \ + $${PPAPI_CPP_SOURCE}/audio_encoder.cc \ + $${PPAPI_CPP_SOURCE}/audio.cc \ + $${PPAPI_CPP_SOURCE}/compositor_layer.cc \ + $${PPAPI_CPP_SOURCE}/compositor.cc \ $${PPAPI_CPP_SOURCE}/core.cc \ $${PPAPI_CPP_SOURCE}/cursor_control_dev.cc \ $${PPAPI_CPP_SOURCE}/directory_entry.cc \ @@ -14,14 +18,16 @@ SOURCES += \ $${PPAPI_CPP_SOURCE}/font_dev.cc \ $${PPAPI_CPP_SOURCE}/fullscreen.cc \ $${PPAPI_CPP_SOURCE}/graphics_2d.cc \ - $${PPAPI_CPP_SOURCE}/graphics_3d.cc \ $${PPAPI_CPP_SOURCE}/graphics_3d_client.cc \ + $${PPAPI_CPP_SOURCE}/graphics_3d.cc \ $${PPAPI_CPP_SOURCE}/host_resolver.cc \ $${PPAPI_CPP_SOURCE}/image_data.cc \ $${PPAPI_CPP_SOURCE}/input_event.cc \ - $${PPAPI_CPP_SOURCE}/instance.cc \ $${PPAPI_CPP_SOURCE}/instance_handle.cc \ + $${PPAPI_CPP_SOURCE}/instance.cc \ $${PPAPI_CPP_SOURCE}/lock.cc \ + $${PPAPI_CPP_SOURCE}/media_stream_audio_track.cc \ + $${PPAPI_CPP_SOURCE}/media_stream_video_track.cc \ $${PPAPI_CPP_SOURCE}/memory_dev.cc \ $${PPAPI_CPP_SOURCE}/message_loop.cc \ $${PPAPI_CPP_SOURCE}/module.cc \ @@ -38,7 +44,6 @@ SOURCES += \ $${PPAPI_CPP_SOURCE}/rect.cc \ $${PPAPI_CPP_SOURCE}/resource.cc \ $${PPAPI_CPP_SOURCE}/scriptable_object_deprecated.cc \ - $${PPAPI_CPP_SOURCE}/selection_dev.cc \ $${PPAPI_CPP_SOURCE}/simple_thread.cc \ $${PPAPI_CPP_SOURCE}/tcp_socket.cc \ $${PPAPI_CPP_SOURCE}/text_input_controller.cc \ @@ -47,17 +52,18 @@ SOURCES += \ $${PPAPI_CPP_SOURCE}/url_loader.cc \ $${PPAPI_CPP_SOURCE}/url_request_info.cc \ $${PPAPI_CPP_SOURCE}/url_response_info.cc \ - $${PPAPI_CPP_SOURCE}/var.cc \ - $${PPAPI_CPP_SOURCE}/var_array.cc \ $${PPAPI_CPP_SOURCE}/var_array_buffer.cc \ + $${PPAPI_CPP_SOURCE}/var_array.cc \ $${PPAPI_CPP_SOURCE}/var_dictionary.cc \ - $${PPAPI_CPP_SOURCE}/view.cc \ + $${PPAPI_CPP_SOURCE}/var.cc \ + $${PPAPI_CPP_SOURCE}/video_decoder.cc \ + $${PPAPI_CPP_SOURCE}/video_encoder.cc \ + $${PPAPI_CPP_SOURCE}/video_frame.cc \ $${PPAPI_CPP_SOURCE}/view_dev.cc \ - $${PPAPI_CPP_SOURCE}/websocket.cc \ + $${PPAPI_CPP_SOURCE}/view.cc \ $${PPAPI_CPP_SOURCE}/websocket_api.cc \ - $${PPAPI_CPP_SOURCE}/zoom_dev.cc \ - $${PPAPI_CPP_SOURCE}/media_stream_video_track.cc \ - $${PPAPI_CPP_SOURCE}/video_frame.cc \ + $${PPAPI_CPP_SOURCE}/websocket.cc + # libppapi (stub) SOURCES += \ @@ -65,8 +71,32 @@ SOURCES += \ # rest of libppapi is implemented in JavasScript and added to the build # with '--pre-js' at link time. +!emscripten { +# Emscripten provides a better GLES2 API directly than pepper.js +# TODO Consider adding back this when pepper.js has better GLES2 support # OpenGL PPAPI_GLES_SOURCE= $$(NACL_SDK_ROOT)/src/ppapi_gles2 SOURCES +=\ $${PPAPI_GLES_SOURCE}/gles2.c \ $${PPAPI_GLES_SOURCE}/gl2ext_ppapi.c \ + +} + +OTHER_FILES += \ + $$PWD/3rdparty/pepper.js/audio.js \ + $$PWD/3rdparty/pepper.js/base.js \ + $$PWD/3rdparty/pepper.js/common.js \ + $$PWD/3rdparty/pepper.js/file.js \ + $$PWD/3rdparty/pepper.js/gles.js \ + $$PWD/3rdparty/pepper.js/gles_ext.js \ + $$PWD/3rdparty/pepper.js/graphics_2d.js \ + $$PWD/3rdparty/pepper.js/graphics_3d.js \ + $$PWD/3rdparty/pepper.js/input_events.js \ + $$PWD/3rdparty/pepper.js/loadnacl.js \ + $$PWD/3rdparty/pepper.js/mouse_lock.js \ + $$PWD/3rdparty/pepper.js/ppapi_preamble.js \ + $$PWD/3rdparty/pepper.js/testing.js \ + $$PWD/3rdparty/pepper.js/url_loader.js \ + $$PWD/3rdparty/pepper.js/view.js \ + $$PWD/3rdparty/pepper.js/web_socket.js \ + $$PWD/3rdparty/pepper.js/LICENSE diff --git a/src/plugins/platforms/pepper/qpeppereventdispatcher.cpp b/src/plugins/platforms/pepper/qpeppereventdispatcher.cpp index c5549c75f7..7af6b2d161 100644 --- a/src/plugins/platforms/pepper/qpeppereventdispatcher.cpp +++ b/src/plugins/platforms/pepper/qpeppereventdispatcher.cpp @@ -45,6 +45,7 @@ QPepperEventDispatcher::QPepperEventDispatcher(QObject *parent) , m_currentTimerSerial(0) , m_messageLoop(pp::MessageLoop::GetCurrent()) , m_completionCallbackFactory(this) + , m_hasPendingProcessEvents(false) { qCDebug(QT_PLATFORM_PEPPER_EVENTDISPATHCER) << "QPepperEventDispatcher()"; } @@ -54,9 +55,25 @@ QPepperEventDispatcher::~QPepperEventDispatcher() {} bool QPepperEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags) { bool processed = false; +#ifdef Q_OS_NACL_EMSCRIPTEN + // We need to give the control back to the browser due to lack of PTHREADS + // Limit the number of events that may be processed at the time + // TODO: Set maxProcessedEvents to the actual number of pending events, the real issue is that events may spawn new events + int maxProcessedEvents = 2; + int processedCount = 0; + do { + processed = QUnixEventDispatcherQPA::processEvents(flags); + processedCount += 1; + } while (processed && hasPendingEvents() && processedCount < maxProcessedEvents); + // Schedule a new processing loop if we still have events pending + if (hasPendingEvents()) { + scheduleProcessEvents(); + } +#else do { processed = QUnixEventDispatcherQPA::processEvents(flags); } while (processed && hasPendingEvents()); +#endif return true; } @@ -193,19 +210,23 @@ void QPepperEventDispatcher::timerCallback(int32_t result, int32_t timerSerial) void QPepperEventDispatcher::scheduleProcessEvents() { - qCDebug(QT_PLATFORM_PEPPER_EVENTDISPATHCER) << "scheduleProcessEvents"; - pp::CompletionCallback processEvents - = m_completionCallbackFactory.NewCallback(&QPepperEventDispatcher::processEventsCallback); - int32_t result = m_messageLoop.PostWork(processEvents); - if (result != PP_OK) - qCDebug(QT_PLATFORM_PEPPER_EVENTDISPATHCER) << "scheduleProcessEvents PostWork error" - << result; + qCDebug(QT_PLATFORM_PEPPER_EVENTDISPATHCER) << "scheduleProcessEvents" << m_hasPendingProcessEvents; + if (!m_hasPendingProcessEvents) { + m_hasPendingProcessEvents = true; + pp::CompletionCallback processEvents + = m_completionCallbackFactory.NewCallback(&QPepperEventDispatcher::processEventsCallback); + int32_t result = m_messageLoop.PostWork(processEvents); + if (result != PP_OK) + qCDebug(QT_PLATFORM_PEPPER_EVENTDISPATHCER) << "scheduleProcessEvents PostWork error" + << result; + } } void QPepperEventDispatcher::processEventsCallback(int32_t status) { Q_UNUSED(status); qCDebug(QT_PLATFORM_PEPPER_EVENTDISPATHCER) << "processEvents"; + m_hasPendingProcessEvents = false; processEvents(); } diff --git a/src/plugins/platforms/pepper/qpeppereventdispatcher.h b/src/plugins/platforms/pepper/qpeppereventdispatcher.h index 935f8ac653..efcb458b11 100644 --- a/src/plugins/platforms/pepper/qpeppereventdispatcher.h +++ b/src/plugins/platforms/pepper/qpeppereventdispatcher.h @@ -94,6 +94,7 @@ private: QHash m_timerDetails; pp::MessageLoop m_messageLoop; pp::CompletionCallbackFactory m_completionCallbackFactory; + bool m_hasPendingProcessEvents; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/pepper/qpepperfontdatabase.cpp b/src/plugins/platforms/pepper/qpepperfontdatabase.cpp index e542939587..5b816b8059 100644 --- a/src/plugins/platforms/pepper/qpepperfontdatabase.cpp +++ b/src/plugins/platforms/pepper/qpepperfontdatabase.cpp @@ -49,6 +49,8 @@ void QPepperFontDatabase::populateFontDatabase() registerFont("Arial", "", QFont::Normal, QFont::StyleNormal, QFont::Unstretched, true, true, 12, writingSystems, 0); #else + Q_INIT_RESOURCE(naclfonts); + // Load font file from resources. Currently // all fonts needs to be bundled with the nexe // as Qt resources. diff --git a/src/plugins/platforms/pepper/qpepperglcontext.cpp b/src/plugins/platforms/pepper/qpepperglcontext.cpp index 7587062c05..da7cc315fd 100644 --- a/src/plugins/platforms/pepper/qpepperglcontext.cpp +++ b/src/plugins/platforms/pepper/qpepperglcontext.cpp @@ -44,7 +44,12 @@ #include #include + +// Emscriptens GLES2 API is more complete than pepper.js +#ifndef Q_OS_NACL_EMSCRIPTEN #include +#endif + #include #include @@ -109,15 +114,18 @@ bool QPepperGLContext::makeCurrent(QPlatformSurface *surface) } m_currentSize = newSize; } - +#ifndef Q_OS_NACL_EMSCRIPTEN glSetCurrentContextPPAPI(m_context.pp_resource()); +#endif return true; } void QPepperGLContext::doneCurrent() { qCDebug(QT_PLATFORM_PEPPER_GLCONTEXT) << "doneCurrent"; +#ifndef Q_OS_NACL_EMSCRIPTEN glSetCurrentContextPPAPI(0); +#endif } QFunctionPointer QPepperGLContext::getProcAddress(const QByteArray &procName) @@ -144,10 +152,12 @@ void QPepperGLContext::flushCallback(int32_t) bool QPepperGLContext::initGl() { qCDebug(QT_PLATFORM_PEPPER_GLCONTEXT) << "initGl"; +#ifndef Q_OS_NACL_EMSCRIPTEN if (!glInitializePPAPI(pp::Module::Get()->get_browser_interface())) { qWarning("Unable to initialize GL PPAPI!\n"); return false; } +#endif m_currentSize = QPepperInstancePrivate::get()->geometry().size(); QSurfaceFormat f = format(); @@ -165,7 +175,9 @@ bool QPepperGLContext::initGl() if (!instance->BindGraphics(m_context)) { qWarning("Unable to bind 3d context!\n"); m_context = pp::Graphics3D(); +#ifndef Q_OS_NACL_EMSCRIPTEN glSetCurrentContextPPAPI(0); +#endif return false; } diff --git a/src/plugins/platforms/pepper/qpepperpluginmain.cpp b/src/plugins/platforms/pepper/qpepperpluginmain.cpp index 598401e57f..dfc7545626 100644 --- a/src/plugins/platforms/pepper/qpepperpluginmain.cpp +++ b/src/plugins/platforms/pepper/qpepperpluginmain.cpp @@ -33,40 +33,43 @@ ** ****************************************************************************/ -#include "qpepperintegration.h" +// TODO: Check if this is needed. Removed because it caused duplicate +// symbol definition of qt_plugin_query_metadata for everything linking QtGui -#include -#include - -QT_BEGIN_NAMESPACE - -class QPepperIntegrationPlugin : public QPlatformIntegrationPlugin -{ - Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QPA.QPlatformIntegrationFactoryInterface.5.1" FILE - "pepper.json") -public: - QStringList keys() const; - QPlatformIntegration *create(const QString &, const QStringList &) Q_DECL_OVERRIDE; -}; - -QStringList QPepperIntegrationPlugin::keys() const -{ - QStringList list; - list << QStringLiteral("pepper"); - return list; -} - -QPlatformIntegration *QPepperIntegrationPlugin::create(const QString &system, - const QStringList ¶mList) -{ - Q_UNUSED(paramList); - // qDebug() << "QPepperIntegrationPlugin::create" << system; - if (system.toLower() == QStringLiteral("pepper")) - return new QPepperIntegration; - return 0; -} - -QT_END_NAMESPACE - -#include "qpepperpluginmain.moc" +// #include "qpepperintegration.h" +// +// #include +// #include +// +// QT_BEGIN_NAMESPACE +// +// class QPepperIntegrationPlugin : public QPlatformIntegrationPlugin +// { +// Q_OBJECT +// Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QPA.QPlatformIntegrationFactoryInterface.5.1" FILE +// "pepper.json") +// public: +// QStringList keys() const; +// QPlatformIntegration *create(const QString &, const QStringList &) Q_DECL_OVERRIDE; +// }; +// +// QStringList QPepperIntegrationPlugin::keys() const +// { +// QStringList list; +// list << QStringLiteral("pepper"); +// return list; +// } +// +// QPlatformIntegration *QPepperIntegrationPlugin::create(const QString &system, +// const QStringList ¶mList) +// { +// Q_UNUSED(paramList); +// // qDebug() << "QPepperIntegrationPlugin::create" << system; +// if (system.toLower() == QStringLiteral("pepper")) +// return new QPepperIntegration; +// return 0; +// } +// +// QT_END_NAMESPACE +// +// #include "qpepperpluginmain.moc" diff --git a/src/tools/nacldeployqt/main.cpp b/src/tools/nacldeployqt/main.cpp index cdc982e8f8..418c5fc4e7 100644 --- a/src/tools/nacldeployqt/main.cpp +++ b/src/tools/nacldeployqt/main.cpp @@ -46,7 +46,7 @@ private: QString findPNaClTool(const QString &sdkRoot, const QString &toolName); QList quote(const QList &list); void runCommand(const QString &command); - bool copyRecursively(const QString &srcFilePath, const QString &tgtFilePath); + bool copyRecursively(const QString &srcFilePath, const QString &tgtFilePath, bool skipBinaries); QByteArray instantiateTemplate(const QByteArray &tmplate); void instantiateWriteTemplate(const QByteArray &tmplate, const QString &filePath); }; @@ -172,7 +172,11 @@ int QtNaclDeployer::deploy() QString target = targetBase + "/" + import; // TODO: Skip the binaries for static builds; they will be built into the main nexe - copyRecursively(source, target); + bool skipBinaries = false; + if (deploymentType == Emscripten) { + skipBinaries = true; + } + copyRecursively(source, target, skipBinaries); } } @@ -390,7 +394,8 @@ void QtNaclDeployer::runCommand(const QString &command) } bool QtNaclDeployer::copyRecursively(const QString &srcFilePath, - const QString &tgtFilePath) + const QString &tgtFilePath, + bool skipBinaries) { QFileInfo srcFileInfo(srcFilePath); if (srcFileInfo.isDir()) { @@ -402,11 +407,14 @@ bool QtNaclDeployer::copyRecursively(const QString &srcFilePath, QDir sourceDir(srcFilePath); QStringList fileNames = sourceDir.entryList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot | QDir::Hidden | QDir::System); foreach (const QString &fileName, fileNames) { + if (skipBinaries && (fileName.endsWith(".so") || fileName.endsWith(".a"))) { + continue; + } const QString newSrcFilePath = srcFilePath + QLatin1Char('/') + fileName; const QString newTgtFilePath = tgtFilePath + QLatin1Char('/') + fileName; - if (!copyRecursively(newSrcFilePath, newTgtFilePath)) + if (!copyRecursively(newSrcFilePath, newTgtFilePath, skipBinaries)) return false; } } else { diff --git a/src/tools/nacldeployqt/template_qtloader.cpp b/src/tools/nacldeployqt/template_qtloader.cpp index fdf3d313ad..201e387066 100644 --- a/src/tools/nacldeployqt/template_qtloader.cpp +++ b/src/tools/nacldeployqt/template_qtloader.cpp @@ -2,7 +2,7 @@ const char *templateQtLoader = R"STRING_DELIMITER( // This script is generated by nacldeployqt as a part of the standard // Qt deployment. It can be used either as-is or as a basis for a // custom deployment solution. Note that some parts of this script -// (such as onMessage) is required by Qt. +// (such as onMessage) are required by Qt. // // Usage: // @@ -49,6 +49,10 @@ const char *templateQtLoader = R"STRING_DELIMITER( // 1) As argn, argv key/value pairs to Init() of a QPepperInstance subclass. // 2) As environment variables: toUpper(key)=value. +var doCreateInstance = function () { + console.log("Please call QtLoader.load() instead of loading your application script.") +} + function QtLoader(config) { var self = this; self.config = config; @@ -182,14 +186,6 @@ function onLoad(event) self.embed.style.visibility = "visible" } -function loadScript(src, onload) -{ - var script = document.createElement('script') - script.src = src - script.onload = function () { onload() }; - document.head.appendChild(script); -} - // Create Qt container element, possibly re-using existingElement function createElement(existingElement) { @@ -263,15 +259,20 @@ function loadEmscripten() var height = self.listener.offsetHeight var embed = document.createElement("div"); + self.embed = embed embed.setAttribute("class", "qt-embed"); self.listener.appendChild(embed); self.listener.embed = embed; - loadScript(config.src, function(){ + doCreateInstance = function() { CreateInstance(width, height, embed); embed.finishLoading(); - }) -} + }; + + var script = document.createElement('script') + script.src = config.src; + document.head.appendChild(script); +}; function postMessage(message) { self.embed.postMessage(message) -- cgit v1.2.3