From 248be33550961ffa88130f8815616cf61701ff1e Mon Sep 17 00:00:00 2001 From: Michael Bishop Date: Fri, 18 Oct 2013 11:04:08 -0400 Subject: [PATCH 01/12] Added preliminary support for the SDL2 touch api. Missing items: 1. Timestamps 2. TouchID (the Device ID) As inline with the SDL spec, we will pass a touch ID of `SDL_TOUCH_MOUSEID` for touch events that are simulated by the mouse so games can rely solely on touch events if they like. Includes the SDL2 Copyright notice on the headers that contain SDL2 content. Includes a fix to SDL_PeepEvents. --- src/library_browser.js | 46 ++++--- src/library_sdl.js | 217 ++++++++++++++++++++++++-------- src/struct_info.json | 23 +++- system/include/SDL/COPYING | 5 + system/include/SDL/SDL_events.h | 70 +++++++---- system/include/SDL/SDL_touch.h | 92 +++++--------- 6 files changed, 296 insertions(+), 157 deletions(-) diff --git a/src/library_browser.js b/src/library_browser.js index 0808b9f04a0a9..9f4bed5cffaca 100644 --- a/src/library_browser.js +++ b/src/library_browser.js @@ -482,6 +482,8 @@ mergeInto(LibraryManager.library, { mouseY: 0, mouseMovementX: 0, mouseMovementY: 0, + touches: {}, + lastTouches: {}, calculateMouseEvent: function(event) { // event should be mousemove, mousedown or mouseup if (Browser.pointerLock) { @@ -510,8 +512,9 @@ mergeInto(LibraryManager.library, { // Otherwise, calculate the movement based on the changes // in the coordinates. var rect = Module["canvas"].getBoundingClientRect(); - var x, y; - + var cw = Module["canvas"].width; + var ch = Module["canvas"].height; + // Neither .scrollX or .pageXOffset are defined in a spec, but // we prefer .scrollX because it is currently in a spec draft. // (see: http://www.w3.org/TR/2013/WD-cssom-view-20131217/) @@ -522,26 +525,37 @@ mergeInto(LibraryManager.library, { // and we have no viable fallback. assert((typeof scrollX !== 'undefined') && (typeof scrollY !== 'undefined'), 'Unable to retrieve scroll position, mouse positions likely broken.'); #endif - if (event.type == 'touchstart' || - event.type == 'touchend' || - event.type == 'touchmove') { - var t = event.touches.item(0); - if (t) { - x = t.pageX - (scrollX + rect.left); - y = t.pageY - (scrollY + rect.top); - } else { - return; + + if (event.type === 'touchstart' || event.type === 'touchend' || event.type === 'touchmove') { + var touch = event.touch; + if (touch === undefined) { + return; // the "touch" property is only defined in SDL + } - } else { - x = event.pageX - (scrollX + rect.left); - y = event.pageY - (scrollY + rect.top); + var adjustedX = touch.pageX - (scrollX + rect.left); + var adjustedY = touch.pageY - (scrollY + rect.top); + + adjustedX = adjustedX * (cw / rect.width); + adjustedY = adjustedY * (ch / rect.height); + + var coords = {x: adjustedX, y: adjustedY}; + + if (event.type === 'touchstart') { + Browser.lastTouches[touch.identifier] = coords; + Browser.touches[touch.identifier] = coords; + } else if (event.type === 'touchend' || event.type === 'touchmove') { + Browser.lastTouches[touch.identifier] = Browser.touches[touch.identifier]; + Browser.touches[touch.identifier] = { x: adjustedX, y: adjustedY }; + } + return; } + var x = event.pageX - (scrollX + rect.left); + var y = event.pageY - (scrollY + rect.top); + // the canvas might be CSS-scaled compared to its backbuffer; // SDL-using content will want mouse coordinates in terms // of backbuffer units. - var cw = Module["canvas"].width; - var ch = Module["canvas"].height; x = x * (cw / rect.width); y = y * (ch / rect.height); diff --git a/src/library_sdl.js b/src/library_sdl.js index d90484ad44a1e..ffa2b2a5bd3f3 100644 --- a/src/library_sdl.js +++ b/src/library_sdl.js @@ -82,6 +82,8 @@ var LibrarySDL = { DOMEventToSDLEvent: {}, + TOUCH_DEFAULT_ID: 0, // Our default deviceID for touch events (we get nothing from the browser) + keyCodes: { // DOM code ==> SDL code. See https://developer.mozilla.org/en/Document_Object_Model_%28DOM%29/KeyboardEvent and SDL_keycode.h // For keys that don't have unicode value, we map DOM codes with the corresponding scan codes + 1024 (using "| 1 << 10") 16: 225 | 1<<10, // shift @@ -417,50 +419,104 @@ var LibrarySDL = { } }, - touchX: 0, touchY: 0, + // the browser sends out touchstart events with the whole group of touches + // even if we received a previous touchstart for a specific touch identifier. + // You can test this by pressing one finger to the screen, then another. You'll + // receive two touchstart events, the first with a touches count of 1 the second + // with a touches count of two. + // SDL sends out a new touchstart event for only each newly started touch so to + // emulate this, we keep track of previously started touches. + downFingers: {}, savedKeydown: null, receiveEvent: function(event) { switch(event.type) { - case 'touchstart': + case 'touchstart': case 'touchmove': { event.preventDefault(); - var touch = event.touches[0]; - touchX = touch.pageX; - touchY = touch.pageY; - var event = { - type: 'mousedown', - button: 0, - pageX: touchX, - pageY: touchY + + var touches = []; + + // Clear out any touchstart events that we've already processed + if (event.type === 'touchstart') { + for(var i = 0; i < event.touches.length; i++) { + var touch = event.touches[i]; + if (SDL.downFingers[touch.identifier] != true) { + SDL.downFingers[touch.identifier] = true; + touches.push(touch); + } + } + } else { + touches = event.touches; + } + + var firstTouch = touches[0]; + if ( event.type == 'touchstart' ) { + SDL.DOMButtons[0] = 1; }; - SDL.DOMButtons[0] = 1; - SDL.events.push(event); - break; - case 'touchmove': - event.preventDefault(); - var touch = event.touches[0]; - touchX = touch.pageX; - touchY = touch.pageY; - event = { - type: 'mousemove', + var mouseEventType; + switch(event.type) { + case 'touchstart': mouseEventType = 'mousedown'; break; + case 'touchmove': mouseEventType = 'mousemove'; break; + } + var mouseEvent = { + type: mouseEventType, button: 0, - pageX: touchX, - pageY: touchY + pageX: firstTouch.clientX, + pageY: firstTouch.clientY + }; + SDL.events.push(mouseEvent); + + for (i=0;i 0 && numEvents > 0) { - var type = SDL.DOMEventToSDLEvent[SDL.events[0].type]; - if (type < from || type > to) break; - SDL.makeCEvent(SDL.events.shift(), events); - got++; - numEvents--; - // events += sizeof(..) + // We only handle 1 event right now + assert(requestedEventCount == 1); + + var index = 0; + var retrievedEventCount = 0; + // this should look through the entire queue until it has filled up the events + // array + while ( index < SDL.events.length && retrievedEventCount < requestedEventCount ) { + var event = SDL.events[index]; + var type = SDL.DOMEventToSDLEvent[event.type]; + if ( from <= type && type <= to) { + SDL.makeCEvent(event, events); + SDL.events.splice(index, 1); + retrievedEventCount++; + } else { + index++; + } } - return got; + return retrievedEventCount; } default: throw 'SDL_PeepEvents does not yet support that action: ' + action; } diff --git a/src/struct_info.json b/src/struct_info.json index 2a2b4c641dc73..f762bf2b0e3dc 100644 --- a/src/struct_info.json +++ b/src/struct_info.json @@ -948,11 +948,10 @@ ], "SDL_MouseMotionEvent": [ "type", + "timestamp", "windowID", + "which", "state", - "padding1", - "padding2", - "padding3", "x", "y", "xrel", @@ -960,7 +959,9 @@ ], "SDL_MouseButtonEvent": [ "type", + "timestamp", "windowID", + "which", "button", "state", "padding1", @@ -983,6 +984,17 @@ "state", "padding1" ], + "SDL_TouchFingerEvent": [ + "type", + "timestamp", + "touchId", + "fingerId", + "x", + "y", + "dx", + "dy", + "pressure" + ], "SDL_ResizeEvent": [ "type", "w", @@ -990,6 +1002,11 @@ ] } }, + { + "file": "SDL/SDL_touch.h", + "defines": ["SDL_TOUCH_MOUSEID"], + "structs": {} + }, { "file": "SDL/SDL_audio.h", "defines": [ diff --git a/system/include/SDL/COPYING b/system/include/SDL/COPYING index 15639581a7883..71cc7e42e20dc 100644 --- a/system/include/SDL/COPYING +++ b/system/include/SDL/COPYING @@ -17,3 +17,8 @@ freely, subject to the following restrictions: 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. + +--- + + Portions of these headers taken from SDL2 (where noted) + Copyright (C) 1997-2013 Sam Lantinga diff --git a/system/include/SDL/SDL_events.h b/system/include/SDL/SDL_events.h index 8be00ceb32b64..183ea4b2c5b03 100644 --- a/system/include/SDL/SDL_events.h +++ b/system/include/SDL/SDL_events.h @@ -2,6 +2,9 @@ Simple DirectMedia Layer Copyright (C) 1997-2011 Sam Lantinga + Portions of these headers taken from SDL2 (where noted) + Copyright (C) 1997-2013 Sam Lantinga + This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. @@ -182,33 +185,43 @@ typedef struct SDL_TextInputEvent /** * \brief Mouse motion event structure (event.motion.*) */ +/*================================= IMPORTANT ================================ + The version of SDL_MouseMotionEvent that comes in these (emscripten) + headers is taken from the finalized version of SDL2 + ============================================================================*/ + typedef struct SDL_MouseMotionEvent { Uint32 type; /**< ::SDL_MOUSEMOTION */ + Uint32 timestamp; Uint32 windowID; /**< The window with mouse focus, if any */ - Uint8 state; /**< The current button state */ - Uint8 padding1; - Uint8 padding2; - Uint8 padding3; - int x; /**< X coordinate, relative to window */ - int y; /**< Y coordinate, relative to window */ - int xrel; /**< The relative motion in the X direction */ - int yrel; /**< The relative motion in the Y direction */ + Uint32 which; /**< The mouse instance id, or SDL_TOUCH_MOUSEID */ + Uint32 state; /**< The current button state */ + Sint32 x; /**< X coordinate, relative to window */ + Sint32 y; /**< Y coordinate, relative to window */ + Sint32 xrel; /**< The relative motion in the X direction */ + Sint32 yrel; /**< The relative motion in the Y direction */ } SDL_MouseMotionEvent; /** * \brief Mouse button event structure (event.button.*) */ +/*================================= IMPORTANT ================================ + The version of SDL_MouseButtonEvent that comes in these (emscripten) + headers is taken from the finalized version of SDL2 + ============================================================================*/ typedef struct SDL_MouseButtonEvent { Uint32 type; /**< ::SDL_MOUSEBUTTONDOWN or ::SDL_MOUSEBUTTONUP */ + Uint32 timestamp; Uint32 windowID; /**< The window with mouse focus, if any */ + Uint32 which; /**< The mouse instance id, or SDL_TOUCH_MOUSEID */ Uint8 button; /**< The mouse button index */ Uint8 state; /**< ::SDL_PRESSED or ::SDL_RELEASED */ Uint8 padding1; Uint8 padding2; - int x; /**< X coordinate, relative to window */ - int y; /**< Y coordinate, relative to window */ + Sint32 x; /**< X coordinate, relative to window */ + Sint32 y; /**< Y coordinate, relative to window */ } SDL_MouseButtonEvent; /** @@ -217,9 +230,11 @@ typedef struct SDL_MouseButtonEvent typedef struct SDL_MouseWheelEvent { Uint32 type; /**< ::SDL_MOUSEWHEEL */ + Uint32 timestamp; Uint32 windowID; /**< The window with mouse focus, if any */ - int x; /**< The amount scrolled horizontally */ - int y; /**< The amount scrolled vertically */ + Uint32 which; /**< The mouse instance id, or SDL_TOUCH_MOUSEID */ + Sint32 x; /**< The amount scrolled horizontally */ + Sint32 y; /**< The amount scrolled vertically */ } SDL_MouseWheelEvent; /** @@ -281,24 +296,25 @@ typedef struct SDL_JoyButtonEvent /** - * \brief Touch finger motion/finger event structure (event.tmotion.*) + * \brief Touch finger motion/finger event structure (event.tfinger.*) */ + +/*================================= IMPORTANT ================================ + The version of SDL_TouchFingerEvent that comes in these (emscripten) + headers is taken from the finalized version of SDL2 + ============================================================================*/ + typedef struct SDL_TouchFingerEvent { - Uint32 type; /**< ::SDL_FINGERMOTION OR - SDL_FINGERDOWN OR SDL_FINGERUP*/ - Uint32 windowID; /**< The window with mouse focus, if any */ - SDL_TouchID touchId; /**< The touch device id */ + Uint32 type; /**< ::SDL_FINGERMOTION or ::SDL_FINGERDOWN or ::SDL_FINGERUP */ + Uint32 timestamp; + SDL_TouchID touchId; /**< The touch device id */ SDL_FingerID fingerId; - Uint8 state; /**< The current button state */ - Uint8 padding1; - Uint8 padding2; - Uint8 padding3; - Uint16 x; - Uint16 y; - Sint16 dx; - Sint16 dy; - Uint16 pressure; + float x; /**< Normalized in the range 0...1 */ + float y; /**< Normalized in the range 0...1 */ + float dx; /**< Normalized in the range 0...1 */ + float dy; /**< Normalized in the range 0...1 */ + float pressure; /**< Normalized in the range 0...1 */ } SDL_TouchFingerEvent; @@ -434,7 +450,7 @@ typedef union SDL_Event SDL_QuitEvent quit; /**< Quit request event data */ SDL_UserEvent user; /**< Custom event data */ SDL_SysWMEvent syswm; /**< System dependent window event data */ - SDL_TouchFingerEvent tfinger; /**< Touch finger event data */ + SDL_TouchFingerEvent tfinger; /**< SDL2 Touch finger event data */ SDL_TouchButtonEvent tbutton; /**< Touch button event data */ SDL_MultiGestureEvent mgesture; /**< Multi Finger Gesture data */ SDL_DollarGestureEvent dgesture; /**< Multi Finger Gesture data */ diff --git a/system/include/SDL/SDL_touch.h b/system/include/SDL/SDL_touch.h index 587efcbfba841..fe238f104d2ab 100644 --- a/system/include/SDL/SDL_touch.h +++ b/system/include/SDL/SDL_touch.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2011 Sam Lantinga + Copyright (C) 1997-2013 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -19,9 +19,15 @@ 3. This notice may not be removed or altered from any source distribution. */ +/* + ================================= IMPORTANT ================================ + This header taken from SDL2 + ============================================================================ +*/ + /** * \file SDL_touch.h - * + * * Include file for SDL touch event handling. */ @@ -35,90 +41,52 @@ #include "begin_code.h" /* Set up for C function definitions, even when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ extern "C" { -/* *INDENT-ON* */ #endif - typedef Sint64 SDL_TouchID; typedef Sint64 SDL_FingerID; +typedef struct SDL_Finger +{ + SDL_FingerID id; + float x; + float y; + float pressure; +} SDL_Finger; -struct SDL_Finger { - SDL_FingerID id; - Uint16 x; - Uint16 y; - Uint16 pressure; - Uint16 xdelta; - Uint16 ydelta; - Uint16 last_x, last_y,last_pressure; /* the last reported coordinates */ - SDL_bool down; -}; - -typedef struct SDL_Touch SDL_Touch; -typedef struct SDL_Finger SDL_Finger; - - -struct SDL_Touch { - - /* Free the touch when it's time */ - void (*FreeTouch) (SDL_Touch * touch); - - /* data common for tablets */ - float pressure_max, pressure_min; - float x_max,x_min; - float y_max,y_min; - Uint16 xres,yres,pressureres; - float native_xres,native_yres,native_pressureres; - float tilt; /* for future use */ - float rotation; /* for future use */ - - /* Data common to all touch */ - SDL_TouchID id; - SDL_Window *focus; - - char *name; - Uint8 buttonstate; - SDL_bool relative_mode; - SDL_bool flush_motion; - - int num_fingers; - int max_fingers; - SDL_Finger** fingers; - - void *driverdata; -}; - +/* Used as the device ID for mouse events simulated with touch input */ +#define SDL_TOUCH_MOUSEID ((Uint32)-1) /* Function prototypes */ /** - * \brief Get the touch object at the given id. - * - * + * \brief Get the number of registered touch devices. */ - extern DECLSPEC SDL_Touch* SDLCALL SDL_GetTouch(SDL_TouchID id); +extern DECLSPEC int SDLCALL SDL_GetNumTouchDevices(void); +/** + * \brief Get the touch ID with the given index, or 0 if the index is invalid. + */ +extern DECLSPEC SDL_TouchID SDLCALL SDL_GetTouchDevice(int index); +/** + * \brief Get the number of active fingers for a given touch device. + */ +extern DECLSPEC int SDLCALL SDL_GetNumTouchFingers(SDL_TouchID touchID); /** - * \brief Get the finger object of the given touch, at the given id. - * - * + * \brief Get the finger object of the given touch, with the given index. */ - extern - DECLSPEC SDL_Finger* SDLCALL SDL_GetFinger(SDL_Touch *touch, SDL_FingerID id); +extern DECLSPEC SDL_Finger * SDLCALL SDL_GetTouchFinger(SDL_TouchID touchID, int index); /* Ends C function definitions when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ } -/* *INDENT-ON* */ #endif #include "close_code.h" -#endif /* _SDL_mouse_h */ +#endif /* _SDL_touch_h */ /* vi: set ts=4 sw=4 expandtab: */ From 1bea0b9d70733e69a127d80a8c33b35137cdfb42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jukka=20Jyl=C3=A4nki?= Date: Sun, 13 Apr 2014 17:03:33 +0300 Subject: [PATCH 02/12] Apply kripken's code formatting review to michaeljbishop's SDL2 touch pull request. --- src/library_browser.js | 2 +- src/library_sdl.js | 17 ++++++++--------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/library_browser.js b/src/library_browser.js index 9f4bed5cffaca..4be7315e73fd8 100644 --- a/src/library_browser.js +++ b/src/library_browser.js @@ -538,7 +538,7 @@ mergeInto(LibraryManager.library, { adjustedX = adjustedX * (cw / rect.width); adjustedY = adjustedY * (ch / rect.height); - var coords = {x: adjustedX, y: adjustedY}; + var coords = { x: adjustedX, y: adjustedY }; if (event.type === 'touchstart') { Browser.lastTouches[touch.identifier] = coords; diff --git a/src/library_sdl.js b/src/library_sdl.js index ffa2b2a5bd3f3..6d8261ff09229 100644 --- a/src/library_sdl.js +++ b/src/library_sdl.js @@ -438,7 +438,7 @@ var LibrarySDL = { // Clear out any touchstart events that we've already processed if (event.type === 'touchstart') { - for(var i = 0; i < event.touches.length; i++) { + for (var i = 0; i < event.touches.length; i++) { var touch = event.touches[i]; if (SDL.downFingers[touch.identifier] != true) { SDL.downFingers[touch.identifier] = true; @@ -450,9 +450,9 @@ var LibrarySDL = { } var firstTouch = touches[0]; - if ( event.type == 'touchstart' ) { + if (event.type == 'touchstart') { SDL.DOMButtons[0] = 1; - }; + } var mouseEventType; switch(event.type) { case 'touchstart': mouseEventType = 'mousedown'; break; @@ -466,7 +466,7 @@ var LibrarySDL = { }; SDL.events.push(mouseEvent); - for (i=0;i Date: Sun, 13 Apr 2014 18:08:53 +0300 Subject: [PATCH 03/12] Implement SDL2 touch event timestamps and add a digital 0/1 pressure if no pressure data is present. --- src/library_sdl.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/library_sdl.js b/src/library_sdl.js index 6d8261ff09229..eedb8c482cef6 100644 --- a/src/library_sdl.js +++ b/src/library_sdl.js @@ -10,7 +10,7 @@ // or otherwise). var LibrarySDL = { - $SDL__deps: ['$FS', '$PATH', '$Browser'], + $SDL__deps: ['$FS', '$PATH', '$Browser', 'SDL_GetTicks'], $SDL: { defaults: { width: 320, @@ -801,14 +801,18 @@ var LibrarySDL = { if (touch['deviceID'] === undefined) touch.deviceID = SDL.TOUCH_DEFAULT_ID; if (dx === 0 && dy === 0 && event.type === 'touchmove') return; // don't send these if nothing happened {{{ makeSetValue('ptr', C_STRUCTS.SDL_TouchFingerEvent.type, 'SDL.DOMEventToSDLEvent[event.type]', 'i32') }}}; - {{{ makeSetValue('ptr', C_STRUCTS.SDL_TouchFingerEvent.timestamp, '0', 'i32') }}}; // XXX michaeljbishop - Unimplemented for now + {{{ makeSetValue('ptr', C_STRUCTS.SDL_TouchFingerEvent.timestamp, '_SDL_GetTicks()', 'i32') }}}; {{{ makeSetValue('ptr', C_STRUCTS.SDL_TouchFingerEvent.touchId, 'touch.deviceID', 'i64') }}}; {{{ makeSetValue('ptr', C_STRUCTS.SDL_TouchFingerEvent.fingerId, 'touch.identifier', 'i64') }}}; {{{ makeSetValue('ptr', C_STRUCTS.SDL_TouchFingerEvent.x, 'x', 'float') }}}; {{{ makeSetValue('ptr', C_STRUCTS.SDL_TouchFingerEvent.y, 'y', 'float') }}}; {{{ makeSetValue('ptr', C_STRUCTS.SDL_TouchFingerEvent.dx, 'dx', 'float') }}}; {{{ makeSetValue('ptr', C_STRUCTS.SDL_TouchFingerEvent.dy, 'dy', 'float') }}}; - {{{ makeSetValue('ptr', C_STRUCTS.SDL_TouchFingerEvent.pressure, 'touch.force', 'float') }}}; + if (touch.force !== undefined) { + {{{ makeSetValue('ptr', C_STRUCTS.SDL_TouchFingerEvent.pressure, 'touch.force', 'float') }}}; + } else { // No pressure data, send a digital 0/1 pressure. + {{{ makeSetValue('ptr', C_STRUCTS.SDL_TouchFingerEvent.pressure, 'event.type == "touchend" ? 0 : 1', 'float') }}}; + } break; } case 'unload': { From 2bbdb0cd396d785a9587bc776d699283c1902ff7 Mon Sep 17 00:00:00 2001 From: Chad Austin Date: Mon, 31 Mar 2014 22:43:28 -0700 Subject: [PATCH 04/12] embind doesn't always need the full std::type_info record. if EMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES=0, then use a lighter type identifier. This shaves 175 KB off of our engine's minified JavaScript. --- system/include/emscripten/bind.h | 2 +- system/include/emscripten/wire.h | 64 +++++++++++++++++++++++++++----- system/lib/embind/bind.cpp | 38 +++++++++++-------- tests/embind/embind.test.js | 4 ++ tests/embind/embind_test.cpp | 2 + 5 files changed, 83 insertions(+), 27 deletions(-) diff --git a/system/include/emscripten/bind.h b/system/include/emscripten/bind.h index 872f279b610db..b4c5004e87991 100644 --- a/system/include/emscripten/bind.h +++ b/system/include/emscripten/bind.h @@ -813,7 +813,7 @@ namespace emscripten { // NOTE: this returns the class type, not the pointer type template inline TYPEID getActualType(T* ptr) { - return reinterpret_cast(&typeid(*ptr)); + return getLightTypeID(*ptr); }; } diff --git a/system/include/emscripten/wire.h b/system/include/emscripten/wire.h index 05b3ac33685cb..c20e2f5555f1c 100644 --- a/system/include/emscripten/wire.h +++ b/system/include/emscripten/wire.h @@ -15,22 +15,66 @@ #define EMSCRIPTEN_ALWAYS_INLINE __attribute__((always_inline)) namespace emscripten { + #ifndef EMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES + #define EMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES 1 + #endif + + + #if EMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES + constexpr bool has_unbound_type_names = true; + #else + constexpr bool has_unbound_type_names = false; + #endif + namespace internal { typedef void (*GenericFunction)(); - typedef const struct _TYPEID* TYPEID; + typedef const struct _TYPEID {}* TYPEID; + + + // We don't need the full std::type_info implementation. We + // just need a unique identifier per type and polymorphic type + // identification. + + template + struct CanonicalizedID { + static TYPEID get() { + static _TYPEID c; + return &c; + } + }; + + template + struct Canonicalized { + typedef typename std::remove_cv::type>::type type; + }; + + template + struct LightTypeID { + static TYPEID get() { + typedef typename Canonicalized::type C; + if (has_unbound_type_names || std::is_polymorphic::value) { + return reinterpret_cast(&typeid(C)); + } else { + return CanonicalizedID::get(); + } + } + }; + + template + const TYPEID getLightTypeID(const T& value) { + typedef typename Canonicalized::type C; + if (has_unbound_type_names || std::is_polymorphic::value) { + return reinterpret_cast(&typeid(value)); + } else { + return LightTypeID::get(); + } + } - // This implementation is technically not legal, as it's not - // required that two calls to typeid produce the same exact - // std::type_info instance. That said, it's likely to work - // given Emscripten compiles everything into one binary. - // Should it not work in the future: replace TypeID with an - // int, and store all TypeInfo we see in a map, allocating new - // TypeIDs as we add new items to the map. template struct TypeID { static TYPEID get() { - return reinterpret_cast(&typeid(T)); + return LightTypeID::get(); } }; @@ -53,7 +97,7 @@ namespace emscripten { template struct TypeID> { static TYPEID get() { - return reinterpret_cast(&typeid(T*)); + return LightTypeID::get(); } }; diff --git a/system/lib/embind/bind.cpp b/system/lib/embind/bind.cpp index f43d1ea1dbfbd..37918050e7c64 100644 --- a/system/lib/embind/bind.cpp +++ b/system/lib/embind/bind.cpp @@ -14,26 +14,32 @@ using namespace emscripten; extern "C" { const char* __attribute__((used)) __getTypeName(const std::type_info* ti) { + if (has_unbound_type_names) { #ifdef USE_CXA_DEMANGLE - int stat; - char* demangled = abi::__cxa_demangle(ti->name(), NULL, NULL, &stat); - if (stat == 0 && demangled) { - return demangled; - } + int stat; + char* demangled = abi::__cxa_demangle(ti->name(), NULL, NULL, &stat); + if (stat == 0 && demangled) { + return demangled; + } - switch (stat) { - case -1: - return strdup(""); - case -2: - return strdup(""); - case -3: - return strdup(""); - default: - return strdup(""); - } + switch (stat) { + case -1: + return strdup(""); + case -2: + return strdup(""); + case -3: + return strdup(""); + default: + return strdup(""); + } #else - return strdup(ti->name()); + return strdup(ti->name()); #endif + } else { + char str[80]; + sprintf(str, "%p", ti); + return strdup(str); + } } } diff --git a/tests/embind/embind.test.js b/tests/embind/embind.test.js index e2160c33a82fa..4b10a6c6ce6a7 100644 --- a/tests/embind/embind.test.js +++ b/tests/embind/embind.test.js @@ -1646,6 +1646,10 @@ module({ if (typeof INVOKED_FROM_EMSCRIPTEN_TEST_RUNNER === "undefined") { // TODO: Enable this to work in Emscripten runner as well! BaseFixture.extend("unbound types", function() { + if (!cm.hasUnboundTypeNames) { + return; + } + function assertMessage(fn, message) { var e = assert.throws(cm.UnboundTypeError, fn); assert.equal(message, e.message); diff --git a/tests/embind/embind_test.cpp b/tests/embind/embind_test.cpp index d299660a5e708..b0c68f75d10de 100644 --- a/tests/embind/embind_test.cpp +++ b/tests/embind/embind_test.cpp @@ -2147,6 +2147,8 @@ struct BoundClass { }; EMSCRIPTEN_BINDINGS(incomplete) { + constant("hasUnboundTypeNames", emscripten::has_unbound_type_names); + function("getUnboundClass", &passThrough); class_>("HasUnboundBase") From e4cfbda44856c3b7bc4081d3828423971cbedf1d Mon Sep 17 00:00:00 2001 From: Chad Austin Date: Mon, 31 Mar 2014 23:42:50 -0700 Subject: [PATCH 05/12] Add a way to opt out of compiler-generated type names for smart pointers and wrapper types. --- system/include/emscripten/bind.h | 18 ++++++++---- tests/embind/embind.test.js | 2 +- tests/embind/embind_test.cpp | 48 ++++++++++++++++---------------- 3 files changed, 37 insertions(+), 31 deletions(-) diff --git a/system/include/emscripten/bind.h b/system/include/emscripten/bind.h index b4c5004e87991..1c7daeba2dbd7 100644 --- a/system/include/emscripten/bind.h +++ b/system/include/emscripten/bind.h @@ -890,7 +890,7 @@ namespace emscripten { } template - const class_& smart_ptr() const { + const class_& smart_ptr(const char* name = typeid(PointerType).name()) const { using namespace internal; typedef smart_ptr_trait PointerTrait; @@ -901,7 +901,7 @@ namespace emscripten { _embind_register_smart_ptr( TypeID::get(), TypeID::get(), - typeid(PointerType).name(), + name, PointerTrait::get_sharing_policy(), reinterpret_cast(&PointerTrait::get), reinterpret_cast(&PointerTrait::construct_null), @@ -933,10 +933,16 @@ namespace emscripten { } template - const class_& smart_ptr_constructor(SmartPtr (*factory)(Args...), Policies...) const { + const class_& smart_ptr_constructor(SmartPtr (*factory)(Args...), Policies&&... policies) const { + // TODO: once everyone has manually specified a name, remove this + return smart_ptr_constructor(typeid(SmartPtr).name(), factory, std::forward(policies)...); + } + + template + const class_& smart_ptr_constructor(const char* smartPtrName, SmartPtr (*factory)(Args...), Policies...) const { using namespace internal; - smart_ptr(); + smart_ptr(smartPtrName); typename WithPolicies::template ArgTypeList args; _embind_register_class_constructor( @@ -949,10 +955,10 @@ namespace emscripten { } template - const class_& allow_subclass() const { + const class_& allow_subclass(const char* wrapperClassName = typeid(WrapperType).name()) const { using namespace internal; - auto cls = class_>(typeid(WrapperType).name()) + auto cls = class_>(wrapperClassName) ; SmartPtrIfNeeded _(cls); diff --git a/tests/embind/embind.test.js b/tests/embind/embind.test.js index 4b10a6c6ce6a7..6bba4de085d82 100644 --- a/tests/embind/embind.test.js +++ b/tests/embind/embind.test.js @@ -1408,7 +1408,7 @@ module({ var e = assert.throws(cm.BindingError, function() { cm.passThroughCustomSmartPtr(o); }); - assert.equal('Cannot convert argument of type NSt3__110shared_ptrI20HeldByCustomSmartPtrEE to parameter type 14CustomSmartPtrI20HeldByCustomSmartPtrE', e.message); + assert.equal('Cannot convert argument of type shared_ptr to parameter type CustomSmartPtr', e.message); o.delete(); }); diff --git a/tests/embind/embind_test.cpp b/tests/embind/embind_test.cpp index b0c68f75d10de..48529b9ebb348 100644 --- a/tests/embind/embind_test.cpp +++ b/tests/embind/embind_test.cpp @@ -1150,8 +1150,8 @@ void callDifferentArguments(AbstractClass& ac, int i, double d, unsigned char f, EMSCRIPTEN_BINDINGS(interface_tests) { class_("AbstractClass") - .smart_ptr>() - .allow_subclass() + .smart_ptr>("shared_ptr") + .allow_subclass("AbstractClassWrapper") .function("abstractMethod", &AbstractClass::abstractMethod) .function("optionalMethod", &AbstractClass::optionalMethod) ; @@ -1483,7 +1483,7 @@ EMSCRIPTEN_BINDINGS(tests) { function("emval_test_take_and_return_TupleInStruct", &emval_test_take_and_return_TupleInStruct); class_("ValHolder") - .smart_ptr>() + .smart_ptr>("std::shared_ptr") .constructor() .function("getVal", &ValHolder::getVal) .function("getValNonConst", &ValHolder::getValNonConst) @@ -1522,7 +1522,7 @@ EMSCRIPTEN_BINDINGS(tests) { function("emval_test_take_and_call_functor", &emval_test_take_and_call_functor); class_("StringHolder") - .smart_ptr>() + .smart_ptr>("shared_ptr") .constructor() .function("set", &StringHolder::set) .function("get", &StringHolder::get) @@ -1566,7 +1566,7 @@ EMSCRIPTEN_BINDINGS(tests) { // register Derived before Base as a test that it's possible to // register base classes afterwards class_>("Derived") - .smart_ptr>() + .smart_ptr>("shared_ptr") .constructor<>() .function("getClassName", &Derived::getClassName) .function("getMember", &Derived::getMember) @@ -1575,7 +1575,7 @@ EMSCRIPTEN_BINDINGS(tests) { ; class_("Base") - .smart_ptr>() + .smart_ptr>("shared_ptr() .function("getClassName", &Base::getClassName) .function("getClassNameFromBase", &Base::getClassNameFromBase) @@ -1589,7 +1589,7 @@ EMSCRIPTEN_BINDINGS(tests) { ; class_("SecondBase") - .smart_ptr>() + .smart_ptr>("shared_ptr") .constructor<>() .function("getClassName", &SecondBase::getClassName) .function("getClassNameFromSecondBase", &SecondBase::getClassNameFromSecondBase) @@ -1612,13 +1612,13 @@ EMSCRIPTEN_BINDINGS(tests) { ; class_("SiblingDerived") - .smart_ptr>() + .smart_ptr>("shared_ptr") .constructor<>() .function("getClassName", &SiblingDerived::getClassName) ; class_>("MultiplyDerived") - .smart_ptr>() + .smart_ptr>("shared_ptr") .constructor<>() .function("getClassName", &MultiplyDerived::getClassName) .class_function("getInstanceCount", &MultiplyDerived::getInstanceCount) @@ -1630,26 +1630,26 @@ EMSCRIPTEN_BINDINGS(tests) { ; class_ >("DerivedThrice") - .smart_ptr>() + .smart_ptr>("shared_ptr") .constructor<>() .function("getClassName", &DerivedThrice::getClassName) ; class_("PolyBase") - .smart_ptr>() + .smart_ptr>("shared_ptr") .constructor<>() .function("virtualGetClassName", &PolyBase::virtualGetClassName) .function("getClassName", &PolyBase::getClassName) ; class_("PolySecondBase") - .smart_ptr>() + .smart_ptr>("shared_ptr") .constructor<>() .function("getClassName", &PolySecondBase::getClassName) ; class_>("PolyDerived") - .smart_ptr>() + .smart_ptr>("shared_ptr") .constructor<>() .function("virtualGetClassName", &PolyDerived::virtualGetClassName) .function("getClassName", &PolyDerived::getClassName) @@ -1671,43 +1671,43 @@ EMSCRIPTEN_BINDINGS(tests) { // } class_>("PolySiblingDerived") - .smart_ptr>() + .smart_ptr>("shared_ptr") .constructor<>() .function("getClassName", &PolySiblingDerived::getClassName) ; class_>("PolyMultiplyDerived") - .smart_ptr>() + .smart_ptr>("shared_ptr") .constructor<>() .function("getClassName", &PolyMultiplyDerived::getClassName) ; class_>("PolyDerivedThrice") - .smart_ptr>() + .smart_ptr>("shared_ptr") .constructor<>() .function("getClassName", &PolyDerivedThrice::getClassName) ; class_("PolyDiamondBase") - .smart_ptr>() + .smart_ptr>("shared_ptr") .constructor<>() .function("getClassName", &PolyDiamondBase::getClassName) ; class_("PolyDiamondDerived") - .smart_ptr>() + .smart_ptr>("shared_ptr") .constructor<>() .function("getClassName", &PolyDiamondDerived::getClassName) ; class_("PolyDiamondSiblingDerived") - .smart_ptr>() + .smart_ptr>("shared_ptr") .constructor<>() .function("getClassName", &PolyDiamondSiblingDerived::getClassName) ; class_("PolyDiamondMultiplyDerived") - .smart_ptr>() + .smart_ptr>("shared_ptr") .constructor<>() .function("getClassName", &PolyDiamondMultiplyDerived::getClassName) ; @@ -1825,7 +1825,7 @@ EMSCRIPTEN_BINDINGS(tests) { auto HeldBySmartPtr_class = class_("HeldBySmartPtr"); HeldBySmartPtr_class - .smart_ptr>() + .smart_ptr>("CustomSmartPtr") .smart_ptr_constructor(&std::make_shared) .class_function("newCustomPtr", HeldBySmartPtr::newCustomPtr) .function("returnThis", &takesHeldBySmartPtrSharedPtr) @@ -1836,8 +1836,8 @@ EMSCRIPTEN_BINDINGS(tests) { function("takesHeldBySmartPtrSharedPtr", &takesHeldBySmartPtrSharedPtr); class_("HeldByCustomSmartPtr") - .smart_ptr>() - .smart_ptr_constructor(&HeldByCustomSmartPtr::create) + .smart_ptr>("shared_ptr") + .smart_ptr_constructor("CustomSmartPtr", &HeldByCustomSmartPtr::create) .class_function("createSharedPtr", &HeldByCustomSmartPtr::createSharedPtr) .property("i", &HeldByCustomSmartPtr::i) .property("s", &HeldByCustomSmartPtr::s) @@ -2022,7 +2022,7 @@ EMSCRIPTEN_BINDINGS(overloads) { ; class_("MultipleSmartCtors") - .smart_ptr>() + .smart_ptr>("shared_ptr") .constructor(&std::make_shared) .constructor(&std::make_shared) .function("WhichCtorCalled", &MultipleSmartCtors::WhichCtorCalled) From 5b57fb6c4f6b149bf73b598c987dc275fe450c2b Mon Sep 17 00:00:00 2001 From: Chad Austin Date: Tue, 1 Apr 2014 10:21:19 -0700 Subject: [PATCH 06/12] Always require an explicit name for shared_ptr and wrapper type bindings --- system/include/emscripten/bind.h | 10 ++-------- tests/embind/embind_test.cpp | 4 ++-- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/system/include/emscripten/bind.h b/system/include/emscripten/bind.h index 1c7daeba2dbd7..0de16043ba0cc 100644 --- a/system/include/emscripten/bind.h +++ b/system/include/emscripten/bind.h @@ -890,7 +890,7 @@ namespace emscripten { } template - const class_& smart_ptr(const char* name = typeid(PointerType).name()) const { + const class_& smart_ptr(const char* name) const { using namespace internal; typedef smart_ptr_trait PointerTrait; @@ -932,12 +932,6 @@ namespace emscripten { return *this; } - template - const class_& smart_ptr_constructor(SmartPtr (*factory)(Args...), Policies&&... policies) const { - // TODO: once everyone has manually specified a name, remove this - return smart_ptr_constructor(typeid(SmartPtr).name(), factory, std::forward(policies)...); - } - template const class_& smart_ptr_constructor(const char* smartPtrName, SmartPtr (*factory)(Args...), Policies...) const { using namespace internal; @@ -955,7 +949,7 @@ namespace emscripten { } template - const class_& allow_subclass(const char* wrapperClassName = typeid(WrapperType).name()) const { + const class_& allow_subclass(const char* wrapperClassName) const { using namespace internal; auto cls = class_>(wrapperClassName) diff --git a/tests/embind/embind_test.cpp b/tests/embind/embind_test.cpp index 48529b9ebb348..1b835751f02fe 100644 --- a/tests/embind/embind_test.cpp +++ b/tests/embind/embind_test.cpp @@ -1826,7 +1826,7 @@ EMSCRIPTEN_BINDINGS(tests) { auto HeldBySmartPtr_class = class_("HeldBySmartPtr"); HeldBySmartPtr_class .smart_ptr>("CustomSmartPtr") - .smart_ptr_constructor(&std::make_shared) + .smart_ptr_constructor("shared_ptr", &std::make_shared) .class_function("newCustomPtr", HeldBySmartPtr::newCustomPtr) .function("returnThis", &takesHeldBySmartPtrSharedPtr) .property("i", &HeldBySmartPtr::i) @@ -2249,7 +2249,7 @@ std::shared_ptr return_Base_from_DerivedWithOffset(std::shared_ptr>("DerivedWithOffset") - .smart_ptr_constructor(&std::make_shared) + .smart_ptr_constructor("shared_ptr", &std::make_shared) ; function("return_Base_from_DerivedWithOffset", &return_Base_from_DerivedWithOffset); From 1838f123d3fcd45453b6ca373dce94cc40621d77 Mon Sep 17 00:00:00 2001 From: Chad Austin Date: Tue, 1 Apr 2014 17:06:36 -0700 Subject: [PATCH 07/12] some compile fixes --- system/include/emscripten/bind.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/system/include/emscripten/bind.h b/system/include/emscripten/bind.h index 0de16043ba0cc..0699715c22377 100644 --- a/system/include/emscripten/bind.h +++ b/system/include/emscripten/bind.h @@ -851,15 +851,15 @@ namespace emscripten { template struct SmartPtrIfNeeded { template - SmartPtrIfNeeded(U& cls) { - cls.template smart_ptr(); + SmartPtrIfNeeded(U& cls, const char* smartPtrName) { + cls.template smart_ptr(smartPtrName); } }; template struct SmartPtrIfNeeded { template - SmartPtrIfNeeded(U&) { + SmartPtrIfNeeded(U&, const char*) { } }; }; @@ -949,12 +949,12 @@ namespace emscripten { } template - const class_& allow_subclass(const char* wrapperClassName) const { + const class_& allow_subclass(const char* wrapperClassName, const char* pointerName = "") const { using namespace internal; auto cls = class_>(wrapperClassName) ; - SmartPtrIfNeeded _(cls); + SmartPtrIfNeeded _(cls, pointerName); return class_function( "implement", From 2faa69a865c3d6046d7d5202f2dc747dea3229f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jukka=20Jyl=C3=A4nki?= Date: Mon, 14 Apr 2014 01:22:19 +0300 Subject: [PATCH 08/12] Add interactive and automated testing for SDL touch events. --- tests/sdl_touch.c | 78 +++++++++++++++++++++++++++++++++++++++ tests/test_browser.py | 5 +++ tests/test_interactive.py | 3 ++ 3 files changed, 86 insertions(+) create mode 100644 tests/sdl_touch.c diff --git a/tests/sdl_touch.c b/tests/sdl_touch.c new file mode 100644 index 0000000000000..1fce1df15dc05 --- /dev/null +++ b/tests/sdl_touch.c @@ -0,0 +1,78 @@ +#include +#include +#include +#include +#include + +int result = 1; + +static char *TouchFingerTypeToString(int type) { + if (type == SDL_FINGERMOTION) return "SDL_FINGERMOTION"; + if (type == SDL_FINGERDOWN) return "SDL_FINGERDOWN"; + if (type == SDL_FINGERUP) return "SDL_FINGERUP"; + return "UNKNOWN"; +} + +int got_down = 0; +int got_move = 0; +int got_up = 0; + +void progress() { + if (!got_down) printf("Hold down a finger to generate a touch down event.\n"); + else if (!got_move) printf("Drag a finger to generate a touch move event.\n"); + else if (!got_up) printf("Release a finger to generate a touch up event.\n"); + else + { + int result = 0; +#ifdef REPORT_RESULT + REPORT_RESULT(); +#endif + } +} + +void loop() { + SDL_Event event; + while (SDL_PollEvent(&event)) { + switch(event.type) { + case SDL_FINGERMOTION: + case SDL_FINGERDOWN: + case SDL_FINGERUP: { + SDL_TouchFingerEvent *t = (SDL_TouchFingerEvent*)&event; + printf("type: %s, timestamp: %u, touchId: %llu, fingerId: %llu, x: %f, y: %f, dx: %f, dy: %f, pressure: %f\n", + TouchFingerTypeToString(event.type), t->timestamp, t->touchId, t->fingerId, t->x, t->y, t->dx, t->dy, t->pressure); + + if (t->timestamp != 0 && t->x >= 0.f && t->x <= 1.f && t->y >= 0.f && t->y <= 1.f && t->pressure >= 0.f && t->pressure <= 1.f) { + if (event.type == SDL_FINGERDOWN) { got_down = 1; progress(); } + if (event.type == SDL_FINGERMOTION) { got_move = 1; progress(); } + if (event.type == SDL_FINGERDOWN) { got_up = 1; progress(); } + } + break; + } + } + } +} + +int main() { + SDL_Init(SDL_INIT_VIDEO); + SDL_Surface *screen = SDL_SetVideoMode(600, 450, 32, SDL_HWSURFACE); + + progress(); + +#ifdef AUTOMATE_SUCCESS + EM_ASM( + function sendEvent(type, data) { + var event = document.createEvent('Event'); + event.initEvent(type, true, true); + for(var d in data) event[d] = data[d]; + Module['canvas'].dispatchEvent(event); + } + sendEvent('touchstart', { touches: [ { pageX: 300, pageY: 400, deviceID: 1, identifier: 1, force: 1 } ] }); + sendEvent('touchmove', { touches: [ { pageX: 350, pageY: 400, deviceID: 1, identifier: 1, force: 1 } ] }); + sendEvent('touchend', { changedTouches: [ { pageX: 350, pageY: 400, deviceID: 1, identifier: 1, force: 1 } ] }); + ); +#endif + + emscripten_set_main_loop(loop, 0, 0); + + return 0; +} diff --git a/tests/test_browser.py b/tests/test_browser.py index cf893eb578b77..c06f11ac7ef09 100644 --- a/tests/test_browser.py +++ b/tests/test_browser.py @@ -1793,6 +1793,11 @@ def test_html5(self): print opts self.btest(path_from_root('tests', 'test_html5.c'), args=opts, expected='0') + def test_sdl_touch(self): + for opts in [[], ['-O2', '-g1', '--closure', '1']]: + print opts + self.btest(path_from_root('tests', 'sdl_touch.c'), args=opts + ['-DAUTOMATE_SUCCESS=1'], expected='0') + def test_html5_mouse(self): for opts in [[], ['-O2', '-g1', '--closure', '1']]: print opts diff --git a/tests/test_interactive.py b/tests/test_interactive.py index 4ac52f55a43ff..aa1d96af29ea5 100644 --- a/tests/test_interactive.py +++ b/tests/test_interactive.py @@ -25,6 +25,9 @@ def test_html5_fullscreen(self): def test_html5_mouse(self): self.btest(path_from_root('tests', 'test_html5_mouse.c'), expected='0') + def test_sdl_touch(self): + self.btest(path_from_root('tests', 'sdl_touch.c'), args=['-O2', '-g1', '--closure', '1'], expected='0') + def test_sdl_wm_togglefullscreen(self): self.btest('sdl_wm_togglefullscreen.c', expected='1', args=['-s', 'NO_EXIT_RUNTIME=1']) From f988a171ee8176243ecc9792e3c3e27df9299ba7 Mon Sep 17 00:00:00 2001 From: Jukka Jylanki Date: Mon, 14 Apr 2014 12:10:57 +0300 Subject: [PATCH 09/12] Remove undefined behavior reading 32-bit variables as 64-bit in printf formatting in test_atomic_cxx. Fixes the test on OSX. --- tests/core/test_atomic_cxx.cpp | 34 +++++++++++----------- tests/core/test_atomic_cxx.txt | 52 +++++++++++++++++----------------- 2 files changed, 43 insertions(+), 43 deletions(-) diff --git a/tests/core/test_atomic_cxx.cpp b/tests/core/test_atomic_cxx.cpp index e347c34a470bd..f78922a11e43d 100644 --- a/tests/core/test_atomic_cxx.cpp +++ b/tests/core/test_atomic_cxx.cpp @@ -8,7 +8,7 @@ #include #include -template void test(TYPE mask0, TYPE mask1, TYPE mask2) { +template void test(TYPE mask0, TYPE mask1, TYPE mask2) { typedef TYPE dog; const TYPE numMemoryOrders = 6; @@ -54,54 +54,54 @@ template void test(TYPE mask0, TYPE mask1, TYPE mask2) { atomicDog = 0; for (TYPE i = 0; i < numMemoryOrders; i++) { TYPE old = atomicDog.fetch_add(1, memoryOrder[i]); - printf("fetch_add %lld: old=%lld new=%lld\n", (long long)i, (long long)old, TYPE(atomicDog)); + printf("fetch_add %lld: old=%lld new=%lld\n", (long long)i, (long long)old, (long long)TYPE(atomicDog)); } // fetch_sub for (TYPE i = 0; i < numMemoryOrders; i++) { TYPE old = atomicDog.fetch_sub(1, memoryOrder[i]); - printf("fetch_sub %lld: old=%lld new=%lld\n", (long long)i, (long long)old, TYPE(atomicDog)); + printf("fetch_sub %lld: old=%lld new=%lld\n", (long long)i, (long long)old, (long long)TYPE(atomicDog)); } // fetch_and for (TYPE i = 0; i < numMemoryOrders; i++) { atomicDog.store(mask0, memoryOrder[i]); TYPE old = atomicDog.fetch_and((1<(0xFF, 0xF0, 0x0F); + test(0xFF, 0xF0, 0x0F); printf("\n16 bits\n\n"); - test(0xFFFF, 0xF0F0, 0x0F0F); + test(0xFFFF, 0xF0F0, 0x0F0F); printf("\n32 bits\n\n"); - test(0xFFFFFFFF, 0xF0F0F0F0, 0x0F0F0F0F); + test(0xFFFFFFFF, 0xF0F0F0F0, 0x0F0F0F0F); printf("\n64 bits\n\n"); - test(0xFFFFFFFFFFFFFFFF, 0xF0F0F0F0F0F0F0F0, 0x0F0F0F0F0F0F0F0F); + test(0xFFFFFFFFFFFFFFFF, 0xF0F0F0F0F0F0F0F0, 0x0F0F0F0F0F0F0F0F); // test atomic_flag (should also have memory_orders, but probably doesn't matter // to find the missing atomic functions) diff --git a/tests/core/test_atomic_cxx.txt b/tests/core/test_atomic_cxx.txt index e0beb49858f76..da437b570aa72 100644 --- a/tests/core/test_atomic_cxx.txt +++ b/tests/core/test_atomic_cxx.txt @@ -29,12 +29,12 @@ fetch_sub 2: old=4 new=3 fetch_sub 3: old=3 new=2 fetch_sub 4: old=2 new=1 fetch_sub 5: old=1 new=0 -fetch_and 0: old=ffffffffffffffff, new=1 -fetch_and 1: old=ffffffffffffffff, new=2 -fetch_and 2: old=ffffffffffffffff, new=4 -fetch_and 3: old=ffffffffffffffff, new=8 -fetch_and 4: old=ffffffffffffffff, new=10 -fetch_and 5: old=ffffffffffffffff, new=20 +fetch_and 0: old=ff, new=1 +fetch_and 1: old=ff, new=2 +fetch_and 2: old=ff, new=4 +fetch_and 3: old=ff, new=8 +fetch_and 4: old=ff, new=10 +fetch_and 5: old=ff, new=20 fetch_or 0: old=0, new=1 fetch_or 1: old=1, new=3 fetch_or 2: old=3, new=7 @@ -51,9 +51,9 @@ operator++: 1 operator--: 0 operator+=: 10 operator-=: 5 -operator|=: ffffffff -operator|=: fffffff0 -operator^=: ffffffff +operator|=: ff +operator&=: f0 +operator^=: ff 16 bits @@ -85,12 +85,12 @@ fetch_sub 2: old=4 new=3 fetch_sub 3: old=3 new=2 fetch_sub 4: old=2 new=1 fetch_sub 5: old=1 new=0 -fetch_and 0: old=ffffffffffffffff, new=1 -fetch_and 1: old=ffffffffffffffff, new=2 -fetch_and 2: old=ffffffffffffffff, new=4 -fetch_and 3: old=ffffffffffffffff, new=8 -fetch_and 4: old=ffffffffffffffff, new=10 -fetch_and 5: old=ffffffffffffffff, new=20 +fetch_and 0: old=ffff, new=1 +fetch_and 1: old=ffff, new=2 +fetch_and 2: old=ffff, new=4 +fetch_and 3: old=ffff, new=8 +fetch_and 4: old=ffff, new=10 +fetch_and 5: old=ffff, new=20 fetch_or 0: old=0, new=1 fetch_or 1: old=1, new=3 fetch_or 2: old=3, new=7 @@ -107,9 +107,9 @@ operator++: 1 operator--: 0 operator+=: 10 operator-=: 5 -operator|=: ffffffff -operator|=: fffff0f0 -operator^=: ffffffff +operator|=: ffff +operator&=: f0f0 +operator^=: ffff 32 bits @@ -141,12 +141,12 @@ fetch_sub 2: old=4 new=3 fetch_sub 3: old=3 new=2 fetch_sub 4: old=2 new=1 fetch_sub 5: old=1 new=0 -fetch_and 0: old=ffffffffffffffff, new=1 -fetch_and 1: old=ffffffffffffffff, new=2 -fetch_and 2: old=ffffffffffffffff, new=4 -fetch_and 3: old=ffffffffffffffff, new=8 -fetch_and 4: old=ffffffffffffffff, new=10 -fetch_and 5: old=ffffffffffffffff, new=20 +fetch_and 0: old=ffffffff, new=1 +fetch_and 1: old=ffffffff, new=2 +fetch_and 2: old=ffffffff, new=4 +fetch_and 3: old=ffffffff, new=8 +fetch_and 4: old=ffffffff, new=10 +fetch_and 5: old=ffffffff, new=20 fetch_or 0: old=0, new=1 fetch_or 1: old=1, new=3 fetch_or 2: old=3, new=7 @@ -164,7 +164,7 @@ operator--: 0 operator+=: 10 operator-=: 5 operator|=: ffffffff -operator|=: f0f0f0f0 +operator&=: f0f0f0f0 operator^=: ffffffff 64 bits @@ -220,7 +220,7 @@ operator--: 0 operator+=: 10 operator-=: 5 operator|=: ffffffffffffffff -operator|=: f0f0f0f0f0f0f0f0 +operator&=: f0f0f0f0f0f0f0f0 operator^=: ffffffffffffffff atomic_flag: false done. From 96a1da27484c4579e9e6e5e6ad1242865b54ee02 Mon Sep 17 00:00:00 2001 From: Jukka Jylanki Date: Mon, 14 Apr 2014 15:12:01 +0300 Subject: [PATCH 10/12] Allow setting SPIDERMONKEY_ENGINE=None in .emscripten to simplify test runner operation. --- tests/test_core.py | 2 +- tools/shared.py | 15 ++++++++------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/tests/test_core.py b/tests/test_core.py index a3712de244dee..1dc5066b3e8e1 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -2983,7 +2983,7 @@ def test_dlfcn_qsort(self): output_nicerizer=lambda x, err: x.replace('\n', '*'), post_build=self.dlfcn_post_build) - if Settings.ASM_JS and os.path.exists(SPIDERMONKEY_ENGINE[0]): + if Settings.ASM_JS and SPIDERMONKEY_ENGINE and os.path.exists(SPIDERMONKEY_ENGINE[0]): out = run_js('liblib.so', engine=SPIDERMONKEY_ENGINE, full_output=True, stderr=STDOUT) if 'asm' in out: self.validate_asmjs(out) diff --git a/tools/shared.py b/tools/shared.py index e912a7006089d..82bdd98b917d4 100644 --- a/tools/shared.py +++ b/tools/shared.py @@ -746,13 +746,14 @@ def include_directive(paths): # Engine tweaks try: - new_spidermonkey = listify(SPIDERMONKEY_ENGINE) - if 'gcparam' not in str(new_spidermonkey): - new_spidermonkey += ['-e', "gcparam('maxBytes', 1024*1024*1024);"] # Our very large files need lots of gc heap - if '-w' not in str(new_spidermonkey): - new_spidermonkey += ['-w'] - JS_ENGINES = map(lambda x: new_spidermonkey if x == SPIDERMONKEY_ENGINE else x, JS_ENGINES) - SPIDERMONKEY_ENGINE = new_spidermonkey + if SPIDERMONKEY_ENGINE: + new_spidermonkey = listify(SPIDERMONKEY_ENGINE) + if 'gcparam' not in str(new_spidermonkey): + new_spidermonkey += ['-e', "gcparam('maxBytes', 1024*1024*1024);"] # Our very large files need lots of gc heap + if '-w' not in str(new_spidermonkey): + new_spidermonkey += ['-w'] + JS_ENGINES = map(lambda x: new_spidermonkey if x == SPIDERMONKEY_ENGINE else x, JS_ENGINES) + SPIDERMONKEY_ENGINE = new_spidermonkey except NameError: pass From cfecdac66f1bde8da28adf34d782cfff6be9f83e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jukka=20Jyl=C3=A4nki?= Date: Mon, 14 Apr 2014 18:37:13 +0300 Subject: [PATCH 11/12] Store CMAKE_AR and CMAKE_RANLIB in CMake CACHE so that the values persist to user CMake toolchain files. Also CACHE the variable Emscripten, in the hope of that fixing the visibility issue with variable. Some users have reported that in their CMakeLists.txt files the variable EMSCRIPTEN is not always visible, even though in the Emscripten cmake unit tests it always works. Fixes #2288. Thanks mhenschel! --- cmake/Platform/Emscripten.cmake | 7 +++--- tests/cmake/target_html/CMakeLists.txt | 32 ++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/cmake/Platform/Emscripten.cmake b/cmake/Platform/Emscripten.cmake index 7d86c46775e22..f9d8c7737788a 100644 --- a/cmake/Platform/Emscripten.cmake +++ b/cmake/Platform/Emscripten.cmake @@ -66,11 +66,11 @@ if ("${CMAKE_CXX_COMPILER}" STREQUAL "") endif() if ("${CMAKE_AR}" STREQUAL "") - set(CMAKE_AR "${EMSCRIPTEN_ROOT_PATH}/emar${EMCC_SUFFIX}") + set(CMAKE_AR "${EMSCRIPTEN_ROOT_PATH}/emar${EMCC_SUFFIX}" CACHE FILEPATH "Emscripten ar") endif() if ("${CMAKE_RANLIB}" STREQUAL "") - set(CMAKE_RANLIB "${EMSCRIPTEN_ROOT_PATH}/emranlib${EMCC_SUFFIX}") + set(CMAKE_RANLIB "${EMSCRIPTEN_ROOT_PATH}/emranlib${EMCC_SUFFIX}" CACHE FILEPATH "Emscripten ranlib") endif() # Don't do compiler autodetection, since we are cross-compiling. @@ -113,8 +113,7 @@ set(CMAKE_CXX_ARCHIVE_APPEND "${CMAKE_AR} r ${CMAKE_START_TEMP_FILE} ${CMAKE_START_TEMP_FILE} ${CMAKE_END_TEMP_FILE}") # Set a global EMSCRIPTEN variable that can be used in client CMakeLists.txt to detect when building using Emscripten. -# There seems to be some kind of bug with CMake, so you might need to define this manually on the command line with "-DEMSCRIPTEN=1". -set(EMSCRIPTEN 1) +set(EMSCRIPTEN 1 CACHE BOOL "If true, we are targeting Emscripten output.") # We are cross-compiling, so unset the common CMake variables that represent the target platform. Leave UNIX define enabled, since Emscripten # mimics a Linux environment. diff --git a/tests/cmake/target_html/CMakeLists.txt b/tests/cmake/target_html/CMakeLists.txt index b5c694176a12c..ce26c5413a87b 100644 --- a/tests/cmake/target_html/CMakeLists.txt +++ b/tests/cmake/target_html/CMakeLists.txt @@ -10,6 +10,38 @@ else() # Either MinSizeRel, RelWithDebInfo or Release, all which run with optimi SET(linkFlags "-O2") endif() +if (NOT CMAKE_AR OR NOT EXISTS "${CMAKE_AR}") + message(FATAL_ERROR "CMAKE_AR='${CMAKE_AR}' does not exist for Emscripten toolchain!") +endif() + +if (NOT CMAKE_RANLIB OR NOT EXISTS "${CMAKE_RANLIB}") + message(FATAL_ERROR "CMAKE_RANLIB='${CMAKE_RANLIB}' does not exist for Emscripten toolchain!") +endif() + +if (NOT CMAKE_C_COMPILER OR NOT EXISTS "${CMAKE_C_COMPILER}") + message(FATAL_ERROR "CMAKE_C_COMPILER='${CMAKE_C_COMPILER}' does not exist for Emscripten toolchain!") +endif() + +if (NOT CMAKE_CXX_COMPILER OR NOT EXISTS "${CMAKE_CXX_COMPILER}") + message(FATAL_ERROR "CMAKE_CXX_COMPILER='${CMAKE_CXX_COMPILER}' does not exist for Emscripten toolchain!") +endif() + +if (WIN32) + message(FATAL_ERROR "WIN32 should not be defined when cross-compiling!") +endif() + +if (APPLE) + message(FATAL_ERROR "APPLE should not be defined when cross-compiling!") +endif() + +if (NOT EMSCRIPTEN) + message(FATAL_ERROR "EMSCRIPTEN should be defined when cross-compiling!") +endif() + +if (NOT CMAKE_C_SIZEOF_DATA_PTR) + message(FATAL_ERROR "CMAKE_C_SIZEOF_DATA_PTR was not defined!") +endif() + SET(CMAKE_EXECUTABLE_SUFFIX ".html") add_executable(hello_world_gles ${sourceFiles}) From 153e0f6426ff908166abdf07be7f91601fbed07f Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 14 Apr 2014 15:37:17 -0700 Subject: [PATCH 12/12] 1.15.1 --- emscripten-version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/emscripten-version.txt b/emscripten-version.txt index 226e95b7c3c48..db39b14cd04c6 100644 --- a/emscripten-version.txt +++ b/emscripten-version.txt @@ -1,2 +1,2 @@ -1.15.0 +1.15.1