Browse Source

Removed Remotery.

Branimir Karadžić 8 years ago
parent
commit
f0971eda83
42 changed files with 5 additions and 13148 deletions
  1. 0 175
      3rdparty/remotery/LICENSE
  2. 0 6697
      3rdparty/remotery/lib/Remotery.c
  3. 0 620
      3rdparty/remotery/lib/Remotery.h
  4. 0 49
      3rdparty/remotery/lib/RemoteryMetal.mm
  5. 0 216
      3rdparty/remotery/readme.md
  6. 0 45
      3rdparty/remotery/sample/sample.c
  7. BIN
      3rdparty/remotery/screenshot.png
  8. 0 194
      3rdparty/remotery/vis/Code/Console.js
  9. 0 47
      3rdparty/remotery/vis/Code/DataViewReader.js
  10. 0 61
      3rdparty/remotery/vis/Code/PixelTimeRange.js
  11. 0 330
      3rdparty/remotery/vis/Code/Remotery.js
  12. 0 178
      3rdparty/remotery/vis/Code/SampleWindow.js
  13. 0 28
      3rdparty/remotery/vis/Code/ThreadFrame.js
  14. 0 376
      3rdparty/remotery/vis/Code/TimelineRow.js
  15. 0 270
      3rdparty/remotery/vis/Code/TimelineWindow.js
  16. 0 59
      3rdparty/remotery/vis/Code/TitleWindow.js
  17. 0 137
      3rdparty/remotery/vis/Code/WebSocketConnection.js
  18. 0 212
      3rdparty/remotery/vis/Styles/Remotery.css
  19. 0 65
      3rdparty/remotery/vis/extern/BrowserLib/Core/Code/Animation.js
  20. 0 92
      3rdparty/remotery/vis/extern/BrowserLib/Core/Code/Bind.js
  21. 0 204
      3rdparty/remotery/vis/extern/BrowserLib/Core/Code/Convert.js
  22. 0 20
      3rdparty/remotery/vis/extern/BrowserLib/Core/Code/Core.js
  23. 0 499
      3rdparty/remotery/vis/extern/BrowserLib/Core/Code/DOM.js
  24. 0 149
      3rdparty/remotery/vis/extern/BrowserLib/Core/Code/Keyboard.js
  25. 0 26
      3rdparty/remotery/vis/extern/BrowserLib/Core/Code/LocalStore.js
  26. 0 83
      3rdparty/remotery/vis/extern/BrowserLib/Core/Code/Mouse.js
  27. 0 68
      3rdparty/remotery/vis/extern/BrowserLib/Core/Code/MurmurHash3.js
  28. 0 131
      3rdparty/remotery/vis/extern/BrowserLib/WindowManager/Code/Button.js
  29. 0 237
      3rdparty/remotery/vis/extern/BrowserLib/WindowManager/Code/ComboBox.js
  30. 0 34
      3rdparty/remotery/vis/extern/BrowserLib/WindowManager/Code/Container.js
  31. 0 119
      3rdparty/remotery/vis/extern/BrowserLib/WindowManager/Code/EditBox.js
  32. 0 252
      3rdparty/remotery/vis/extern/BrowserLib/WindowManager/Code/Grid.js
  33. 0 31
      3rdparty/remotery/vis/extern/BrowserLib/WindowManager/Code/Label.js
  34. 0 352
      3rdparty/remotery/vis/extern/BrowserLib/WindowManager/Code/Treeview.js
  35. 0 109
      3rdparty/remotery/vis/extern/BrowserLib/WindowManager/Code/TreeviewItem.js
  36. 0 243
      3rdparty/remotery/vis/extern/BrowserLib/WindowManager/Code/Window.js
  37. 0 54
      3rdparty/remotery/vis/extern/BrowserLib/WindowManager/Code/WindowManager.js
  38. 0 546
      3rdparty/remotery/vis/extern/BrowserLib/WindowManager/Styles/WindowManager.css
  39. 0 55
      3rdparty/remotery/vis/index.html
  40. 0 49
      examples/common/entry/entry.cpp
  41. 0 12
      src/bgfx.cpp
  42. 5 24
      src/bgfx_p.h

+ 0 - 175
3rdparty/remotery/LICENSE

@@ -1,175 +0,0 @@
-
-                                 Apache License
-                           Version 2.0, January 2004
-                        http://www.apache.org/licenses/
-
-   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-   1. Definitions.
-
-      "License" shall mean the terms and conditions for use, reproduction,
-      and distribution as defined by Sections 1 through 9 of this document.
-
-      "Licensor" shall mean the copyright owner or entity authorized by
-      the copyright owner that is granting the License.
-
-      "Legal Entity" shall mean the union of the acting entity and all
-      other entities that control, are controlled by, or are under common
-      control with that entity. For the purposes of this definition,
-      "control" means (i) the power, direct or indirect, to cause the
-      direction or management of such entity, whether by contract or
-      otherwise, or (ii) ownership of fifty percent (50%) or more of the
-      outstanding shares, or (iii) beneficial ownership of such entity.
-
-      "You" (or "Your") shall mean an individual or Legal Entity
-      exercising permissions granted by this License.
-
-      "Source" form shall mean the preferred form for making modifications,
-      including but not limited to software source code, documentation
-      source, and configuration files.
-
-      "Object" form shall mean any form resulting from mechanical
-      transformation or translation of a Source form, including but
-      not limited to compiled object code, generated documentation,
-      and conversions to other media types.
-
-      "Work" shall mean the work of authorship, whether in Source or
-      Object form, made available under the License, as indicated by a
-      copyright notice that is included in or attached to the work
-      (an example is provided in the Appendix below).
-
-      "Derivative Works" shall mean any work, whether in Source or Object
-      form, that is based on (or derived from) the Work and for which the
-      editorial revisions, annotations, elaborations, or other modifications
-      represent, as a whole, an original work of authorship. For the purposes
-      of this License, Derivative Works shall not include works that remain
-      separable from, or merely link (or bind by name) to the interfaces of,
-      the Work and Derivative Works thereof.
-
-      "Contribution" shall mean any work of authorship, including
-      the original version of the Work and any modifications or additions
-      to that Work or Derivative Works thereof, that is intentionally
-      submitted to Licensor for inclusion in the Work by the copyright owner
-      or by an individual or Legal Entity authorized to submit on behalf of
-      the copyright owner. For the purposes of this definition, "submitted"
-      means any form of electronic, verbal, or written communication sent
-      to the Licensor or its representatives, including but not limited to
-      communication on electronic mailing lists, source code control systems,
-      and issue tracking systems that are managed by, or on behalf of, the
-      Licensor for the purpose of discussing and improving the Work, but
-      excluding communication that is conspicuously marked or otherwise
-      designated in writing by the copyright owner as "Not a Contribution."
-
-      "Contributor" shall mean Licensor and any individual or Legal Entity
-      on behalf of whom a Contribution has been received by Licensor and
-      subsequently incorporated within the Work.
-
-   2. Grant of Copyright License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      copyright license to reproduce, prepare Derivative Works of,
-      publicly display, publicly perform, sublicense, and distribute the
-      Work and such Derivative Works in Source or Object form.
-
-   3. Grant of Patent License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      (except as stated in this section) patent license to make, have made,
-      use, offer to sell, sell, import, and otherwise transfer the Work,
-      where such license applies only to those patent claims licensable
-      by such Contributor that are necessarily infringed by their
-      Contribution(s) alone or by combination of their Contribution(s)
-      with the Work to which such Contribution(s) was submitted. If You
-      institute patent litigation against any entity (including a
-      cross-claim or counterclaim in a lawsuit) alleging that the Work
-      or a Contribution incorporated within the Work constitutes direct
-      or contributory patent infringement, then any patent licenses
-      granted to You under this License for that Work shall terminate
-      as of the date such litigation is filed.
-
-   4. Redistribution. You may reproduce and distribute copies of the
-      Work or Derivative Works thereof in any medium, with or without
-      modifications, and in Source or Object form, provided that You
-      meet the following conditions:
-
-      (a) You must give any other recipients of the Work or
-          Derivative Works a copy of this License; and
-
-      (b) You must cause any modified files to carry prominent notices
-          stating that You changed the files; and
-
-      (c) You must retain, in the Source form of any Derivative Works
-          that You distribute, all copyright, patent, trademark, and
-          attribution notices from the Source form of the Work,
-          excluding those notices that do not pertain to any part of
-          the Derivative Works; and
-
-      (d) If the Work includes a "NOTICE" text file as part of its
-          distribution, then any Derivative Works that You distribute must
-          include a readable copy of the attribution notices contained
-          within such NOTICE file, excluding those notices that do not
-          pertain to any part of the Derivative Works, in at least one
-          of the following places: within a NOTICE text file distributed
-          as part of the Derivative Works; within the Source form or
-          documentation, if provided along with the Derivative Works; or,
-          within a display generated by the Derivative Works, if and
-          wherever such third-party notices normally appear. The contents
-          of the NOTICE file are for informational purposes only and
-          do not modify the License. You may add Your own attribution
-          notices within Derivative Works that You distribute, alongside
-          or as an addendum to the NOTICE text from the Work, provided
-          that such additional attribution notices cannot be construed
-          as modifying the License.
-
-      You may add Your own copyright statement to Your modifications and
-      may provide additional or different license terms and conditions
-      for use, reproduction, or distribution of Your modifications, or
-      for any such Derivative Works as a whole, provided Your use,
-      reproduction, and distribution of the Work otherwise complies with
-      the conditions stated in this License.
-
-   5. Submission of Contributions. Unless You explicitly state otherwise,
-      any Contribution intentionally submitted for inclusion in the Work
-      by You to the Licensor shall be under the terms and conditions of
-      this License, without any additional terms or conditions.
-      Notwithstanding the above, nothing herein shall supersede or modify
-      the terms of any separate license agreement you may have executed
-      with Licensor regarding such Contributions.
-
-   6. Trademarks. This License does not grant permission to use the trade
-      names, trademarks, service marks, or product names of the Licensor,
-      except as required for reasonable and customary use in describing the
-      origin of the Work and reproducing the content of the NOTICE file.
-
-   7. Disclaimer of Warranty. Unless required by applicable law or
-      agreed to in writing, Licensor provides the Work (and each
-      Contributor provides its Contributions) on an "AS IS" BASIS,
-      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-      implied, including, without limitation, any warranties or conditions
-      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
-      PARTICULAR PURPOSE. You are solely responsible for determining the
-      appropriateness of using or redistributing the Work and assume any
-      risks associated with Your exercise of permissions under this License.
-
-   8. Limitation of Liability. In no event and under no legal theory,
-      whether in tort (including negligence), contract, or otherwise,
-      unless required by applicable law (such as deliberate and grossly
-      negligent acts) or agreed to in writing, shall any Contributor be
-      liable to You for damages, including any direct, indirect, special,
-      incidental, or consequential damages of any character arising as a
-      result of this License or out of the use or inability to use the
-      Work (including but not limited to damages for loss of goodwill,
-      work stoppage, computer failure or malfunction, or any and all
-      other commercial damages or losses), even if such Contributor
-      has been advised of the possibility of such damages.
-
-   9. Accepting Warranty or Additional Liability. While redistributing
-      the Work or Derivative Works thereof, You may choose to offer,
-      and charge a fee for, acceptance of support, warranty, indemnity,
-      or other liability obligations and/or rights consistent with this
-      License. However, in accepting such obligations, You may act only
-      on Your own behalf and on Your sole responsibility, not on behalf
-      of any other Contributor, and only if You agree to indemnify,
-      defend, and hold each Contributor harmless for any liability
-      incurred by, or claims asserted against, such Contributor by reason
-      of your accepting any such warranty or additional liability.

+ 0 - 6697
3rdparty/remotery/lib/Remotery.c

@@ -1,6697 +0,0 @@
-//
-// Copyright 2014-2017 Celtoys Ltd
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-/*
-@Contents:
-
-    @DEPS:          External Dependencies
-    @TIMERS:        Platform-specific timers
-    @TLS:           Thread-Local Storage
-    @ATOMIC:        Atomic Operations
-    @VMBUFFER:      Mirror Buffer using Virtual Memory for auto-wrap
-    @NEW:           New/Delete operators with error values for simplifying object create/destroy
-    @THREADS:       Threads
-    @SAFEC:         Safe C Library excerpts
-    @OBJALLOC:      Reusable Object Allocator
-    @DYNBUF:        Dynamic Buffer
-    @HASHTABLE:     Integer pair hash map for inserts/finds. No removes for added simplicity.
-    @STRINGTABLE:	Map from string hash to string offset in local buffer
-    @SOCKETS:       Sockets TCP/IP Wrapper
-    @SHA1:          SHA-1 Cryptographic Hash Function
-    @BASE64:        Base-64 encoder
-    @MURMURHASH:    Murmur-Hash 3
-    @WEBSOCKETS:    WebSockets
-    @MESSAGEQ:      Multiple producer, single consumer message queue
-    @NETWORK:       Network Server
-    @SAMPLE:        Base Sample Description (CPU by default)
-    @SAMPLETREE:    A tree of samples with their allocator
-    @TSAMPLER:      Per-Thread Sampler
-    @REMOTERY:      Remotery
-    @CUDA:          CUDA event sampling
-    @D3D11:         Direct3D 11 event sampling
-    @OPENGL:        OpenGL event sampling
-    @METAL:         Metal event sampling
-*/
-
-#define RMT_IMPL
-#include "Remotery.h"
-
-
-#ifdef RMT_PLATFORM_WINDOWS
-  #pragma comment(lib, "ws2_32.lib")
-#endif
-
-
-#if RMT_ENABLED
-
-
-// Global settings
-static rmtSettings g_Settings;
-static rmtBool g_SettingsInitialized = RMT_FALSE;
-
-
-/*
-------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------
-   @DEPS: External Dependencies
-------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------
-*/
-
-
-
-//
-// Required CRT dependencies
-//
-#if RMT_USE_TINYCRT
-
-    #include <TinyCRT/TinyCRT.h>
-    #include <TinyCRT/TinyWinsock.h>
-    #include <Memory/Memory.h>
-
-    #define CreateFileMapping CreateFileMappingA
-
-#else
-
-    #ifdef RMT_PLATFORM_MACOS
-        #include <mach/mach_time.h>
-        #include <mach/vm_map.h>
-        #include <mach/mach.h>
-        #include <sys/time.h>
-    #else
-        #include <malloc.h>
-    #endif
-
-    #include <assert.h>
-
-    #ifdef RMT_PLATFORM_WINDOWS
-        #include <winsock2.h>
-        #ifndef __MINGW32__
-            #include <intrin.h>
-        #endif
-        #undef min
-        #undef max
-    #endif
-
-    #ifdef RMT_PLATFORM_LINUX
-        #include <time.h>
-        #include <sys/prctl.h>
-    #endif
-
-    #if defined(RMT_PLATFORM_POSIX)
-        #include <stdlib.h>
-        #include <pthread.h>
-        #include <unistd.h>
-        #include <string.h>
-        #include <sys/socket.h>
-        #include <sys/mman.h>
-        #include <netinet/in.h>
-        #include <fcntl.h>
-        #include <errno.h>
-        #include <dlfcn.h>
-    #endif
-
-    #ifdef __MINGW32__
-        #include <pthread.h>
-    #endif
-
-#endif
-
-#if 0 //def _MSC_VER
-    #define RMT_UNREFERENCED_PARAMETER(i) assert(i == 0 || i != 0);	// To fool warning C4100 on warning level 4
-#else
-    #define RMT_UNREFERENCED_PARAMETER(i) (void)(1 ? (void)0 : ((void)i))
-#endif
-
-
-#if RMT_USE_CUDA
-    #include <cuda.h>
-#endif
-
-
-
-rmtU8 minU8(rmtU8 a, rmtU8 b)
-{
-    return a < b ? a : b;
-}
-rmtS64 minS64(rmtS64 a, rmtS64 b)
-{
-    return a < b ? a : b;
-}
-
-
-rmtU8 maxU8(rmtU8 a, rmtU8 b)
-{
-    return a > b ? a : b;
-}
-rmtS64 maxS64(rmtS64 a, rmtS64 b)
-{
-    return a > b ? a : b;
-}
-
-
-// Memory management functions
-static void* rmtMalloc( rmtU32 size )
-{
-    return g_Settings.malloc( g_Settings.mm_context, size );
-}
-
-static void* rmtRealloc( void* ptr, rmtU32 size)
-{
-    return g_Settings.realloc( g_Settings.mm_context, ptr, size );
-}
-
-static void rmtFree( void* ptr )
-{
-    g_Settings.free( g_Settings.mm_context, ptr );
-}
-
-#if RMT_USE_OPENGL
-// DLL/Shared Library functions
-static void* rmtLoadLibrary(const char* path)
-{
-    #if defined(RMT_PLATFORM_WINDOWS)
-        return (void*)LoadLibraryA(path);
-    #elif defined(RMT_PLATFORM_POSIX)
-        return dlopen(path, RTLD_LOCAL | RTLD_LAZY);
-    #else
-        return NULL;
-    #endif
-}
-
-static void rmtFreeLibrary(void* handle)
-{
-    #if defined(RMT_PLATFORM_WINDOWS)
-        FreeLibrary((HMODULE)handle);
-    #elif defined(RMT_PLATFORM_POSIX)
-        dlclose(handle);
-    #endif
-}
-
-static void* rmtGetProcAddress(void* handle, const char* symbol)
-{
-    #if defined(RMT_PLATFORM_WINDOWS)
-        #ifdef _MSC_VER
-            #pragma warning(push)
-            #pragma warning(disable:4152) // C4152: nonstandard extension, function/data pointer conversion in expression
-        #endif
-        return GetProcAddress((HMODULE)handle, (LPCSTR)symbol);
-        #ifdef _MSC_VER
-            #pragma warning(pop)
-        #endif
-    #elif defined(RMT_PLATFORM_POSIX)
-        return dlsym(handle, symbol);
-    #else
-        return NULL;
-    #endif
-}
-#endif
-
-/*
-------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------
-   @TIMERS: Platform-specific timers
-------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------
-*/
-
-
-
-//
-// Get millisecond timer value that has only one guarantee: multiple calls are consistently comparable.
-// On some platforms, even though this returns milliseconds, the timer may be far less accurate.
-//
-static rmtU32 msTimer_Get()
-{
-    #ifdef RMT_PLATFORM_WINDOWS
-        return (rmtU32)GetTickCount();
-    #else
-        clock_t time = clock();
-        rmtU32 msTime = (rmtU32) (time / (CLOCKS_PER_SEC / 1000));
-        return msTime;
-    #endif
-}
-
-
-//
-// Micro-second accuracy high performance counter
-//
-#ifndef RMT_PLATFORM_WINDOWS
-    typedef rmtU64 LARGE_INTEGER;
-#endif
-typedef struct
-{
-    LARGE_INTEGER counter_start;
-    double counter_scale;
-} usTimer;
-
-
-static void usTimer_Init(usTimer* timer)
-{
-    #if defined(RMT_PLATFORM_WINDOWS)
-        LARGE_INTEGER performance_frequency;
-
-        assert(timer != NULL);
-
-        // Calculate the scale from performance counter to microseconds
-        QueryPerformanceFrequency(&performance_frequency);
-        timer->counter_scale = 1000000.0 / performance_frequency.QuadPart;
-
-        // Record the offset for each read of the counter
-        QueryPerformanceCounter(&timer->counter_start);
-
-    #elif defined(RMT_PLATFORM_MACOS)
-
-        mach_timebase_info_data_t nsScale;
-        mach_timebase_info( &nsScale );
-        const double ns_per_us = 1.0e3;
-        timer->counter_scale = (double)(nsScale.numer) / ((double)nsScale.denom * ns_per_us);
-
-        timer->counter_start = mach_absolute_time();
-
-    #elif defined(RMT_PLATFORM_LINUX)
-
-        struct timespec tv;
-        clock_gettime(CLOCK_REALTIME, &tv);
-        timer->counter_start = (rmtU64)(tv.tv_sec * (rmtU64)1000000) + (rmtU64)(tv.tv_nsec * 0.001);
-
-    #endif
-}
-
-
-static rmtU64 usTimer_Get(usTimer* timer)
-{
-    #if defined(RMT_PLATFORM_WINDOWS)
-        LARGE_INTEGER performance_count;
-
-        assert(timer != NULL);
-
-        // Read counter and convert to microseconds
-        QueryPerformanceCounter(&performance_count);
-        return (rmtU64)((performance_count.QuadPart - timer->counter_start.QuadPart) * timer->counter_scale);
-
-    #elif defined(RMT_PLATFORM_MACOS)
-
-        rmtU64 curr_time = mach_absolute_time();
-        return (rmtU64)((curr_time - timer->counter_start) * timer->counter_scale);
-
-    #elif defined(RMT_PLATFORM_LINUX)
-
-        struct timespec tv;
-        clock_gettime(CLOCK_REALTIME, &tv);
-        return  ((rmtU64)(tv.tv_sec * (rmtU64)1000000) + (rmtU64)(tv.tv_nsec * 0.001)) - timer->counter_start;
-
-    #endif
-}
-
-
-static void msSleep(rmtU32 time_ms)
-{
-    #ifdef RMT_PLATFORM_WINDOWS
-        Sleep(time_ms);
-    #elif defined(RMT_PLATFORM_POSIX)
-        usleep(time_ms * 1000);
-    #endif
-}
-
-
-
-/*
-------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------
-   @TLS: Thread-Local Storage
-------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------
-*/
-
-
-
-#define TLS_INVALID_HANDLE 0xFFFFFFFF
-
-#if defined(RMT_PLATFORM_WINDOWS)
-    typedef rmtU32 rmtTLS;
-#else
-    typedef pthread_key_t rmtTLS;
-#endif
-
-static rmtError tlsAlloc(rmtTLS* handle)
-{
-    assert(handle != NULL);
-
-#if defined(RMT_PLATFORM_WINDOWS)
-
-    *handle = (rmtTLS)TlsAlloc();
-    if (*handle == TLS_OUT_OF_INDEXES)
-    {
-        *handle = TLS_INVALID_HANDLE;
-        return RMT_ERROR_TLS_ALLOC_FAIL;
-    }
-
-#elif defined(RMT_PLATFORM_POSIX)
-
-    if (pthread_key_create(handle, NULL) != 0)
-    {
-        *handle = TLS_INVALID_HANDLE;
-        return RMT_ERROR_TLS_ALLOC_FAIL;
-    }
-
-#endif
-
-    return RMT_ERROR_NONE;
-}
-
-
-static void tlsFree(rmtTLS handle)
-{
-    assert(handle != TLS_INVALID_HANDLE);
-
-#if defined(RMT_PLATFORM_WINDOWS)
-
-    TlsFree(handle);
-
-#elif defined(RMT_PLATFORM_POSIX)
-
-    pthread_key_delete((pthread_key_t)handle);
-
-#endif
-}
-
-
-static void tlsSet(rmtTLS handle, void* value)
-{
-    assert(handle != TLS_INVALID_HANDLE);
-
-#if defined(RMT_PLATFORM_WINDOWS)
-
-    TlsSetValue(handle, value);
-
-#elif defined(RMT_PLATFORM_POSIX)
-
-    pthread_setspecific((pthread_key_t)handle, value);
-
-#endif
-}
-
-
-static void* tlsGet(rmtTLS handle)
-{
-    assert(handle != TLS_INVALID_HANDLE);
-
-#if defined(RMT_PLATFORM_WINDOWS)
-
-    return TlsGetValue(handle);
-
-#elif defined(RMT_PLATFORM_POSIX)
-
-    return pthread_getspecific((pthread_key_t)handle);
-
-#endif
-}
-
-
-
-/*
-------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------
-   @ATOMIC: Atomic Operations
-------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------
-*/
-
-
-static rmtBool AtomicCompareAndSwap(rmtU32 volatile* val, long old_val, long new_val)
-{
-    #if defined(RMT_PLATFORM_WINDOWS) && !defined(__MINGW32__)
-        return _InterlockedCompareExchange((long volatile*)val, new_val, old_val) == old_val ? RMT_TRUE : RMT_FALSE;
-    #elif defined(RMT_PLATFORM_POSIX) || defined(__MINGW32__)
-        return __sync_bool_compare_and_swap(val, old_val, new_val) ? RMT_TRUE : RMT_FALSE;
-    #endif
-}
-
-
-static rmtBool AtomicCompareAndSwapPointer(long* volatile* ptr, long* old_ptr, long* new_ptr)
-{
-    #if defined(RMT_PLATFORM_WINDOWS) && !defined(__MINGW32__)
-        #ifdef _WIN64
-            return _InterlockedCompareExchange64((__int64 volatile*)ptr, (__int64)new_ptr, (__int64)old_ptr) == (__int64)old_ptr ? RMT_TRUE : RMT_FALSE;
-        #else
-            return _InterlockedCompareExchange((long volatile*)ptr, (long)new_ptr, (long)old_ptr) == (long)old_ptr ? RMT_TRUE : RMT_FALSE;
-        #endif
-    #elif defined(RMT_PLATFORM_POSIX) || defined(__MINGW32__)
-        return __sync_bool_compare_and_swap(ptr, old_ptr, new_ptr) ? RMT_TRUE : RMT_FALSE;
-    #endif
-}
-
-
-//
-// NOTE: Does not guarantee a memory barrier
-// TODO: Make sure all platforms don't insert a memory barrier as this is only for stats
-//       Alternatively, add strong/weak memory order equivalents
-//
-static rmtS32 AtomicAdd(rmtS32 volatile* value, rmtS32 add)
-{
-    #if defined(RMT_PLATFORM_WINDOWS) && !defined(__MINGW32__)
-        return _InterlockedExchangeAdd((long volatile*)value, (long)add);
-    #elif defined(RMT_PLATFORM_POSIX) || defined(__MINGW32__)
-        return __sync_fetch_and_add(value, add);
-    #endif
-}
-
-
-static void AtomicSub(rmtS32 volatile* value, rmtS32 sub)
-{
-    // Not all platforms have an implementation so just negate and add
-    AtomicAdd(value, -sub);
-}
-
-
-// Compiler write fences (windows implementation)
-static void WriteFence()
-{
-#if defined(RMT_PLATFORM_WINDOWS) && !defined(__MINGW32__)
-    _WriteBarrier();
-#elif defined (__clang__)
-	__asm__ volatile("" : : : "memory");
-#else
-    asm volatile ("" : : : "memory");
-#endif
-}
-
-
-
-/*
-------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------
-   @NEW: New/Delete operators with error values for simplifying object create/destroy
-------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------
-*/
-
-
-
-// Ensures the pointer is non-NULL, calls the destructor, frees memory and sets the pointer to NULL
-#define Delete(type, obj)           \
-    if (obj != NULL)                \
-    {                               \
-        type##_Destructor(obj);     \
-        rmtFree(obj);               \
-        obj = NULL;                 \
-    }
-
-
-// New is implemented in terms of two begin/end macros
-// New will allocate enough space for the object and call the constructor
-// If allocation fails the constructor won't be called
-// If the constructor fails, the destructor is called and memory is released
-// NOTE: Use of sizeof() requires that the type be defined at the point of call
-// This is a disadvantage over requiring only a custom Create function
-#define BeginNew(type, obj)                 \
-    {                                       \
-        obj = (type*)rmtMalloc(sizeof(type));  \
-        if (obj == NULL)                    \
-        {                                   \
-            error = RMT_ERROR_MALLOC_FAIL;  \
-        }                                   \
-        else                                \
-        {                                   \
-
-
-#define EndNew(type, obj)                   \
-            if (error != RMT_ERROR_NONE)    \
-                Delete(type, obj);          \
-        }                                   \
-    }
-
-
-// Specialisations for New with varying constructor parameter counts
-#define New_0(type, obj)    \
-    BeginNew(type, obj); error = type##_Constructor(obj); EndNew(type, obj)
-#define New_1(type, obj, a0)    \
-    BeginNew(type, obj); error = type##_Constructor(obj, a0); EndNew(type, obj)
-#define New_2(type, obj, a0, a1)    \
-    BeginNew(type, obj); error = type##_Constructor(obj, a0, a1); EndNew(type, obj)
-#define New_3(type, obj, a0, a1, a2)    \
-    BeginNew(type, obj); error = type##_Constructor(obj, a0, a1, a2); EndNew(type, obj)
-
-
-
-/*
-------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------
-   @VMBUFFER: Mirror Buffer using Virtual Memory for auto-wrap
-------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------
-*/
-
-
-
-typedef struct VirtualMirrorBuffer
-{
-    // Page-rounded size of the buffer without mirroring
-    rmtU32 size;
-
-    // Pointer to the first part of the mirror
-    // The second part comes directly after at ptr+size bytes
-    rmtU8* ptr;
-
-#ifdef RMT_PLATFORM_WINDOWS
-    HANDLE file_map_handle;
-#endif
-
-} VirtualMirrorBuffer;
-
-
-#ifdef __ANDROID__
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/ioctl.h>
-#include <linux/ashmem.h>
-#include <fcntl.h>
-#include <string.h>
-#define ASHMEM_DEVICE   "/dev/ashmem"
-
-/*
- * ashmem_create_region - creates a new ashmem region and returns the file
- * descriptor, or <0 on error
- *
- * `name' is an optional label to give the region (visible in /proc/pid/maps)
- * `size' is the size of the region, in page-aligned bytes
- */
-int ashmem_create_region(const char *name, size_t size)
-{
-        int fd, ret;
-
-        fd = open(ASHMEM_DEVICE, O_RDWR);
-        if (fd < 0)
-                return fd;
-
-        if (name) {
-                char buf[ASHMEM_NAME_LEN] = {0};
-
-                strncpy(buf, name, sizeof(buf));
-                buf[sizeof(buf)-1] = 0;
-                ret = ioctl(fd, ASHMEM_SET_NAME, buf);
-                if (ret < 0)
-                        goto error;
-        }
-
-        ret = ioctl(fd, ASHMEM_SET_SIZE, size);
-        if (ret < 0)
-                goto error;
-
-        return fd;
-
-error:
-        close(fd);
-        return ret;
-}
-#endif // __ANDROID__
-
-
-static rmtError VirtualMirrorBuffer_Constructor(VirtualMirrorBuffer* buffer, rmtU32 size, int nb_attempts)
-{
-    static const rmtU32 k_64 = 64 * 1024;
-    RMT_UNREFERENCED_PARAMETER(nb_attempts);
-
-#ifdef RMT_PLATFORM_LINUX
-    char path[] = "/dev/shm/ring-buffer-XXXXXX";
-    int file_descriptor;
-#endif
-
-    // Round up to page-granulation; the nearest 64k boundary for now
-    size = (size + k_64 - 1) / k_64 * k_64;
-
-    // Set defaults
-    buffer->size = size;
-    buffer->ptr = NULL;
-#ifdef RMT_PLATFORM_WINDOWS
-    buffer->file_map_handle = INVALID_HANDLE_VALUE;
-#endif
-
-#ifdef RMT_PLATFORM_WINDOWS
-
-    // Windows version based on https://gist.github.com/rygorous/3158316
-
-    while (nb_attempts-- > 0)
-    {
-        rmtU8* desired_addr;
-
-        // Create a file mapping for pointing to its physical address with multiple virtual pages
-        buffer->file_map_handle = CreateFileMapping(
-            INVALID_HANDLE_VALUE,
-            0,
-            PAGE_READWRITE,
-            0,
-            size,
-            0);
-        if (buffer->file_map_handle == NULL)
-            break;
-
-        // Reserve two contiguous pages of virtual memory
-        desired_addr = (rmtU8*)VirtualAlloc(0, size * 2, MEM_RESERVE, PAGE_NOACCESS);
-        if (desired_addr == NULL)
-            break;
-
-        // Release the range immediately but retain the address for the next sequence of code to
-        // try and map to it. In the mean-time some other OS thread may come along and allocate this
-        // address range from underneath us so multiple attempts need to be made.
-        VirtualFree(desired_addr, 0, MEM_RELEASE);
-
-        // Immediately try to point both pages at the file mapping
-        if (MapViewOfFileEx(buffer->file_map_handle, FILE_MAP_ALL_ACCESS, 0, 0, size, desired_addr) == desired_addr &&
-            MapViewOfFileEx(buffer->file_map_handle, FILE_MAP_ALL_ACCESS, 0, 0, size, desired_addr + size) == desired_addr + size)
-        {
-            buffer->ptr = desired_addr;
-            break;
-        }
-
-        // Failed to map the virtual pages; cleanup and try again
-        CloseHandle(buffer->file_map_handle);
-        buffer->file_map_handle = NULL;
-    }
-
-#endif
-
-#ifdef RMT_PLATFORM_MACOS
-
-    //
-    // Mac version based on https://github.com/mikeash/MAMirroredQueue
-    //
-    // Copyright (c) 2010, Michael Ash
-    // All rights reserved.
-    //
-    // Redistribution and use in source and binary forms, with or without modification, are permitted provided that
-    // the following conditions are met:
-    //
-    // Redistributions of source code must retain the above copyright notice, this list of conditions and the following
-    // disclaimer.
-    //
-    // Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
-    // following disclaimer in the documentation and/or other materials provided with the distribution.
-    // Neither the name of Michael Ash nor the names of its contributors may be used to endorse or promote products
-    // derived from this software without specific prior written permission.
-    //
-    // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
-    // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-    // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-    // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
-    // GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-    // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-    // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-    //
-
-    while (nb_attempts-- > 0)
-    {
-        vm_prot_t cur_prot, max_prot;
-        kern_return_t mach_error;
-        rmtU8* ptr = NULL;
-        rmtU8* target = NULL;
-
-        // Allocate 2 contiguous pages of virtual memory
-        if (vm_allocate(mach_task_self(), (vm_address_t*)&ptr, size * 2, VM_FLAGS_ANYWHERE) != KERN_SUCCESS)
-            break;
-
-        // Try to deallocate the last page, leaving its virtual memory address free
-        target = ptr + size;
-        if (vm_deallocate(mach_task_self(), (vm_address_t)target, size) != KERN_SUCCESS)
-        {
-            vm_deallocate(mach_task_self(), (vm_address_t)ptr, size * 2);
-            break;
-        }
-
-        // Attempt to remap the page just deallocated to the buffer again
-        mach_error = vm_remap(
-            mach_task_self(),
-            (vm_address_t*)&target,
-            size,
-            0,  // mask
-            0,  // anywhere
-            mach_task_self(),
-            (vm_address_t)ptr,
-            0,  //copy
-            &cur_prot,
-            &max_prot,
-            VM_INHERIT_COPY);
-
-        if (mach_error == KERN_NO_SPACE)
-        {
-            // Failed on this pass, cleanup and make another attempt
-            if (vm_deallocate(mach_task_self(), (vm_address_t)ptr, size) != KERN_SUCCESS)
-                break;
-        }
-
-        else if (mach_error == KERN_SUCCESS)
-        {
-            // Leave the loop on success
-            buffer->ptr = ptr;
-            break;
-        }
-
-        else
-        {
-            // Unknown error, can't recover
-            vm_deallocate(mach_task_self(), (vm_address_t)ptr, size);
-            break;
-        }
-    }
-
-#endif
-
-#ifdef RMT_PLATFORM_LINUX
-
-    // Linux version based on now-defunct Wikipedia section http://en.wikipedia.org/w/index.php?title=Circular_buffer&oldid=600431497
-
-
-#ifdef __ANDROID__
-    file_descriptor = ashmem_create_region("remotery_shm", size * 2);
-    if (file_descriptor < 0) {
-        return RMT_ERROR_VIRTUAL_MEMORY_BUFFER_FAIL;
-    }
-#else
-    // Create a unique temporary filename in the shared memory folder
-    file_descriptor = mkstemp(path);
-    if (file_descriptor < 0)
-        return RMT_ERROR_VIRTUAL_MEMORY_BUFFER_FAIL;
-
-    // Delete the name
-    if (unlink(path))
-        return RMT_ERROR_VIRTUAL_MEMORY_BUFFER_FAIL;
-
-    // Set the file size to twice the buffer size
-    // TODO: this 2x behaviour can be avoided with similar solution to Win/Mac
-    if (ftruncate (file_descriptor, size * 2))
-        return RMT_ERROR_VIRTUAL_MEMORY_BUFFER_FAIL;
-
-#endif
-    // Map 2 contiguous pages
-    buffer->ptr = (rmtU8*)mmap(NULL, size * 2, PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
-    if (buffer->ptr == MAP_FAILED)
-    {
-        buffer->ptr = NULL;
-        return RMT_ERROR_VIRTUAL_MEMORY_BUFFER_FAIL;
-    }
-
-    // Point both pages to the same memory file
-    if (mmap(buffer->ptr, size, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_SHARED, file_descriptor, 0) != buffer->ptr ||
-        mmap(buffer->ptr + size, size, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_SHARED, file_descriptor, 0) != buffer->ptr + size)
-        return RMT_ERROR_VIRTUAL_MEMORY_BUFFER_FAIL;
-
-#endif
-
-    // Cleanup if exceeded number of attempts or failed
-    if (buffer->ptr == NULL)
-        return RMT_ERROR_VIRTUAL_MEMORY_BUFFER_FAIL;
-
-    return RMT_ERROR_NONE;
-}
-
-
-static void VirtualMirrorBuffer_Destructor(VirtualMirrorBuffer* buffer)
-{
-    assert(buffer != 0);
-
-#ifdef RMT_PLATFORM_WINDOWS
-    if (buffer->file_map_handle != NULL)
-    {
-        CloseHandle(buffer->file_map_handle);
-        buffer->file_map_handle = NULL;
-    }
-#endif
-
-#ifdef RMT_PLATFORM_MACOS
-    if (buffer->ptr != NULL)
-        vm_deallocate(mach_task_self(), (vm_address_t)buffer->ptr, buffer->size * 2);
-#endif
-
-#ifdef RMT_PLATFORM_LINUX
-    if (buffer->ptr != NULL)
-        munmap(buffer->ptr, buffer->size * 2);
-#endif
-
-    buffer->ptr = NULL;
-}
-
-
-
-/*
-------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------
-   @THREADS: Threads
-------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------
-*/
-
-
-typedef struct Thread_t rmtThread;
-typedef rmtError(*ThreadProc)(rmtThread* thread);
-
-
-struct Thread_t
-{
-    // OS-specific data
-    #if defined(RMT_PLATFORM_WINDOWS)
-        HANDLE handle;
-    #else
-        pthread_t handle;
-    #endif
-
-    // Callback executed when the thread is created
-    ThreadProc callback;
-
-    // Caller-specified parameter passed to Thread_Create
-    void* param;
-
-    // Error state returned from callback
-    rmtError error;
-
-    // External threads can set this to request an exit
-    volatile rmtBool request_exit;
-
-};
-
-
-#if defined(RMT_PLATFORM_WINDOWS)
-
-    static DWORD WINAPI ThreadProcWindows(LPVOID lpParameter)
-    {
-        rmtThread* thread = (rmtThread*)lpParameter;
-        assert(thread != NULL);
-        thread->error = thread->callback(thread);
-        return thread->error == RMT_ERROR_NONE ? 1 : 0;
-    }
-
-#else
-    static void* StartFunc( void* pArgs )
-    {
-        rmtThread* thread = (rmtThread*)pArgs;
-        assert(thread != NULL);
-        thread->error = thread->callback(thread);
-        return NULL; // returned error not use, check thread->error.
-    }
-#endif
-
-
-static int rmtThread_Valid(rmtThread* thread)
-{
-    assert(thread != NULL);
-
-    #if defined(RMT_PLATFORM_WINDOWS)
-        return thread->handle != NULL;
-    #else
-        return !pthread_equal(thread->handle, pthread_self());
-    #endif
-}
-
-
-static rmtError rmtThread_Constructor(rmtThread* thread, ThreadProc callback, void* param)
-{
-    assert(thread != NULL);
-
-    thread->callback = callback;
-    thread->param = param;
-    thread->error = RMT_ERROR_NONE;
-    thread->request_exit = RMT_FALSE;
-
-    // OS-specific thread creation
-
-    #if defined (RMT_PLATFORM_WINDOWS)
-
-        thread->handle = CreateThread(
-            NULL,                               // lpThreadAttributes
-            0,                                  // dwStackSize
-            ThreadProcWindows,                  // lpStartAddress
-            thread,                            // lpParameter
-            0,                                  // dwCreationFlags
-            NULL);                              // lpThreadId
-
-        if (thread->handle == NULL)
-            return RMT_ERROR_CREATE_THREAD_FAIL;
-
-    #else
-
-        int32_t error = pthread_create( &thread->handle, NULL, StartFunc, thread );
-        if (error)
-        {
-            // Contents of 'thread' parameter to pthread_create() are undefined after
-            // failure call so can't pre-set to invalid value before hand.
-            thread->handle = pthread_self();
-            return RMT_ERROR_CREATE_THREAD_FAIL;
-        }
-
-    #endif
-
-    return RMT_ERROR_NONE;
-}
-
-
-static void rmtThread_RequestExit(rmtThread* thread)
-{
-    // Not really worried about memory barriers or delayed visibility to the target thread
-    assert(thread != NULL);
-    thread->request_exit = RMT_TRUE;
-}
-
-
-static void rmtThread_Join(rmtThread* thread)
-{
-    assert(rmtThread_Valid(thread));
-
-    #if defined(RMT_PLATFORM_WINDOWS)
-    WaitForSingleObject(thread->handle, INFINITE);
-    #else
-    pthread_join(thread->handle, NULL);
-    #endif
-}
-
-
-static void rmtThread_Destructor(rmtThread* thread)
-{
-    assert(thread != NULL);
-
-    if (rmtThread_Valid(thread))
-    {
-        // Shutdown the thread
-        rmtThread_RequestExit(thread);
-        rmtThread_Join(thread);
-
-        // OS-specific release of thread resources
-
-        #if defined(RMT_PLATFORM_WINDOWS)
-        CloseHandle(thread->handle);
-        thread->handle = NULL;
-        #endif
-    }
-}
-
-
-
-/*
-------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------
-   @SAFEC: Safe C Library excerpts
-   http://sourceforge.net/projects/safeclib/
-------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------
-*/
-
-
-
-/*------------------------------------------------------------------
- *
- * November 2008, Bo Berry
- *
- * Copyright (c) 2008-2011 by Cisco Systems, Inc
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *------------------------------------------------------------------
- */
-
-
-// NOTE: Microsoft also has its own version of these functions so I'm do some hacky PP to remove them
-#define strnlen_s strnlen_s_safe_c
-#define strncat_s strncat_s_safe_c
-#define strcpy_s strcpy_s_safe_c
-
-
-#define RSIZE_MAX_STR (4UL << 10)   /* 4KB */
-#define RCNEGATE(x) x
-
-
-#define EOK             ( 0 )
-#define ESNULLP         ( 400 )       /* null ptr                    */
-#define ESZEROL         ( 401 )       /* length is zero              */
-#define ESLEMAX         ( 403 )       /* length exceeds max          */
-#define ESOVRLP         ( 404 )       /* overlap undefined           */
-#define ESNOSPC         ( 406 )       /* not enough space for s2     */
-#define ESUNTERM        ( 407 )       /* unterminated string         */
-#define ESNOTFND        ( 409 )       /* not found                   */
-
-#ifndef _ERRNO_T_DEFINED
-#define _ERRNO_T_DEFINED
-typedef int errno_t;
-#endif
-
-#if (!defined(_WIN64) && !defined(__APPLE__)) || (defined(__MINGW32__) && !defined(RSIZE_T_DEFINED))
-typedef unsigned int rsize_t;
-#endif
-
-#if defined(RMT_PLATFORM_MACOS) && !defined(_RSIZE_T)
-typedef __darwin_size_t rsize_t;
-#endif
-
-static rsize_t
-strnlen_s (const char *dest, rsize_t dmax)
-{
-    rsize_t count;
-
-    if (dest == NULL) {
-        return RCNEGATE(0);
-    }
-
-    if (dmax == 0) {
-        return RCNEGATE(0);
-    }
-
-    if (dmax > RSIZE_MAX_STR) {
-        return RCNEGATE(0);
-    }
-
-    count = 0;
-    while (*dest && dmax) {
-        count++;
-        dmax--;
-        dest++;
-    }
-
-    return RCNEGATE(count);
-}
-
-
-static errno_t
-strstr_s (char *dest, rsize_t dmax,
-          const char *src, rsize_t slen, char **substring)
-{
-    rsize_t len;
-    rsize_t dlen;
-    int i;
-
-    if (substring == NULL) {
-        return RCNEGATE(ESNULLP);
-    }
-    *substring = NULL;
-
-    if (dest == NULL) {
-        return RCNEGATE(ESNULLP);
-    }
-
-    if (dmax == 0) {
-        return RCNEGATE(ESZEROL);
-    }
-
-    if (dmax > RSIZE_MAX_STR) {
-        return RCNEGATE(ESLEMAX);
-    }
-
-    if (src == NULL) {
-        return RCNEGATE(ESNULLP);
-    }
-
-    if (slen == 0) {
-        return RCNEGATE(ESZEROL);
-    }
-
-    if (slen > RSIZE_MAX_STR) {
-        return RCNEGATE(ESLEMAX);
-    }
-
-    /*
-     * src points to a string with zero length, or
-     * src equals dest, return dest
-     */
-    if (*src == '\0' || dest == src) {
-        *substring = dest;
-        return RCNEGATE(EOK);
-    }
-
-    while (*dest && dmax) {
-        i = 0;
-        len = slen;
-        dlen = dmax;
-
-        while (src[i] && dlen) {
-
-            /* not a match, not a substring */
-            if (dest[i] != src[i]) {
-                break;
-            }
-
-            /* move to the next char */
-            i++;
-            len--;
-            dlen--;
-
-            if (src[i] == '\0' || !len) {
-                *substring = dest;
-                return RCNEGATE(EOK);
-            }
-        }
-        dest++;
-        dmax--;
-    }
-
-    /*
-     * substring was not found, return NULL
-     */
-    *substring = NULL;
-    return RCNEGATE(ESNOTFND);
-}
-
-
-static errno_t
-strncat_s (char *dest, rsize_t dmax, const char *src, rsize_t slen)
-{
-    const char *overlap_bumper;
-
-    if (dest == NULL) {
-        return RCNEGATE(ESNULLP);
-    }
-
-    if (src == NULL) {
-        return RCNEGATE(ESNULLP);
-    }
-
-    if (slen > RSIZE_MAX_STR) {
-        return RCNEGATE(ESLEMAX);
-    }
-
-    if (dmax == 0) {
-        return RCNEGATE(ESZEROL);
-    }
-
-    if (dmax > RSIZE_MAX_STR) {
-        return RCNEGATE(ESLEMAX);
-    }
-
-    /* hold base of dest in case src was not copied */
-
-    if (dest < src) {
-        overlap_bumper = src;
-
-        /* Find the end of dest */
-        while (*dest != '\0') {
-
-            if (dest == overlap_bumper) {
-                return RCNEGATE(ESOVRLP);
-            }
-
-            dest++;
-            dmax--;
-            if (dmax == 0) {
-                return RCNEGATE(ESUNTERM);
-            }
-        }
-
-        while (dmax > 0) {
-            if (dest == overlap_bumper) {
-                return RCNEGATE(ESOVRLP);
-            }
-
-            /*
-             * Copying truncated before the source null is encountered
-             */
-            if (slen == 0) {
-                *dest = '\0';
-                return RCNEGATE(EOK);
-            }
-
-            *dest = *src;
-            if (*dest == '\0') {
-                return RCNEGATE(EOK);
-            }
-
-            dmax--;
-            slen--;
-            dest++;
-            src++;
-        }
-
-    } else {
-        overlap_bumper = dest;
-
-        /* Find the end of dest */
-        while (*dest != '\0') {
-
-            /*
-             * NOTE: no need to check for overlap here since src comes first
-             * in memory and we're not incrementing src here.
-             */
-            dest++;
-            dmax--;
-            if (dmax == 0) {
-                return RCNEGATE(ESUNTERM);
-            }
-        }
-
-        while (dmax > 0) {
-            if (src == overlap_bumper) {
-                return RCNEGATE(ESOVRLP);
-            }
-
-            /*
-             * Copying truncated
-             */
-            if (slen == 0) {
-                *dest = '\0';
-                return RCNEGATE(EOK);
-            }
-
-            *dest = *src;
-            if (*dest == '\0') {
-                return RCNEGATE(EOK);
-            }
-
-            dmax--;
-            slen--;
-            dest++;
-            src++;
-        }
-    }
-
-    /*
-     * the entire src was not copied, so the string will be nulled.
-     */
-    return RCNEGATE(ESNOSPC);
-}
-
-
-errno_t
-strcpy_s(char *dest, rsize_t dmax, const char *src)
-{
-    const char *overlap_bumper;
-
-    if (dest == NULL) {
-        return RCNEGATE(ESNULLP);
-    }
-
-    if (dmax == 0) {
-        return RCNEGATE(ESZEROL);
-    }
-
-    if (dmax > RSIZE_MAX_STR) {
-        return RCNEGATE(ESLEMAX);
-    }
-
-    if (src == NULL) {
-        *dest = '\0';
-        return RCNEGATE(ESNULLP);
-    }
-
-    if (dest == src) {
-        return RCNEGATE(EOK);
-    }
-
-    if (dest < src) {
-        overlap_bumper = src;
-
-        while (dmax > 0) {
-            if (dest == overlap_bumper) {
-                return RCNEGATE(ESOVRLP);
-            }
-
-            *dest = *src;
-            if (*dest == '\0') {
-                return RCNEGATE(EOK);
-            }
-
-            dmax--;
-            dest++;
-            src++;
-        }
-
-    }
-    else {
-        overlap_bumper = dest;
-
-        while (dmax > 0) {
-            if (src == overlap_bumper) {
-                return RCNEGATE(ESOVRLP);
-            }
-
-            *dest = *src;
-            if (*dest == '\0') {
-                return RCNEGATE(EOK);
-            }
-
-            dmax--;
-            dest++;
-            src++;
-        }
-    }
-
-    /*
-    * the entire src must have been copied, if not reset dest
-    * to null the string.
-    */
-    return RCNEGATE(ESNOSPC);
-}
-
-#if !(defined(RMT_PLATFORM_LINUX) && RMT_USE_POSIX_THREADNAMES)
-
-/* very simple integer to hex */
-static const char* hex_encoding_table = "0123456789ABCDEF";
-
-static void itoahex_s( char *dest, rsize_t dmax, rmtS32 value )
-{
-    rsize_t len;
-    rmtS32 halfbytepos;
-
-    halfbytepos = 8;
-
-    /* strip leading 0's */
-    while (halfbytepos > 1)
-    {
-        --halfbytepos;
-        if (value >> (4 * halfbytepos) & 0xF)
-        {
-            ++halfbytepos;
-            break;
-        }
-    }
-
-    len = 0;
-    while(len + 1 < dmax && halfbytepos > 0)
-    {
-        --halfbytepos;
-        dest[len] = hex_encoding_table[value >> (4 * halfbytepos) & 0xF];
-        ++len;
-    }
-
-    if (len < dmax)
-    {
-        dest[len] = 0;
-    }
-}
-
-#endif
-
-/*
-------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------
-   @OBJALLOC: Reusable Object Allocator
-------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------
-*/
-
-
-
-//
-// All objects that require free-list-backed allocation need to inherit from this type.
-//
-typedef struct ObjectLink_s
-{
-    struct ObjectLink_s* volatile next;
-} ObjectLink;
-
-
-static void ObjectLink_Constructor(ObjectLink* link)
-{
-    assert(link != NULL);
-    link->next = NULL;
-}
-
-
-typedef rmtError (*ObjConstructor)(void*);
-typedef void (*ObjDestructor)(void*);
-
-
-typedef struct
-{
-    // Object create/destroy parameters
-    rmtU32 object_size;
-    ObjConstructor constructor;
-    ObjDestructor destructor;
-
-    // Number of objects in the free list
-    volatile rmtS32 nb_free;
-
-    // Number of objects used by callers
-    volatile rmtS32 nb_inuse;
-
-    // Total allocation count
-    volatile rmtS32 nb_allocated;
-
-    ObjectLink* first_free;
-} ObjectAllocator;
-
-
-static rmtError ObjectAllocator_Constructor(ObjectAllocator* allocator, rmtU32 object_size, ObjConstructor constructor, ObjDestructor destructor)
-{
-    allocator->object_size = object_size;
-    allocator->constructor = constructor;
-    allocator->destructor = destructor;
-    allocator->nb_free = 0;
-    allocator->nb_inuse = 0;
-    allocator->nb_allocated = 0;
-    allocator->first_free = NULL;
-    return RMT_ERROR_NONE;
-}
-
-
-static void ObjectAllocator_Destructor(ObjectAllocator* allocator)
-{
-    // Ensure everything has been released to the allocator
-    assert(allocator != NULL);
-    assert(allocator->nb_inuse == 0);
-
-    // Destroy all objects released to the allocator
-    while (allocator->first_free != NULL)
-    {
-        ObjectLink* next = allocator->first_free->next;
-        assert(allocator->destructor != NULL);
-        allocator->destructor(allocator->first_free);
-        rmtFree(allocator->first_free);
-        allocator->first_free = next;
-    }
-}
-
-
-static void ObjectAllocator_Push(ObjectAllocator* allocator, ObjectLink* start, ObjectLink* end)
-{
-    assert(allocator != NULL);
-    assert(start != NULL);
-    assert(end != NULL);
-
-    // CAS pop add range to the front of the list
-    for (;;)
-    {
-        ObjectLink* old_link = (ObjectLink*)allocator->first_free;
-        end->next = old_link;
-        if (AtomicCompareAndSwapPointer((long* volatile*)&allocator->first_free, (long*)old_link, (long*)start) == RMT_TRUE)
-            break;
-    }
-}
-
-
-static ObjectLink* ObjectAllocator_Pop(ObjectAllocator* allocator)
-{
-    ObjectLink* link;
-
-    assert(allocator != NULL);
-    assert(allocator->first_free != NULL);
-
-    // CAS pop from the front of the list
-    for (;;)
-    {
-        ObjectLink* old_link = (ObjectLink*)allocator->first_free;
-        ObjectLink* next_link = old_link->next;
-        if (AtomicCompareAndSwapPointer((long* volatile*)&allocator->first_free, (long*)old_link, (long*)next_link) == RMT_TRUE)
-        {
-            link = old_link;
-            break;
-        }
-    }
-
-    link->next = NULL;
-
-    return link;
-}
-
-
-static rmtError ObjectAllocator_Alloc(ObjectAllocator* allocator, void** object)
-{
-    // This function only calls the object constructor on initial malloc of an object
-
-    assert(allocator != NULL);
-    assert(object != NULL);
-
-    // Has the free list run out?
-    if (allocator->first_free == NULL)
-    {
-        rmtError error;
-
-        // Allocate/construct a new object
-        void* free_object = rmtMalloc( allocator->object_size );
-        if (free_object == NULL)
-            return RMT_ERROR_MALLOC_FAIL;
-        assert(allocator->constructor != NULL);
-        error = allocator->constructor(free_object);
-        if (error != RMT_ERROR_NONE)
-        {
-            // Auto-teardown on failure
-            assert(allocator->destructor != NULL);
-            allocator->destructor(free_object);
-            rmtFree(free_object);
-            return error;
-        }
-
-        // Add to the free list
-        ObjectAllocator_Push(allocator, (ObjectLink*)free_object, (ObjectLink*)free_object);
-        AtomicAdd(&allocator->nb_allocated, 1);
-        AtomicAdd(&allocator->nb_free, 1);
-    }
-
-    // Pull available objects from the free list
-    *object = ObjectAllocator_Pop(allocator);
-    AtomicSub(&allocator->nb_free, 1);
-    AtomicAdd(&allocator->nb_inuse, 1);
-
-    return RMT_ERROR_NONE;
-}
-
-
-static void ObjectAllocator_Free(ObjectAllocator* allocator, void* object)
-{
-    // Add back to the free-list
-    assert(allocator != NULL);
-    ObjectAllocator_Push(allocator, (ObjectLink*)object, (ObjectLink*)object);
-    AtomicSub(&allocator->nb_inuse, 1);
-    AtomicAdd(&allocator->nb_free, 1);
-}
-
-
-static void ObjectAllocator_FreeRange(ObjectAllocator* allocator, void* start, void* end, rmtU32 count)
-{
-    assert(allocator != NULL);
-    ObjectAllocator_Push(allocator, (ObjectLink*)start, (ObjectLink*)end);
-    AtomicSub(&allocator->nb_inuse, count);
-    AtomicAdd(&allocator->nb_free, count);
-}
-
-
-
-/*
-------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------
-   @DYNBUF: Dynamic Buffer
-------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------
-*/
-
-
-
-typedef struct
-{
-    rmtU32 alloc_granularity;
-
-    rmtU32 bytes_allocated;
-    rmtU32 bytes_used;
-
-    rmtU8* data;
-} Buffer;
-
-
-static rmtError Buffer_Constructor(Buffer* buffer, rmtU32 alloc_granularity)
-{
-    assert(buffer != NULL);
-    buffer->alloc_granularity = alloc_granularity;
-    buffer->bytes_allocated = 0;
-    buffer->bytes_used = 0;
-    buffer->data = NULL;
-    return RMT_ERROR_NONE;
-}
-
-
-static void Buffer_Destructor(Buffer* buffer)
-{
-    assert(buffer != NULL);
-
-    if (buffer->data != NULL)
-    {
-        rmtFree(buffer->data);
-        buffer->data = NULL;
-    }
-}
-
-
-static rmtError Buffer_Write(Buffer* buffer, void* data, rmtU32 length)
-{
-    assert(buffer != NULL);
-
-    // Reallocate the buffer on overflow
-    if (buffer->bytes_used + length > buffer->bytes_allocated)
-    {
-        // Calculate size increase rounded up to the requested allocation granularity
-        rmtU32 g = buffer->alloc_granularity;
-        rmtU32 a = buffer->bytes_allocated + length;
-        a = a + ((g - 1) - ((a - 1) % g));
-        buffer->bytes_allocated = a;
-        buffer->data = (rmtU8*)rmtRealloc(buffer->data, buffer->bytes_allocated);
-        if (buffer->data == NULL)
-            return RMT_ERROR_MALLOC_FAIL;
-    }
-
-    // Copy all bytes
-    memcpy(buffer->data + buffer->bytes_used, data, length);
-    buffer->bytes_used += length;
-
-    // NULL terminate (if possible) for viewing in debug
-    if (buffer->bytes_used < buffer->bytes_allocated)
-        buffer->data[buffer->bytes_used] = 0;
-
-    return RMT_ERROR_NONE;
-}
-
-
-static rmtError Buffer_WriteStringZ(Buffer* buffer, rmtPStr string)
-{
-    assert(string != NULL);
-    return Buffer_Write(buffer, (void*)string, (rmtU32)strnlen_s(string, 2048) + 1);
-}
-
-
-static void U32ToByteArray(rmtU8* dest, rmtU32 value)
-{
-    // Commit as little-endian
-    dest[0] = value & 255;
-    dest[1] = (value >> 8) & 255;
-    dest[2] = (value >> 16) & 255;
-    dest[3] = value >> 24;
-}
-
-
-static rmtError Buffer_WriteU32(Buffer* buffer, rmtU32 value)
-{
-    rmtU8 temp[4];
-    U32ToByteArray(temp, value);
-    return Buffer_Write(buffer, temp, sizeof(temp));
-}
-
-
-static rmtBool IsLittleEndian()
-{
-    // Not storing this in a global variable allows the compiler to more easily optimise
-    // this away altogether.
-    union
-    {
-        unsigned int i;
-        unsigned char c[sizeof(unsigned int)];
-    } u;
-    u.i = 1;
-    return u.c[0] == 1 ? RMT_TRUE : RMT_FALSE;
-}
-
-
-static rmtError Buffer_WriteU64(Buffer* buffer, rmtU64 value)
-{
-    // Write as a double as Javascript DataView doesn't have a 64-bit integer read
-    union
-    {
-        double d;
-        unsigned char c[sizeof(double)];
-    } u;
-    char temp[8];
-    u.d = (double)value;
-    if (IsLittleEndian())
-    {
-        temp[0] = u.c[0];
-        temp[1] = u.c[1];
-        temp[2] = u.c[2];
-        temp[3] = u.c[3];
-        temp[4] = u.c[4];
-        temp[5] = u.c[5];
-        temp[6] = u.c[6];
-        temp[7] = u.c[7];
-    }
-    else
-    {
-        temp[0] = u.c[7];
-        temp[1] = u.c[6];
-        temp[2] = u.c[5];
-        temp[3] = u.c[4];
-        temp[4] = u.c[3];
-        temp[5] = u.c[2];
-        temp[6] = u.c[1];
-        temp[7] = u.c[0];
-    }
-    return Buffer_Write(buffer, u.c, sizeof(u.c));
-}
-
-
-static rmtError Buffer_WriteStringWithLength(Buffer* buffer, rmtPStr string)
-{
-    rmtU32 length = (rmtU32)strnlen_s(string, 2048);
-    rmtError error;
-
-    error = Buffer_WriteU32(buffer, length);
-    if (error != RMT_ERROR_NONE)
-        return error;
-
-    return Buffer_Write(buffer, (void*)string, length);
-}
-
-
-
-/*
-------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------
-   @HASHTABLE: Integer pair hash map for inserts/finds. No removes for added simplicity.
-------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------
-*/
-
-
-
-#define RMT_NOT_FOUND 0xFFFFFFFF
-
-
-typedef struct
-{
-    // Non-zero, pre-hashed key
-    rmtU32 key;
-
-    // Value that's not equal to RMT_NOT_FOUND
-    rmtU32 value;
-} HashSlot;
-
-
-typedef struct
-{
-    // Stats
-    rmtU32 max_nb_slots;
-    rmtU32 nb_slots;
-
-    // Data
-    HashSlot* slots;
-} rmtHashTable;
-
-
-static rmtError rmtHashTable_Constructor(rmtHashTable* table, rmtU32 max_nb_slots)
-{
-    // Default initialise
-    assert(table != NULL);
-    table->max_nb_slots = max_nb_slots;
-    table->nb_slots = 0;
-
-    // Allocate and clear the hash slots
-    table->slots = (HashSlot*)rmtMalloc(table->max_nb_slots * sizeof(HashSlot));
-    if (table->slots == NULL)
-        return RMT_ERROR_MALLOC_FAIL;
-    memset(table->slots, 0, table->max_nb_slots * sizeof(HashSlot));
-
-    return RMT_ERROR_NONE;
-}
-
-
-static void rmtHashTable_Destructor(rmtHashTable* table)
-{
-    assert(table != NULL);
-
-    if (table->slots != NULL)
-    {
-        rmtFree(table->slots);
-        table->slots = NULL;
-    }
-}
-
-
-static rmtError rmtHashTable_Resize(rmtHashTable* table);
-
-
-static rmtError rmtHashTable_Insert(rmtHashTable* table, rmtU32 key, rmtU32 value)
-{
-    HashSlot* slot = NULL;
-    rmtError error = RMT_ERROR_NONE;
-
-    // Calculate initial slot location for this key
-    rmtU32 index_mask = table->max_nb_slots - 1;
-    rmtU32 index = key & index_mask;
-
-    assert(key != 0);
-    assert(value != RMT_NOT_FOUND);
-
-    // Linear probe for free slot, reusing any existing key matches
-    // There will always be at least one free slot due to load factor management
-    while (table->slots[index].key)
-    {
-        if (table->slots[index].key == key)
-        {
-            // Counter occupied slot increments below
-            table->nb_slots--;
-            break;
-        }
-
-        index = (index + 1) & index_mask;
-    }
-
-    // Just verify that I've got no errors in the code above
-    assert(index < table->max_nb_slots);
-
-    // Add to the table
-    slot = table->slots + index;
-    slot->key = key;
-    slot->value = value;
-    table->nb_slots++;
-
-    // Resize when load factor is greater than 2/3
-    if (table->nb_slots > (table->max_nb_slots * 2) / 3)
-        error = rmtHashTable_Resize(table);
-
-    return error;
-}
-
-
-static rmtError rmtHashTable_Resize(rmtHashTable* table)
-{
-    rmtU32 old_max_nb_slots = table->max_nb_slots;
-    HashSlot* new_slots = NULL;
-    HashSlot* old_slots = table->slots;
-
-    // Increase the table size
-    rmtU32 new_max_nb_slots = table->max_nb_slots;
-    if (new_max_nb_slots < 8192 * 4)
-        new_max_nb_slots *= 4;
-    else
-        new_max_nb_slots *= 2;
-
-    // Allocate and clear a new table
-    new_slots = (HashSlot*)rmtMalloc(new_max_nb_slots * sizeof(HashSlot));
-    if (new_slots == NULL)
-        return RMT_ERROR_MALLOC_FAIL;
-    memset(new_slots, 0, new_max_nb_slots * sizeof(HashSlot));
-
-    // Update fields of the table after successful allocation only
-    table->slots = new_slots;
-    table->max_nb_slots = new_max_nb_slots;
-    table->nb_slots = 0;
-
-    // Reinsert all objects into the new table
-    for (rmtU32 i = 0; i < old_max_nb_slots; i++)
-    {
-        HashSlot* slot = old_slots + i;
-        if (slot->key != 0)
-            rmtHashTable_Insert(table, slot->key, slot->key);
-    }
-
-    free(old_slots);
-
-    return RMT_ERROR_NONE;
-}
-
-
-static rmtU32 rmtHashTable_Find(rmtHashTable* table, rmtU32 key)
-{
-    // Calculate initial slot location for this key
-    rmtU32 index_mask = table->max_nb_slots - 1;
-    rmtU32 index = key & index_mask;
-
-    // Linear probe for matching hash
-    while (table->slots[index].key)
-    {
-        HashSlot* slot = table->slots + index;
-
-        if (slot->key == key)
-            return slot->value;
-
-        index = (index + 1) & index_mask;
-    }
-
-    return RMT_NOT_FOUND;
-}
-
-
-
-/*
-------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------
-   @STRINGTABLE: Map from string hash to string offset in local buffer
-------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------
-*/
-
-
-
-typedef struct
-{
-    // Growable dynamic array of strings added so far
-    Buffer* text;
-
-    // Map from text hash to text location in the buffer
-    rmtHashTable* text_map;
-} StringTable;
-
-
-static rmtError StringTable_Constructor(StringTable* table)
-{
-    rmtError error;
-
-    // Default initialise
-    assert(table != NULL);
-    table->text = NULL;
-    table->text_map = NULL;
-
-    // Allocate reasonably storage for initial sample names
-
-    New_1(Buffer, table->text, 8 * 1024);
-    if (error != RMT_ERROR_NONE)
-        return error;
-
-    New_1(rmtHashTable, table->text_map, 1 * 1024);
-    if (error != RMT_ERROR_NONE)
-        return error;
-
-    return RMT_ERROR_NONE;
-}
-
-
-static void StringTable_Destructor(StringTable* table)
-{
-    assert(table != NULL);
-
-    Delete(rmtHashTable, table->text_map);
-    Delete(Buffer, table->text);
-}
-
-
-static rmtPStr StringTable_Find(StringTable* table, rmtU32 name_hash)
-{
-    rmtU32 text_offset = rmtHashTable_Find(table->text_map, name_hash);
-    if (text_offset != RMT_NOT_FOUND)
-        return (rmtPStr)(table->text->data + text_offset);
-    return NULL;
-}
-
-
-static void StringTable_Insert(StringTable* table, rmtU32 name_hash, rmtPStr name)
-{
-    // Only add to the buffer if the string isn't already there
-    rmtU32 text_offset = rmtHashTable_Find(table->text_map, name_hash);
-    if (text_offset == RMT_NOT_FOUND)
-    {
-        // TODO: Allocation errors aren't being passed on to the caller
-        text_offset = table->text->bytes_used;
-        Buffer_WriteStringZ(table->text, name);
-        rmtHashTable_Insert(table->text_map, name_hash, text_offset);
-    }
-}
-
-
-/*
-------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------
-   @SOCKETS: Sockets TCP/IP Wrapper
-------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------
-*/
-
-
-
-#ifndef RMT_PLATFORM_WINDOWS
-    typedef int SOCKET;
-    #define INVALID_SOCKET -1
-    #define SOCKET_ERROR   -1
-    #define SD_SEND SHUT_WR
-    #define closesocket close
-#endif
-
-
-typedef struct
-{
-    SOCKET socket;
-} TCPSocket;
-
-
-typedef struct
-{
-    rmtBool can_read;
-    rmtBool can_write;
-    rmtError error_state;
-} SocketStatus;
-
-
-//
-// Function prototypes
-//
-static void TCPSocket_Close(TCPSocket* tcp_socket);
-
-
-static rmtError InitialiseNetwork()
-{
-    #ifdef RMT_PLATFORM_WINDOWS
-
-        WSADATA wsa_data;
-        if (WSAStartup(MAKEWORD(2, 2), &wsa_data))
-            return RMT_ERROR_SOCKET_INIT_NETWORK_FAIL;
-        if (LOBYTE(wsa_data.wVersion) != 2 || HIBYTE(wsa_data.wVersion) != 2)
-            return RMT_ERROR_SOCKET_INIT_NETWORK_FAIL;
-
-        return RMT_ERROR_NONE;
-
-    #else
-
-        return RMT_ERROR_NONE;
-
-    #endif
-}
-
-
-static void ShutdownNetwork()
-{
-    #ifdef RMT_PLATFORM_WINDOWS
-        WSACleanup();
-    #endif
-}
-
-
-static rmtError TCPSocket_Constructor(TCPSocket* tcp_socket)
-{
-    assert(tcp_socket != NULL);
-    tcp_socket->socket = INVALID_SOCKET;
-    return InitialiseNetwork();
-}
-
-
-static void TCPSocket_Destructor(TCPSocket* tcp_socket)
-{
-    assert(tcp_socket != NULL);
-    TCPSocket_Close(tcp_socket);
-    ShutdownNetwork();
-}
-
-
-static rmtError TCPSocket_RunServer(TCPSocket* tcp_socket, rmtU16 port, rmtBool limit_connections_to_localhost)
-{
-    SOCKET s = INVALID_SOCKET;
-    struct sockaddr_in sin;
-    int enable = 1;
-    #ifdef RMT_PLATFORM_WINDOWS
-        u_long nonblock = 1;
-    #endif
-
-    memset(&sin, 0, sizeof(sin) );
-    assert(tcp_socket != NULL);
-
-    // Try to create the socket
-    s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
-    if (s == SOCKET_ERROR)
-        return RMT_ERROR_SOCKET_CREATE_FAIL;
-
-    // set SO_REUSEADDR so binding doesn't fail when restarting the application
-    // (otherwise the same port can't be reused within TIME_WAIT)
-    // I'm not checking for errors because if this fails (unlikely) we might still
-    // be able to bind to the socket anyway
-    #ifdef RMT_PLATFORM_POSIX
-        setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable));
-    #elif defined(RMT_PLATFORM_WINDOWS)
-        // windows also needs SO_EXCLUSEIVEADDRUSE,
-        // see http://www.andy-pearce.com/blog/posts/2013/Feb/so_reuseaddr-on-windows/
-        setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&enable, sizeof(enable));
-        enable = 1;
-        setsockopt(s, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (char *)&enable, sizeof(enable));
-    #endif
-
-    // Bind the socket to the incoming port
-    sin.sin_family = AF_INET;
-    sin.sin_addr.s_addr = htonl(limit_connections_to_localhost ? INADDR_LOOPBACK : INADDR_ANY);
-    sin.sin_port = htons(port);
-    if (bind(s, (struct sockaddr*)&sin, sizeof(sin)) == SOCKET_ERROR)
-        return RMT_ERROR_SOCKET_BIND_FAIL;
-
-    // Connection is valid, remaining code is socket state modification
-    tcp_socket->socket = s;
-
-    // Enter a listening state with a backlog of 1 connection
-    if (listen(s, 1) == SOCKET_ERROR)
-        return RMT_ERROR_SOCKET_LISTEN_FAIL;
-
-    // Set as non-blocking
-    #ifdef RMT_PLATFORM_WINDOWS
-        if (ioctlsocket(tcp_socket->socket, FIONBIO, &nonblock) == SOCKET_ERROR)
-            return RMT_ERROR_SOCKET_SET_NON_BLOCKING_FAIL;
-    #else
-        if (fcntl(tcp_socket->socket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
-            return RMT_ERROR_SOCKET_SET_NON_BLOCKING_FAIL;
-    #endif
-
-    return RMT_ERROR_NONE;
-}
-
-
-static void TCPSocket_Close(TCPSocket* tcp_socket)
-{
-    assert(tcp_socket != NULL);
-
-    if (tcp_socket->socket != INVALID_SOCKET)
-    {
-        // Shutdown the connection, stopping all sends
-        int result = shutdown(tcp_socket->socket, SD_SEND);
-        if (result != SOCKET_ERROR)
-        {
-            // Keep receiving until the peer closes the connection
-            int total = 0;
-            char temp_buf[128];
-            while (result > 0)
-            {
-                result = (int)recv(tcp_socket->socket, temp_buf, sizeof(temp_buf), 0);
-                total += result;
-            }
-        }
-
-        // Close the socket and issue a network shutdown request
-        closesocket(tcp_socket->socket);
-        tcp_socket->socket = INVALID_SOCKET;
-    }
-}
-
-
-static SocketStatus TCPSocket_PollStatus(TCPSocket* tcp_socket)
-{
-    SocketStatus status;
-    fd_set fd_read, fd_write, fd_errors;
-    struct timeval tv;
-
-    status.can_read = RMT_FALSE;
-    status.can_write = RMT_FALSE;
-    status.error_state = RMT_ERROR_NONE;
-
-    assert(tcp_socket != NULL);
-    if (tcp_socket->socket == INVALID_SOCKET)
-    {
-        status.error_state = RMT_ERROR_SOCKET_INVALID_POLL;
-        return status;
-    }
-
-    // Set read/write/error markers for the socket
-    FD_ZERO(&fd_read);
-    FD_ZERO(&fd_write);
-    FD_ZERO(&fd_errors);
-#ifdef _MSC_VER
-#   pragma warning(push)
-#   pragma warning(disable:4127) // warning C4127: conditional expression is constant
-#endif // _MSC_VER
-    FD_SET(tcp_socket->socket, &fd_read);
-    FD_SET(tcp_socket->socket, &fd_write);
-    FD_SET(tcp_socket->socket, &fd_errors);
-#ifdef _MSC_VER
-#   pragma warning(pop)
-#endif // _MSC_VER
-
-    // Poll socket status without blocking
-    tv.tv_sec = 0;
-    tv.tv_usec = 0;
-    if (select(((int)tcp_socket->socket)+1, &fd_read, &fd_write, &fd_errors, &tv) == SOCKET_ERROR)
-    {
-        status.error_state = RMT_ERROR_SOCKET_SELECT_FAIL;
-        return status;
-    }
-
-    status.can_read = FD_ISSET(tcp_socket->socket, &fd_read) != 0 ? RMT_TRUE : RMT_FALSE;
-    status.can_write = FD_ISSET(tcp_socket->socket, &fd_write) != 0 ? RMT_TRUE : RMT_FALSE;
-    status.error_state = FD_ISSET(tcp_socket->socket, &fd_errors) != 0 ? RMT_ERROR_SOCKET_POLL_ERRORS : RMT_ERROR_NONE;
-    return status;
-}
-
-
-static rmtError TCPSocket_AcceptConnection(TCPSocket* tcp_socket, TCPSocket** client_socket)
-{
-    SocketStatus status;
-    SOCKET s;
-    rmtError error;
-
-    // Ensure there is an incoming connection
-    assert(tcp_socket != NULL);
-    status = TCPSocket_PollStatus(tcp_socket);
-    if (status.error_state != RMT_ERROR_NONE || !status.can_read)
-        return status.error_state;
-
-    // Accept the connection
-    s = accept(tcp_socket->socket, 0, 0);
-    if (s == SOCKET_ERROR)
-        return RMT_ERROR_SOCKET_ACCEPT_FAIL;
-
-#ifdef SO_NOSIGPIPE
-    // On POSIX systems, send() may send a SIGPIPE signal when writing to an
-    // already closed connection. By setting this option, we prevent the
-    // signal from being emitted and send will instead return an error and set
-    // errno to EPIPE.
-    //
-    // This is supported on BSD platforms and not on Linux.
-    {
-        int flag = 1;
-        setsockopt(s, SOL_SOCKET, SO_NOSIGPIPE, &flag, sizeof(flag));
-    }
-#endif
-    // Create a client socket for the new connection
-    assert(client_socket != NULL);
-    New_0(TCPSocket, *client_socket);
-    if (error != RMT_ERROR_NONE)
-        return error;
-    (*client_socket)->socket = s;
-
-    return RMT_ERROR_NONE;
-}
-
-
-static int TCPSocketWouldBlock()
-{
-#ifdef RMT_PLATFORM_WINDOWS
-    DWORD error = WSAGetLastError();
-    return (error == WSAEWOULDBLOCK);
- #else
-    int error = errno;
-    return (error == EAGAIN || error == EWOULDBLOCK);
-#endif
-
-}
-
-
-static rmtError TCPSocket_Send(TCPSocket* tcp_socket, const void* data, rmtU32 length, rmtU32 timeout_ms)
-{
-    SocketStatus status;
-    char* cur_data = NULL;
-    char* end_data = NULL;
-    rmtU32 start_ms = 0;
-    rmtU32 cur_ms = 0;
-
-    assert(tcp_socket != NULL);
-
-    start_ms = msTimer_Get();
-
-    // Loop until timeout checking whether data can be written
-    status.can_write = RMT_FALSE;
-    while (!status.can_write)
-    {
-        status = TCPSocket_PollStatus(tcp_socket);
-        if (status.error_state != RMT_ERROR_NONE)
-            return status.error_state;
-
-        cur_ms = msTimer_Get();
-        if (cur_ms - start_ms > timeout_ms)
-            return RMT_ERROR_SOCKET_SEND_TIMEOUT;
-    }
-
-    cur_data = (char*)data;
-    end_data = cur_data + length;
-
-    while (cur_data < end_data)
-    {
-        // Attempt to send the remaining chunk of data
-        int bytes_sent;
-        int send_flags = 0;
-#ifdef MSG_NOSIGNAL
-        // On Linux this prevents send from emitting a SIGPIPE signal
-        // Equivalent on BSD to the SO_NOSIGPIPE option.
-        send_flags = MSG_NOSIGNAL;
-#endif
-        bytes_sent = (int)send(tcp_socket->socket, cur_data, (int)(end_data - cur_data), send_flags);
-
-        if (bytes_sent == SOCKET_ERROR || bytes_sent == 0)
-        {
-            // Close the connection if sending fails for any other reason other than blocking
-            if (bytes_sent != 0 && !TCPSocketWouldBlock())
-                return RMT_ERROR_SOCKET_SEND_FAIL;
-
-            // First check for tick-count overflow and reset, giving a slight hitch every 49.7 days
-            cur_ms = msTimer_Get();
-            if (cur_ms < start_ms)
-            {
-                start_ms = cur_ms;
-                continue;
-            }
-
-            //
-            // Timeout can happen when:
-            //
-            //    1) endpoint is no longer there
-            //    2) endpoint can't consume quick enough
-            //    3) local buffers overflow
-            //
-            // As none of these are actually errors, we have to pass this timeout back to the caller.
-            //
-            // TODO: This strategy breaks down if a send partially completes and then times out!
-            //
-            if (cur_ms - start_ms > timeout_ms)
-            {
-                return RMT_ERROR_SOCKET_SEND_TIMEOUT;
-            }
-        }
-        else
-        {
-            // Jump over the data sent
-            cur_data += bytes_sent;
-        }
-    }
-
-    return RMT_ERROR_NONE;
-}
-
-
-static rmtError TCPSocket_Receive(TCPSocket* tcp_socket, void* data, rmtU32 length, rmtU32 timeout_ms)
-{
-    SocketStatus status;
-    char* cur_data = NULL;
-    char* end_data = NULL;
-    rmtU32 start_ms = 0;
-    rmtU32 cur_ms = 0;
-
-    assert(tcp_socket != NULL);
-
-    // Ensure there is data to receive
-    status = TCPSocket_PollStatus(tcp_socket);
-    if (status.error_state != RMT_ERROR_NONE)
-        return status.error_state;
-    if (!status.can_read)
-        return RMT_ERROR_SOCKET_RECV_NO_DATA;
-
-    cur_data = (char*)data;
-    end_data = cur_data + length;
-
-    // Loop until all data has been received
-    start_ms = msTimer_Get();
-    while (cur_data < end_data)
-    {
-        int bytes_received = (int)recv(tcp_socket->socket, cur_data, (int)(end_data - cur_data), 0);
-
-        if (bytes_received == SOCKET_ERROR || bytes_received == 0)
-        {
-            // Close the connection if receiving fails for any other reason other than blocking
-            if (bytes_received != 0 && !TCPSocketWouldBlock())
-                return RMT_ERROR_SOCKET_RECV_FAILED;
-
-            // First check for tick-count overflow and reset, giving a slight hitch every 49.7 days
-            cur_ms = msTimer_Get();
-            if (cur_ms < start_ms)
-            {
-                start_ms = cur_ms;
-                continue;
-            }
-
-            //
-            // Timeout can happen when:
-            //
-            //    1) data is delayed by sender
-            //    2) sender fails to send a complete set of packets
-            //
-            // As not all of these scenarios are errors, we need to pass this information back to the caller.
-            //
-            // TODO: This strategy breaks down if a receive partially completes and then times out!
-            //
-            if (cur_ms - start_ms > timeout_ms)
-            {
-                return RMT_ERROR_SOCKET_RECV_TIMEOUT;
-            }
-        }
-        else
-        {
-            // Jump over the data received
-            cur_data += bytes_received;
-        }
-    }
-
-    return RMT_ERROR_NONE;
-}
-
-
-
-/*
-------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------
-   @SHA1: SHA-1 Cryptographic Hash Function
-------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------
-*/
-
-
-//
-// Typed to allow enforced data size specification
-//
-typedef struct
-{
-    rmtU8 data[20];
-} SHA1;
-
-
-/*
- Copyright (c) 2011, Micael Hildenborg
- All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are met:
-    * Redistributions of source code must retain the above copyright
-      notice, this list of conditions and the following disclaimer.
-    * Redistributions in binary form must reproduce the above copyright
-      notice, this list of conditions and the following disclaimer in the
-      documentation and/or other materials provided with the distribution.
-    * Neither the name of Micael Hildenborg nor the
-      names of its contributors may be used to endorse or promote products
-      derived from this software without specific prior written permission.
-
- THIS SOFTWARE IS PROVIDED BY Micael Hildenborg ''AS IS'' AND ANY
- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- DISCLAIMED. IN NO EVENT SHALL Micael Hildenborg BE LIABLE FOR ANY
- DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- Contributors:
- Gustav
- Several members in the gamedev.se forum.
- Gregory Petrosyan
- */
-
-
-// Rotate an integer value to left.
-static unsigned int rol(const unsigned int value, const unsigned int steps)
-{
-    return ((value << steps) | (value >> (32 - steps)));
-}
-
-
-// Sets the first 16 integers in the buffert to zero.
-// Used for clearing the W buffert.
-static void clearWBuffert(unsigned int* buffert)
-{
-    int pos;
-    for (pos = 16; --pos >= 0;)
-    {
-        buffert[pos] = 0;
-    }
-}
-
-static void innerHash(unsigned int* result, unsigned int* w)
-{
-    unsigned int a = result[0];
-    unsigned int b = result[1];
-    unsigned int c = result[2];
-    unsigned int d = result[3];
-    unsigned int e = result[4];
-
-    int round = 0;
-
-    #define sha1macro(func,val) \
-    { \
-        const unsigned int t = rol(a, 5) + (func) + e + val + w[round]; \
-        e = d; \
-        d = c; \
-        c = rol(b, 30); \
-        b = a; \
-        a = t; \
-    }
-
-    while (round < 16)
-    {
-        sha1macro((b & c) | (~b & d), 0x5a827999)
-        ++round;
-    }
-    while (round < 20)
-    {
-        w[round] = rol((w[round - 3] ^ w[round - 8] ^ w[round - 14] ^ w[round - 16]), 1);
-        sha1macro((b & c) | (~b & d), 0x5a827999)
-        ++round;
-    }
-    while (round < 40)
-    {
-        w[round] = rol((w[round - 3] ^ w[round - 8] ^ w[round - 14] ^ w[round - 16]), 1);
-        sha1macro(b ^ c ^ d, 0x6ed9eba1)
-        ++round;
-    }
-    while (round < 60)
-    {
-        w[round] = rol((w[round - 3] ^ w[round - 8] ^ w[round - 14] ^ w[round - 16]), 1);
-        sha1macro((b & c) | (b & d) | (c & d), 0x8f1bbcdc)
-        ++round;
-    }
-    while (round < 80)
-    {
-        w[round] = rol((w[round - 3] ^ w[round - 8] ^ w[round - 14] ^ w[round - 16]), 1);
-        sha1macro(b ^ c ^ d, 0xca62c1d6)
-        ++round;
-    }
-
-    #undef sha1macro
-
-    result[0] += a;
-    result[1] += b;
-    result[2] += c;
-    result[3] += d;
-    result[4] += e;
-}
-
-
-static void calc(const void* src, const int bytelength, unsigned char* hash)
-{
-    int roundPos;
-    int lastBlockBytes;
-    int hashByte;
-
-    // Init the result array.
-    unsigned int result[5] = { 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0 };
-
-    // Cast the void src pointer to be the byte array we can work with.
-    const unsigned char* sarray = (const unsigned char*) src;
-
-    // The reusable round buffer
-    unsigned int w[80];
-
-    // Loop through all complete 64byte blocks.
-    const int endOfFullBlocks = bytelength - 64;
-    int endCurrentBlock;
-    int currentBlock = 0;
-
-    while (currentBlock <= endOfFullBlocks)
-    {
-        endCurrentBlock = currentBlock + 64;
-
-        // Init the round buffer with the 64 byte block data.
-        for (roundPos = 0; currentBlock < endCurrentBlock; currentBlock += 4)
-        {
-            // This line will swap endian on big endian and keep endian on little endian.
-            w[roundPos++] = (unsigned int) sarray[currentBlock + 3]
-                | (((unsigned int) sarray[currentBlock + 2]) << 8)
-                | (((unsigned int) sarray[currentBlock + 1]) << 16)
-                | (((unsigned int) sarray[currentBlock]) << 24);
-        }
-        innerHash(result, w);
-    }
-
-    // Handle the last and not full 64 byte block if existing.
-    endCurrentBlock = bytelength - currentBlock;
-    clearWBuffert(w);
-    lastBlockBytes = 0;
-    for (;lastBlockBytes < endCurrentBlock; ++lastBlockBytes)
-    {
-        w[lastBlockBytes >> 2] |= (unsigned int) sarray[lastBlockBytes + currentBlock] << ((3 - (lastBlockBytes & 3)) << 3);
-    }
-    w[lastBlockBytes >> 2] |= 0x80U << ((3 - (lastBlockBytes & 3)) << 3);
-    if (endCurrentBlock >= 56)
-    {
-        innerHash(result, w);
-        clearWBuffert(w);
-    }
-    w[15] = bytelength << 3;
-    innerHash(result, w);
-
-    // Store hash in result pointer, and make sure we get in in the correct order on both endian models.
-    for (hashByte = 20; --hashByte >= 0;)
-    {
-        hash[hashByte] = (result[hashByte >> 2] >> (((3 - hashByte) & 0x3) << 3)) & 0xff;
-    }
-}
-
-
-static SHA1 SHA1_Calculate(const void* src, unsigned int length)
-{
-    SHA1 hash;
-    assert((int)length >= 0);
-    calc(src, length, hash.data);
-    return hash;
-}
-
-
-
-/*
-------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------
-   @BASE64: Base-64 encoder
-------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------
-*/
-
-
-
-static const char* b64_encoding_table =
-        "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
-        "abcdefghijklmnopqrstuvwxyz"
-        "0123456789+/";
-
-
-static rmtU32 Base64_CalculateEncodedLength(rmtU32 length)
-{
-    // ceil(l * 4/3)
-    return 4 * ((length + 2) / 3);
-}
-
-
-static void Base64_Encode(const rmtU8* in_bytes, rmtU32 length, rmtU8* out_bytes)
-{
-    rmtU32 i;
-    rmtU32 encoded_length;
-    rmtU32 remaining_bytes;
-
-    rmtU8* optr = out_bytes;
-
-    for (i = 0; i < length; )
-    {
-        // Read input 3 values at a time, null terminating
-        rmtU32 c0 = i < length ? in_bytes[i++] : 0;
-        rmtU32 c1 = i < length ? in_bytes[i++] : 0;
-        rmtU32 c2 = i < length ? in_bytes[i++] : 0;
-
-        // Encode 4 bytes for ever 3 input bytes
-        rmtU32 triple = (c0 << 0x10) + (c1 << 0x08) + c2;
-        *optr++ = b64_encoding_table[(triple >> 3 * 6) & 0x3F];
-        *optr++ = b64_encoding_table[(triple >> 2 * 6) & 0x3F];
-        *optr++ = b64_encoding_table[(triple >> 1 * 6) & 0x3F];
-        *optr++ = b64_encoding_table[(triple >> 0 * 6) & 0x3F];
-    }
-
-    // Pad output to multiple of 3 bytes with terminating '='
-    encoded_length = Base64_CalculateEncodedLength(length);
-    remaining_bytes = (3 - ((length + 2) % 3)) - 1;
-    for (i = 0; i < remaining_bytes; i++)
-        out_bytes[encoded_length - 1 - i] = '=';
-
-    // Null terminate
-    out_bytes[encoded_length] = 0;
-}
-
-
-
-/*
-------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------
-   @MURMURHASH: MurmurHash3
-   https://code.google.com/p/smhasher
-------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------
-*/
-
-
-//-----------------------------------------------------------------------------
-// MurmurHash3 was written by Austin Appleby, and is placed in the public
-// domain. The author hereby disclaims copyright to this source code.
-//-----------------------------------------------------------------------------
-
-
-static rmtU32 rotl32(rmtU32 x, rmtS8 r)
-{
-    return (x << r) | (x >> (32 - r));
-}
-
-
-// Block read - if your platform needs to do endian-swapping or can only
-// handle aligned reads, do the conversion here
-static rmtU32 getblock32(const rmtU32* p, int i)
-{
-    return p[i];
-}
-
-
-// Finalization mix - force all bits of a hash block to avalanche
-static rmtU32 fmix32(rmtU32 h)
-{
-    h ^= h >> 16;
-    h *= 0x85ebca6b;
-    h ^= h >> 13;
-    h *= 0xc2b2ae35;
-    h ^= h >> 16;
-    return h;
-}
-
-
-static rmtU32 MurmurHash3_x86_32(const void* key, int len, rmtU32 seed)
-{
-    const rmtU8* data = (const rmtU8*)key;
-    const int nblocks = len / 4;
-
-    rmtU32 h1 = seed;
-
-    const rmtU32 c1 = 0xcc9e2d51;
-    const rmtU32 c2 = 0x1b873593;
-
-    int i;
-
-    const rmtU32 * blocks = (const rmtU32 *)(data + nblocks*4);
-    const rmtU8 * tail = (const rmtU8*)(data + nblocks*4);
-
-    rmtU32 k1 = 0;
-
-    //----------
-    // body
-
-    for (i = -nblocks; i; i++)
-    {
-        rmtU32 k2 = getblock32(blocks,i);
-
-        k2 *= c1;
-        k2 = rotl32(k2,15);
-        k2 *= c2;
-
-        h1 ^= k2;
-        h1 = rotl32(h1,13);
-        h1 = h1*5+0xe6546b64;
-    }
-
-    //----------
-    // tail
-
-    switch(len & 3)
-    {
-    case 3: k1 ^= tail[2] << 16;
-    case 2: k1 ^= tail[1] << 8;
-    case 1: k1 ^= tail[0];
-        k1 *= c1;
-        k1 = rotl32(k1,15);
-        k1 *= c2;
-        h1 ^= k1;
-    };
-
-    //----------
-    // finalization
-
-    h1 ^= len;
-
-    h1 = fmix32(h1);
-
-    return h1;
-}
-
-
-
-/*
-------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------
-   @WEBSOCKETS: WebSockets
-------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------
-*/
-
-
-
-enum WebSocketMode
-{
-    WEBSOCKET_NONE = 0,
-    WEBSOCKET_TEXT = 1,
-    WEBSOCKET_BINARY = 2,
-};
-
-
-typedef struct
-{
-    TCPSocket* tcp_socket;
-
-    enum WebSocketMode mode;
-
-    rmtU32 frame_bytes_remaining;
-    rmtU32 mask_offset;
-
-    union
-    {
-        rmtU8 mask[4];
-        rmtU32 mask_u32;
-    } data;
-
-} WebSocket;
-
-
-static void WebSocket_Close(WebSocket* web_socket);
-
-
-static char* GetField(char* buffer, rsize_t buffer_length, rmtPStr field_name)
-{
-    char* field = NULL;
-    char* buffer_end = buffer + buffer_length - 1;
-
-    rsize_t field_length = strnlen_s(field_name, buffer_length);
-    if (field_length == 0)
-        return NULL;
-
-    // Search for the start of the field
-    if (strstr_s(buffer, buffer_length, field_name, field_length, &field) != EOK)
-        return NULL;
-
-    // Field name is now guaranteed to be in the buffer so its safe to jump over it without hitting the bounds
-    field += strlen(field_name);
-
-    // Skip any trailing whitespace
-    while (*field == ' ')
-    {
-        if (field >= buffer_end)
-            return NULL;
-        field++;
-    }
-
-    return field;
-}
-
-
-static const char websocket_guid[] = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
-static const char websocket_response[] =
-    "HTTP/1.1 101 Switching Protocols\r\n"
-    "Upgrade: websocket\r\n"
-    "Connection: Upgrade\r\n"
-    "Sec-WebSocket-Accept: ";
-
-
-static rmtError WebSocketHandshake(TCPSocket* tcp_socket, rmtPStr limit_host)
-{
-    rmtU32 start_ms, now_ms;
-
-    // Parsing scratchpad
-    char buffer[1024];
-    char* buffer_ptr = buffer;
-    int buffer_len = sizeof(buffer) - 1;
-    char* buffer_end = buffer + buffer_len;
-
-    char response_buffer[256];
-    int response_buffer_len = sizeof(response_buffer) - 1;
-
-    char* version;
-    char* host;
-    char* key;
-    char* key_end;
-    SHA1 hash;
-
-    assert(tcp_socket != NULL);
-
-    start_ms = msTimer_Get();
-
-    // Really inefficient way of receiving the handshake data from the browser
-    // Not really sure how to do this any better, as the termination requirement is \r\n\r\n
-    while (buffer_ptr - buffer < buffer_len)
-    {
-        rmtError error = TCPSocket_Receive(tcp_socket, buffer_ptr, 1, 20);
-        if (error == RMT_ERROR_SOCKET_RECV_FAILED)
-            return error;
-
-        // If there's a stall receiving the data, check for a handshake timeout
-        if (error == RMT_ERROR_SOCKET_RECV_NO_DATA || error == RMT_ERROR_SOCKET_RECV_TIMEOUT)
-        {
-            now_ms = msTimer_Get();
-            if (now_ms - start_ms > 1000)
-                return RMT_ERROR_SOCKET_RECV_TIMEOUT;
-
-            continue;
-        }
-
-        // Just in case new enums are added...
-        assert(error == RMT_ERROR_NONE);
-
-        if (buffer_ptr - buffer >= 4)
-        {
-            if (*(buffer_ptr - 3) == '\r' &&
-                *(buffer_ptr - 2) == '\n' &&
-                *(buffer_ptr - 1) == '\r' &&
-                *(buffer_ptr - 0) == '\n')
-                break;
-        }
-
-        buffer_ptr++;
-    }
-    *buffer_ptr = 0;
-
-    // HTTP GET instruction
-    if (memcmp(buffer, "GET", 3) != 0)
-        return RMT_ERROR_WEBSOCKET_HANDSHAKE_NOT_GET;
-
-    // Look for the version number and verify that it's supported
-    version = GetField(buffer, buffer_len, "Sec-WebSocket-Version:");
-    if (version == NULL)
-        return RMT_ERROR_WEBSOCKET_HANDSHAKE_NO_VERSION;
-    if (buffer_end - version < 2 || (version[0] != '8' && (version[0] != '1' || version[1] != '3')))
-        return RMT_ERROR_WEBSOCKET_HANDSHAKE_BAD_VERSION;
-
-    // Make sure this connection comes from a known host
-    host = GetField(buffer, buffer_len, "Host:");
-    if (host == NULL)
-        return RMT_ERROR_WEBSOCKET_HANDSHAKE_NO_HOST;
-    if (limit_host != NULL)
-    {
-        rsize_t limit_host_len = strnlen_s(limit_host, 128);
-        char* found = NULL;
-        if (strstr_s(host, buffer_end - host, limit_host, limit_host_len, &found) != EOK)
-            return RMT_ERROR_WEBSOCKET_HANDSHAKE_BAD_HOST;
-    }
-
-    // Look for the key start and null-terminate it within the receive buffer
-    key = GetField(buffer, buffer_len, "Sec-WebSocket-Key:");
-    if (key == NULL)
-        return RMT_ERROR_WEBSOCKET_HANDSHAKE_NO_KEY;
-    if (strstr_s(key, buffer_end - key, "\r\n", 2, &key_end) != EOK)
-        return RMT_ERROR_WEBSOCKET_HANDSHAKE_BAD_KEY;
-    *key_end = 0;
-
-    // Concatenate the browser's key with the WebSocket Protocol GUID and base64 encode
-    // the hash, to prove to the browser that this is a bonafide WebSocket server
-    buffer[0] = 0;
-    if (strncat_s(buffer, buffer_len, key, key_end - key) != EOK)
-        return RMT_ERROR_WEBSOCKET_HANDSHAKE_STRING_FAIL;
-    if (strncat_s(buffer, buffer_len, websocket_guid, sizeof(websocket_guid)) != EOK)
-        return RMT_ERROR_WEBSOCKET_HANDSHAKE_STRING_FAIL;
-    hash = SHA1_Calculate(buffer, (rmtU32)strnlen_s(buffer, buffer_len));
-    Base64_Encode(hash.data, sizeof(hash.data), (rmtU8*)buffer);
-
-    // Send the response back to the server with a longer timeout than usual
-    response_buffer[0] = 0;
-    if (strncat_s(response_buffer, response_buffer_len, websocket_response, sizeof(websocket_response)) != EOK)
-        return RMT_ERROR_WEBSOCKET_HANDSHAKE_STRING_FAIL;
-    if (strncat_s(response_buffer, response_buffer_len, buffer, buffer_len) != EOK)
-        return RMT_ERROR_WEBSOCKET_HANDSHAKE_STRING_FAIL;
-    if (strncat_s(response_buffer, response_buffer_len, "\r\n\r\n", 4) != EOK)
-        return RMT_ERROR_WEBSOCKET_HANDSHAKE_STRING_FAIL;
-
-    return TCPSocket_Send(tcp_socket, response_buffer, (rmtU32)strnlen_s(response_buffer, response_buffer_len), 1000);
-}
-
-
-static rmtError WebSocket_Constructor(WebSocket* web_socket, TCPSocket* tcp_socket)
-{
-    rmtError error = RMT_ERROR_NONE;
-
-    assert(web_socket != NULL);
-    web_socket->tcp_socket = tcp_socket;
-    web_socket->mode = WEBSOCKET_NONE;
-    web_socket->frame_bytes_remaining = 0;
-    web_socket->mask_offset = 0;
-    web_socket->data.mask[0] = 0;
-    web_socket->data.mask[1] = 0;
-    web_socket->data.mask[2] = 0;
-    web_socket->data.mask[3] = 0;
-
-    // Caller can optionally specify which TCP socket to use
-    if (web_socket->tcp_socket == NULL)
-        New_0(TCPSocket, web_socket->tcp_socket);
-
-    return error;
-}
-
-
-static void WebSocket_Destructor(WebSocket* web_socket)
-{
-    WebSocket_Close(web_socket);
-}
-
-
-static rmtError WebSocket_RunServer(WebSocket* web_socket, rmtU16 port, rmtBool limit_connections_to_localhost, enum WebSocketMode mode)
-{
-    // Create the server's listening socket
-    assert(web_socket != NULL);
-    web_socket->mode = mode;
-    return TCPSocket_RunServer(web_socket->tcp_socket, port, limit_connections_to_localhost);
-}
-
-
-static void WebSocket_Close(WebSocket* web_socket)
-{
-    assert(web_socket != NULL);
-    Delete(TCPSocket, web_socket->tcp_socket);
-}
-
-
-static SocketStatus WebSocket_PollStatus(WebSocket* web_socket)
-{
-    assert(web_socket != NULL);
-    return TCPSocket_PollStatus(web_socket->tcp_socket);
-}
-
-
-static rmtError WebSocket_AcceptConnection(WebSocket* web_socket, WebSocket** client_socket)
-{
-    TCPSocket* tcp_socket = NULL;
-    rmtError error;
-
-    // Is there a waiting connection?
-    assert(web_socket != NULL);
-    error = TCPSocket_AcceptConnection(web_socket->tcp_socket, &tcp_socket);
-    if (error != RMT_ERROR_NONE || tcp_socket == NULL)
-        return error;
-
-    // Need a successful handshake between client/server before allowing the connection
-    // TODO: Specify limit_host
-    error = WebSocketHandshake(tcp_socket, NULL);
-    if (error != RMT_ERROR_NONE)
-        return error;
-
-    // Allocate and return a new client socket
-    assert(client_socket != NULL);
-    New_1(WebSocket, *client_socket, tcp_socket);
-    if (error != RMT_ERROR_NONE)
-        return error;
-
-    (*client_socket)->mode = web_socket->mode;
-
-    return RMT_ERROR_NONE;
-}
-
-
-static void WriteSize(rmtU32 size, rmtU8* dest, rmtU32 dest_size, rmtU32 dest_offset)
-{
-    int size_size = dest_size - dest_offset;
-    rmtU32 i;
-    for (i = 0; i < dest_size; i++)
-    {
-        int j = i - dest_offset;
-        dest[i] = (j < 0) ? 0 : (size >> ((size_size - j - 1) * 8)) & 0xFF;
-    }
-}
-
-
-static rmtError WebSocket_Send(WebSocket* web_socket, const void* data, rmtU32 length, rmtU32 timeout_ms)
-{
-    rmtError error;
-    SocketStatus status;
-    rmtU8 final_fragment, frame_type, frame_header[10];
-    rmtU32 frame_header_size;
-
-    assert(web_socket != NULL);
-
-    // Can't send if there are socket errors
-    status = WebSocket_PollStatus(web_socket);
-    if (status.error_state != RMT_ERROR_NONE)
-        return status.error_state;
-
-    final_fragment = 0x1 << 7;
-    frame_type = (rmtU8)web_socket->mode;
-    frame_header[0] = final_fragment | frame_type;
-
-    // Construct the frame header, correctly applying the narrowest size
-    frame_header_size = 0;
-    if (length <= 125)
-    {
-        frame_header_size = 2;
-        frame_header[1] = (rmtU8)length;
-    }
-    else if (length <= 65535)
-    {
-        frame_header_size = 2 + 2;
-        frame_header[1] = 126;
-        WriteSize(length, frame_header + 2, 2, 0);
-    }
-    else
-    {
-        frame_header_size = 2 + 8;
-        frame_header[1] = 127;
-        WriteSize(length, frame_header + 2, 8, 4);
-    }
-
-    // Send frame header
-    assert(data != NULL);
-    error = TCPSocket_Send(web_socket->tcp_socket, frame_header, frame_header_size, timeout_ms);
-    if (error != RMT_ERROR_NONE)
-        return error;
-
-    // Send frame data separately so that we don't have to allocate memory or memcpy it into
-    // the same buffer as the header.
-    // If this step times out then the frame data will be discarded and the browser will receive
-    // an invalid frame without its data, forcing a disconnect error.
-    // Before things get that far, flag this as a send fail and let the server schedule a graceful
-    // disconnect.
-    error = TCPSocket_Send(web_socket->tcp_socket, data, length, timeout_ms);
-    if (error == RMT_ERROR_SOCKET_SEND_TIMEOUT)
-        error = RMT_ERROR_SOCKET_SEND_FAIL;
-
-    return error;
-}
-
-
-static rmtError ReceiveFrameHeader(WebSocket* web_socket)
-{
-    // TODO: Specify infinite timeout?
-
-    rmtError error;
-    rmtU8 msg_header[2] = { 0, 0 };
-    int msg_length, size_bytes_remaining, i;
-    rmtBool mask_present;
-
-    assert(web_socket != NULL);
-
-    // Get message header
-    error = TCPSocket_Receive(web_socket->tcp_socket, msg_header, 2, 20);
-    if (error != RMT_ERROR_NONE)
-        return error;
-
-    // Check for WebSocket Protocol disconnect
-    if (msg_header[0] == 0x88)
-        return RMT_ERROR_WEBSOCKET_DISCONNECTED;
-
-    // Check that the client isn't sending messages we don't understand
-    if (msg_header[0] != 0x81 && msg_header[0] != 0x82)
-        return RMT_ERROR_WEBSOCKET_BAD_FRAME_HEADER;
-
-    // Get message length and check to see if it's a marker for a wider length
-    msg_length = msg_header[1] & 0x7F;
-    size_bytes_remaining = 0;
-    switch (msg_length)
-    {
-        case 126: size_bytes_remaining = 2; break;
-        case 127: size_bytes_remaining = 8; break;
-    }
-
-    if (size_bytes_remaining > 0)
-    {
-        // Receive the wider bytes of the length
-        rmtU8 size_bytes[4];
-        error = TCPSocket_Receive(web_socket->tcp_socket, size_bytes, size_bytes_remaining, 20);
-        if (error != RMT_ERROR_NONE)
-            return RMT_ERROR_WEBSOCKET_BAD_FRAME_HEADER_SIZE;
-
-        // Calculate new length, MSB first
-        msg_length = 0;
-        for (i = 0; i < size_bytes_remaining; i++)
-            msg_length |= size_bytes[i] << ((size_bytes_remaining - 1 - i) * 8);
-    }
-
-    // Receive any message data masks
-    mask_present = (msg_header[1] & 0x80) != 0 ? RMT_TRUE : RMT_FALSE;
-    if (mask_present)
-    {
-        error = TCPSocket_Receive(web_socket->tcp_socket, web_socket->data.mask, 4, 20);
-        if (error != RMT_ERROR_NONE)
-            return error;
-    }
-
-    web_socket->frame_bytes_remaining = msg_length;
-    web_socket->mask_offset = 0;
-
-    return RMT_ERROR_NONE;
-}
-
-
-static rmtError WebSocket_Receive(WebSocket* web_socket, void* data, rmtU32* msg_len, rmtU32 length, rmtU32 timeout_ms)
-{
-    SocketStatus status;
-    char* cur_data;
-    char* end_data;
-    rmtU32 start_ms, now_ms;
-    rmtU32 bytes_to_read;
-    rmtError error;
-
-    assert(web_socket != NULL);
-
-    // Can't read with any socket errors
-    status = WebSocket_PollStatus(web_socket);
-    if (status.error_state != RMT_ERROR_NONE)
-        return status.error_state;
-
-    cur_data = (char*)data;
-    end_data = cur_data + length;
-
-    start_ms = msTimer_Get();
-    while (cur_data < end_data)
-    {
-        // Get next WebSocket frame if we've run out of data to read from the socket
-        if (web_socket->frame_bytes_remaining == 0)
-        {
-            error = ReceiveFrameHeader(web_socket);
-            if (error != RMT_ERROR_NONE)
-                return error;
-
-            // Set output message length only on initial receive
-            if (msg_len != NULL)
-                *msg_len = web_socket->frame_bytes_remaining;
-        }
-
-        // Read as much required data as possible
-        bytes_to_read = web_socket->frame_bytes_remaining < length ? web_socket->frame_bytes_remaining : length;
-        error = TCPSocket_Receive(web_socket->tcp_socket, cur_data, bytes_to_read, 20);
-        if (error == RMT_ERROR_SOCKET_RECV_FAILED)
-            return error;
-
-        // If there's a stall receiving the data, check for timeout
-        if (error == RMT_ERROR_SOCKET_RECV_NO_DATA || error == RMT_ERROR_SOCKET_RECV_TIMEOUT)
-        {
-            now_ms = msTimer_Get();
-            if (now_ms - start_ms > timeout_ms)
-                return RMT_ERROR_SOCKET_RECV_TIMEOUT;
-            continue;
-        }
-
-        // Apply data mask
-        if (web_socket->data.mask_u32 != 0)
-        {
-            rmtU32 i;
-            for (i = 0; i < bytes_to_read; i++)
-            {
-                *((rmtU8*)cur_data + i) ^= web_socket->data.mask[web_socket->mask_offset & 3];
-                web_socket->mask_offset++;
-            }
-        }
-
-        cur_data += bytes_to_read;
-        web_socket->frame_bytes_remaining -= bytes_to_read;
-    }
-
-    return RMT_ERROR_NONE;
-}
-
-
-
-/*
-------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------
-   @MESSAGEQ: Multiple producer, single consumer message queue
-------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------
-*/
-
-
-typedef enum MessageID
-{
-    MsgID_NotReady,
-    MsgID_LogText,
-    MsgID_SampleTree,
-} MessageID;
-
-
-typedef struct Message
-{
-    MessageID id;
-
-    rmtU32 payload_size;
-
-    // For telling which thread the message came from in the debugger
-    struct ThreadSampler* thread_sampler;
-
-    rmtU8 payload[1];
-} Message;
-
-
-// Multiple producer, single consumer message queue that uses its own data buffer
-// to store the message data.
-typedef struct rmtMessageQueue
-{
-    rmtU32 size;
-
-    // The physical address of this data buffer is pointed to by two sequential
-    // virtual memory pages, allowing automatic wrap-around of any reads or writes
-    // that exceed the limits of the buffer.
-    VirtualMirrorBuffer* data;
-
-    // Read/write position never wrap allowing trivial overflow checks
-    // with easier debugging
-    rmtU32 read_pos;
-    rmtU32 write_pos;
-
-} rmtMessageQueue;
-
-
-static rmtError rmtMessageQueue_Constructor(rmtMessageQueue* queue, rmtU32 size)
-{
-    rmtError error;
-
-    assert(queue != NULL);
-
-    // Set defaults
-    queue->size = 0;
-    queue->data = NULL;
-    queue->read_pos = 0;
-    queue->write_pos = 0;
-
-    New_2(VirtualMirrorBuffer, queue->data, size, 10);
-    if (error != RMT_ERROR_NONE)
-        return error;
-
-    // The mirror buffer needs to be page-aligned and will change the requested
-    // size to match that.
-    queue->size = queue->data->size;
-
-    // Set the entire buffer to not ready message
-    memset(queue->data->ptr, MsgID_NotReady, queue->size);
-
-    return RMT_ERROR_NONE;
-}
-
-
-static void rmtMessageQueue_Destructor(rmtMessageQueue* queue)
-{
-    assert(queue != NULL);
-    Delete(VirtualMirrorBuffer, queue->data);
-}
-
-
-static rmtU32 rmtMessageQueue_SizeForPayload(rmtU32 payload_size)
-{
-    // Add message header and align for ARM platforms
-    rmtU32 size = sizeof(Message) + payload_size;
-    size = (size + 3) & ~3U;
-    return size;
-}
-
-
-static Message* rmtMessageQueue_AllocMessage(rmtMessageQueue* queue, rmtU32 payload_size, struct ThreadSampler* thread_sampler)
-{
-    Message* msg;
-
-    rmtU32 write_size = rmtMessageQueue_SizeForPayload(payload_size);
-
-    assert(queue != NULL);
-
-    for (;;)
-    {
-        // Check for potential overflow
-        rmtU32 s = queue->size;
-        rmtU32 r = queue->read_pos;
-        rmtU32 w = queue->write_pos;
-        if ((int)(w - r) > ((int)(s - write_size)))
-            return NULL;
-
-        // Point to the newly allocated space
-        msg = (Message*)(queue->data->ptr + (w & (s - 1)));
-
-        // Increment the write position, leaving the loop if this is the thread that succeeded
-        if (AtomicCompareAndSwap(&queue->write_pos, w, w + write_size) == RMT_TRUE)
-        {
-            // Safe to set payload size after thread claims ownership of this allocated range
-            msg->payload_size = payload_size;
-            msg->thread_sampler = thread_sampler;
-            break;
-        }
-    }
-
-    return msg;
-}
-
-
-static void rmtMessageQueue_CommitMessage(Message* message, MessageID id)
-{
-    assert(message != NULL);
-
-    // Ensure message writes complete before commit
-    WriteFence();
-
-    // Setting the message ID signals to the consumer that the message is ready
-    assert(message->id == MsgID_NotReady);
-    message->id = id;
-}
-
-
-Message* rmtMessageQueue_PeekNextMessage(rmtMessageQueue* queue)
-{
-    Message* ptr;
-    rmtU32 r;
-
-    assert(queue != NULL);
-
-    // First check that there are bytes queued
-    if (queue->write_pos - queue->read_pos == 0)
-        return NULL;
-
-    // Messages are in the queue but may not have been commit yet
-    // Messages behind this one may have been commit but it's not reachable until
-    // the next one in the queue is ready.
-    r = queue->read_pos & (queue->size - 1);
-    ptr = (Message*)(queue->data->ptr + r);
-    if (ptr->id != MsgID_NotReady)
-        return ptr;
-
-    return NULL;
-}
-
-
-static void rmtMessageQueue_ConsumeNextMessage(rmtMessageQueue* queue, Message* message)
-{
-    rmtU32 message_size;
-
-    assert(queue != NULL);
-    assert(message != NULL);
-
-    // Setting the message ID to "not ready" serves as a marker to the consumer that even though
-    // space has been allocated for a message, the message isn't ready to be consumed
-    // yet.
-    //
-    // We can't do that when allocating the message because multiple threads will be fighting for
-    // the same location. Instead, clear out any messages just read by the consumer before advancing
-    // the read position so that a winning thread's allocation will inherit the "not ready" state.
-    //
-    // This costs some write bandwidth and has the potential to flush cache to other cores.
-    message_size = rmtMessageQueue_SizeForPayload(message->payload_size);
-    memset(message, MsgID_NotReady, message_size);
-
-    // Ensure clear completes before advancing the read position
-    WriteFence();
-    queue->read_pos += message_size;
-}
-
-
-static rmtBool rmtMessageQueue_IsEmpty(rmtMessageQueue* queue)
-{
-    assert(queue != NULL);
-    return queue->write_pos - queue->read_pos == 0;
-}
-
-
-/*
-------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------
-   @NETWORK: Network Server
-------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------
-*/
-
-
-typedef rmtError (*Server_ReceiveHandler)(void*, char*, rmtU32);
-
-
-typedef struct
-{
-    WebSocket* listen_socket;
-
-    WebSocket* client_socket;
-
-    rmtU32 last_ping_time;
-
-    rmtU16 port;
-    rmtBool limit_connections_to_localhost;
-
-    // Handler for receiving messages from the client
-    Server_ReceiveHandler receive_handler;
-    void* receive_handler_context;
-} Server;
-
-
-static rmtError Server_CreateListenSocket(Server* server, rmtU16 port, rmtBool limit_connections_to_localhost)
-{
-    rmtError error = RMT_ERROR_NONE;
-
-    New_1(WebSocket, server->listen_socket, NULL);
-    if (error == RMT_ERROR_NONE)
-        error = WebSocket_RunServer(server->listen_socket, port, limit_connections_to_localhost, WEBSOCKET_BINARY);
-
-    return error;
-}
-
-
-static rmtError Server_Constructor(Server* server, rmtU16 port, rmtBool limit_connections_to_localhost)
-{
-    assert(server != NULL);
-    server->listen_socket = NULL;
-    server->client_socket = NULL;
-    server->last_ping_time = 0;
-    server->port = port;
-    server->limit_connections_to_localhost = limit_connections_to_localhost;
-    server->receive_handler = NULL;
-    server->receive_handler_context = NULL;
-
-    // Create the listening WebSocket
-    return Server_CreateListenSocket(server, port, limit_connections_to_localhost);
-}
-
-
-static void Server_Destructor(Server* server)
-{
-    assert(server != NULL);
-    Delete(WebSocket, server->client_socket);
-    Delete(WebSocket, server->listen_socket);
-}
-
-
-static rmtBool Server_IsClientConnected(Server* server)
-{
-    assert(server != NULL);
-    return server->client_socket != NULL ? RMT_TRUE : RMT_FALSE;
-}
-
-
-static void Server_DisconnectClient(Server* server)
-{
-    WebSocket* client_socket;
-
-    assert(server != NULL);
-
-    // NULL the variable before destroying the socket
-    client_socket = server->client_socket;
-    server->client_socket = NULL;
-    WriteFence();
-    Delete(WebSocket, client_socket);
-}
-
-
-static rmtError Server_Send(Server* server, const void* data, rmtU32 length, rmtU32 timeout)
-{
-    assert(server != NULL);
-    if (Server_IsClientConnected(server))
-    {
-        rmtError error = WebSocket_Send(server->client_socket, data, length, timeout);
-        if (error == RMT_ERROR_SOCKET_SEND_FAIL)
-            Server_DisconnectClient(server);
-
-        return error;
-    }
-
-    return RMT_ERROR_NONE;
-}
-
-
-static rmtError Server_ReceiveMessage(Server* server, char message_first_byte, rmtU32 message_length)
-{
-    char message_data[1024];
-    rmtError error;
-
-    // Check for potential message data overflow
-    if (message_length >= sizeof(message_data) - 1)
-    {
-        rmt_LogText("Ignoring console input bigger than internal receive buffer (1024 bytes)");
-        return RMT_ERROR_NONE;
-    }
-
-    // Receive the rest of the message
-    message_data[0] = message_first_byte;
-    error = WebSocket_Receive(server->client_socket, message_data + 1, NULL, message_length - 1, 100);
-    if (error != RMT_ERROR_NONE)
-        return error;
-    message_data[message_length] = 0;
-
-    // Each message must have a descriptive 4 byte header
-    if (message_length < 4)
-        return RMT_ERROR_NONE;
-
-    // Dispatch to handler
-    if (server->receive_handler)
-        error = server->receive_handler(server->receive_handler_context, message_data, message_length);
-
-    return error;
-}
-
-
-static void Server_Update(Server* server)
-{
-    rmtU32 cur_time;
-
-    assert(server != NULL);
-
-    // Recreate the listening socket if it's been destroyed earlier
-    if (server->listen_socket == NULL)
-        Server_CreateListenSocket(server, server->port, server->limit_connections_to_localhost);
-
-    if (server->listen_socket != NULL && server->client_socket == NULL)
-    {
-        // Accept connections as long as there is no client connected
-        WebSocket* client_socket = NULL;
-        rmtError error = WebSocket_AcceptConnection(server->listen_socket, &client_socket);
-        if (error == RMT_ERROR_NONE)
-        {
-            server->client_socket = client_socket;
-        }
-        else
-        {
-            // Destroy the listen socket on failure to accept
-            // It will get recreated in another update
-            Delete(WebSocket, server->listen_socket);
-        }
-    }
-
-    else
-    {
-        // Loop checking for incoming messages
-        for (;;)
-        {
-            // Inspect first byte to see if a message is there
-            char message_first_byte;
-            rmtU32 message_length;
-            rmtError error = WebSocket_Receive(server->client_socket, &message_first_byte, &message_length, 1, 0);
-            if (error == RMT_ERROR_NONE)
-            {
-                // Parse remaining message
-                error = Server_ReceiveMessage(server, message_first_byte, message_length);
-                if (error != RMT_ERROR_NONE)
-                {
-                    Server_DisconnectClient(server);
-                    break;
-                }
-
-                // Check for more...
-                continue;
-            }
-
-            // Passable errors...
-            if (error == RMT_ERROR_SOCKET_RECV_NO_DATA)
-            {
-                // No data available
-                break;
-            }
-
-            if (error == RMT_ERROR_SOCKET_RECV_TIMEOUT)
-            {
-                // Data not available yet, can afford to ignore as we're only reading the first byte
-                break;
-            }
-
-            // Anything else is an error that may have closed the connection
-            Server_DisconnectClient(server);
-            break;
-        }
-    }
-
-    // Send pings to the client every second
-    cur_time = msTimer_Get();
-    if (cur_time - server->last_ping_time > 1000)
-    {
-        rmtPStr ping_message = "PING";
-        Server_Send(server, ping_message, (rmtU32)strlen(ping_message), 4);
-        server->last_ping_time = cur_time;
-    }
-}
-
-
-
-/*
-------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------
-   @SAMPLE: Base Sample Description for CPU by default
-------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------
-*/
-
-
-
-#define SAMPLE_NAME_LEN 128
-
-
-enum SampleType
-{
-    SampleType_CPU,
-    SampleType_CUDA,
-    SampleType_D3D11,
-    SampleType_OpenGL,
-    SampleType_Metal,
-    SampleType_Count,
-};
-
-
-typedef struct Sample
-{
-    // Inherit so that samples can be quickly allocated
-    ObjectLink Link;
-
-    enum SampleType type;
-
-    // Used to anonymously copy sample data without knowning its type
-    rmtU32 size_bytes;
-
-    // Hash generated from sample name
-    rmtU32 name_hash;
-
-    // Unique, persistent ID among all samples
-    rmtU32 unique_id;
-
-    // Null-terminated string storing the hash-prefixed 6-digit colour
-    rmtU8 unique_id_html_colour[8];
-
-    // Links to related samples in the tree
-    struct Sample* parent;
-    struct Sample* first_child;
-    struct Sample* last_child;
-    struct Sample* next_sibling;
-
-    // Keep track of child count to distinguish from repeated calls to the same function at the same stack level
-    // This is also mixed with the callstack hash to allow consistent addressing of any point in the tree
-    rmtU32 nb_children;
-
-    // Sample end points and length in microseconds
-    rmtU64 us_start;
-    rmtU64 us_end;
-    rmtU64 us_length;
-
-} Sample;
-
-
-static rmtError Sample_Constructor(Sample* sample)
-{
-    assert(sample != NULL);
-
-    ObjectLink_Constructor((ObjectLink*)sample);
-
-    sample->type = SampleType_CPU;
-    sample->size_bytes = sizeof(Sample);
-    sample->name_hash = 0;
-    sample->unique_id = 0;
-    sample->unique_id_html_colour[0] = '#';
-    sample->unique_id_html_colour[1] = 0;
-    sample->unique_id_html_colour[7] = 0;
-    sample->parent = NULL;
-    sample->first_child = NULL;
-    sample->last_child = NULL;
-    sample->next_sibling = NULL;
-    sample->nb_children = 0;
-    sample->us_start = 0;
-    sample->us_end = 0;
-    sample->us_length = 0;
-
-    return RMT_ERROR_NONE;
-}
-
-
-static void Sample_Destructor(Sample* sample)
-{
-    RMT_UNREFERENCED_PARAMETER(sample);
-}
-
-
-static void Sample_Prepare(Sample* sample, rmtU32 name_hash, Sample* parent)
-{
-    sample->name_hash = name_hash;
-    sample->unique_id = 0;
-    sample->parent = parent;
-    sample->first_child = NULL;
-    sample->last_child = NULL;
-    sample->next_sibling = NULL;
-    sample->nb_children = 0;
-    sample->us_start = 0;
-    sample->us_end = 0;
-    sample->us_length = 0;
-}
-
-
-#define BIN_ERROR_CHECK(stmt) { error = stmt; if (error != RMT_ERROR_NONE) return error; }
-
-
-static rmtError bin_SampleArray(Buffer* buffer, Sample* first_sample);
-
-
-static rmtError bin_Sample(Buffer* buffer, Sample* sample)
-{
-    rmtError error;
-
-    assert(sample != NULL);
-
-    BIN_ERROR_CHECK(Buffer_WriteU32(buffer, sample->name_hash));
-    BIN_ERROR_CHECK(Buffer_WriteU32(buffer, sample->unique_id));
-    BIN_ERROR_CHECK(Buffer_Write(buffer, sample->unique_id_html_colour, 7));
-    BIN_ERROR_CHECK(Buffer_WriteU64(buffer, sample->us_start));
-    BIN_ERROR_CHECK(Buffer_WriteU64(buffer, maxS64(sample->us_length, 0)));
-    BIN_ERROR_CHECK(bin_SampleArray(buffer, sample));
-
-    return RMT_ERROR_NONE;
-}
-
-
-static rmtError bin_SampleArray(Buffer* buffer, Sample* parent_sample)
-{
-    rmtError error;
-    Sample* sample;
-
-    BIN_ERROR_CHECK(Buffer_WriteU32(buffer, parent_sample->nb_children));
-    for (sample = parent_sample->first_child; sample != NULL; sample = sample->next_sibling)
-        BIN_ERROR_CHECK(bin_Sample(buffer, sample));
-
-    return RMT_ERROR_NONE;
-}
-
-
-
-/*
-------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------
-   @SAMPLETREE: A tree of samples with their allocator
-------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------
-*/
-
-
-
-typedef struct SampleTree
-{
-    // Allocator for all samples
-    ObjectAllocator* allocator;
-
-    // Root sample for all samples created by this thread
-    Sample* root;
-
-    // Most recently pushed sample
-    Sample* current_parent;
-
-} SampleTree;
-
-
-static rmtError SampleTree_Constructor(SampleTree* tree, rmtU32 sample_size, ObjConstructor constructor, ObjDestructor destructor)
-{
-    rmtError error;
-
-    assert(tree != NULL);
-
-    tree->allocator = NULL;
-    tree->root = NULL;
-    tree->current_parent = NULL;
-
-    // Create the sample allocator
-    New_3(ObjectAllocator, tree->allocator, sample_size, constructor, destructor);
-    if (error != RMT_ERROR_NONE)
-        return error;
-
-    // Create a root sample that's around for the lifetime of the thread
-    error = ObjectAllocator_Alloc(tree->allocator, (void**)&tree->root);
-    if (error != RMT_ERROR_NONE)
-        return error;
-    Sample_Prepare(tree->root, 0, NULL);
-    tree->current_parent = tree->root;
-
-    return RMT_ERROR_NONE;
-}
-
-
-static void SampleTree_Destructor(SampleTree* tree)
-{
-    assert(tree != NULL);
-
-    if (tree->root != NULL)
-    {
-        ObjectAllocator_Free(tree->allocator, tree->root);
-        tree->root = NULL;
-    }
-
-    Delete(ObjectAllocator, tree->allocator);
-}
-
-
-static rmtU32 HashCombine(rmtU32 hash_a, rmtU32 hash_b)
-{
-    // A sequence of 32 uniformly random bits so that each bit of the combined hash is changed on application
-    // Derived from the golden ratio: UINT_MAX / ((1 + sqrt(5)) / 2)
-    // In reality it's just an arbitrary value which happens to work well, avoiding mapping all zeros to zeros.
-    // http://burtleburtle.net/bob/hash/doobs.html
-    static rmtU32 random_bits = 0x9E3779B9;
-    hash_a ^= hash_b + random_bits + (hash_a << 6) + (hash_a >> 2);
-    return hash_a;
-}
-
-
-static rmtError SampleTree_Push(SampleTree* tree, rmtU32 name_hash, rmtU32 flags, Sample** sample)
-{
-    Sample* parent;
-    rmtError error;
-    rmtU32 unique_id;
-
-    // As each tree has a root sample node allocated, a parent must always be present
-    assert(tree != NULL);
-    assert(tree->current_parent != NULL);
-    parent = tree->current_parent;
-
-    if ((flags & RMTSF_Aggregate) != 0)
-    {
-        // Linear search for previous instance of this sample name
-        Sample* sibling;
-        for (sibling = parent->first_child; sibling != NULL; sibling = sibling->next_sibling)
-        {
-            if (sibling->name_hash == name_hash)
-            {
-                tree->current_parent = sibling;
-                *sample = sibling;
-                return RMT_ERROR_NONE;
-            }
-        }
-    }
-
-    if (parent->name_hash == name_hash)
-    {
-        // TODO: Collapse recursion on flag?
-    }
-
-    // Allocate a new sample
-    error = ObjectAllocator_Alloc(tree->allocator, (void**)sample);
-    if (error != RMT_ERROR_NONE)
-        return error;
-    Sample_Prepare(*sample, name_hash, parent);
-
-    // Generate a unique ID for this sample in the tree
-    unique_id = parent->unique_id;
-    unique_id = HashCombine(unique_id, (*sample)->name_hash);
-    unique_id = HashCombine(unique_id, parent->nb_children);
-    (*sample)->unique_id = unique_id;
-
-    // Add sample to its parent
-    parent->nb_children++;
-    if (parent->first_child == NULL)
-    {
-        parent->first_child = *sample;
-        parent->last_child = *sample;
-    }
-    else
-    {
-        assert(parent->last_child != NULL);
-        parent->last_child->next_sibling = *sample;
-        parent->last_child = *sample;
-    }
-
-    // Make this sample the new parent of any newly created samples
-    tree->current_parent = *sample;
-
-    return RMT_ERROR_NONE;
-}
-
-
-static void SampleTree_Pop(SampleTree* tree, Sample* sample)
-{
-    assert(tree != NULL);
-    assert(sample != NULL);
-    assert(sample != tree->root);
-    tree->current_parent = sample->parent;
-}
-
-
-static ObjectLink* FlattenSampleTree(Sample* sample, rmtU32* nb_samples)
-{
-    Sample* child;
-    ObjectLink* cur_link = &sample->Link;
-
-    assert(sample != NULL);
-    assert(nb_samples != NULL);
-
-    *nb_samples += 1;
-    sample->Link.next = (ObjectLink*)sample->first_child;
-
-    // Link all children together
-    for (child = sample->first_child; child != NULL; child = child->next_sibling)
-    {
-        ObjectLink* last_link = FlattenSampleTree(child, nb_samples);
-        last_link->next = (ObjectLink*)child->next_sibling;
-        cur_link = last_link;
-    }
-
-    // Clear child info
-    sample->first_child = NULL;
-    sample->last_child = NULL;
-    sample->nb_children = 0;
-
-    return cur_link;
-}
-
-
-static void FreeSampleTree(Sample* sample, ObjectAllocator* allocator)
-{
-    // Chain all samples together in a flat list
-    rmtU32 nb_cleared_samples = 0;
-    ObjectLink* last_link = FlattenSampleTree(sample, &nb_cleared_samples);
-
-    // Release the complete sample memory range
-    if (sample->Link.next != NULL)
-        ObjectAllocator_FreeRange(allocator, sample, last_link, nb_cleared_samples);
-    else
-        ObjectAllocator_Free(allocator, sample);
-}
-
-
-typedef struct Msg_SampleTree
-{
-    Sample* root_sample;
-
-    ObjectAllocator* allocator;
-
-    rmtPStr thread_name;
-} Msg_SampleTree;
-
-
-static void AddSampleTreeMessage(rmtMessageQueue* queue, Sample* sample, ObjectAllocator* allocator, rmtPStr thread_name, struct ThreadSampler* thread_sampler)
-{
-    Msg_SampleTree* payload;
-
-    // Attempt to allocate a message for sending the tree to the viewer
-    Message* message = rmtMessageQueue_AllocMessage(queue, sizeof(Msg_SampleTree), thread_sampler);
-    if (message == NULL)
-    {
-        // Discard the tree on failure
-        FreeSampleTree(sample, allocator);
-        return;
-    }
-
-    // Populate and commit
-    payload = (Msg_SampleTree*)message->payload;
-    payload->root_sample = sample;
-    payload->allocator = allocator;
-    payload->thread_name = thread_name;
-    rmtMessageQueue_CommitMessage(message, MsgID_SampleTree);
-}
-
-
-
-
-/*
-------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------
-   @TSAMPLER: Per-Thread Sampler
-------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------
-*/
-
-
-
-typedef struct ThreadSampler
-{
-    // Name to assign to the thread in the viewer
-    rmtS8 name[64];
-
-    // Store a unique sample tree for each type
-    SampleTree* sample_trees[SampleType_Count];
-
-    // Table of all sample names encountered on this thread
-    StringTable* names;
-
-    // Next in the global list of active thread samplers
-    struct ThreadSampler* volatile next;
-
-} ThreadSampler;
-
-static rmtError ThreadSampler_Constructor(ThreadSampler* thread_sampler)
-{
-    rmtError error;
-    int i;
-
-    assert(thread_sampler != NULL);
-
-    // Set defaults
-    for (i = 0; i < SampleType_Count; i++)
-        thread_sampler->sample_trees[i] = NULL;
-    thread_sampler->names = NULL;
-    thread_sampler->next = NULL;
-
-    // Set the initial name to Thread0 etc. or use the existing Linux name.
-    thread_sampler->name[0] = 0;
-    #if defined(RMT_PLATFORM_LINUX) && RMT_USE_POSIX_THREADNAMES
-    prctl(PR_GET_NAME,thread_sampler->name,0,0,0);
-    #else
-    {
-        static rmtS32 countThreads = 0;
-        strncat_s(thread_sampler->name, sizeof(thread_sampler->name), "Thread", 6);
-        itoahex_s(thread_sampler->name + 6, sizeof(thread_sampler->name) - 6, AtomicAdd(&countThreads, 1));
-    }
-    #endif
-
-    // Create the CPU sample tree only - the rest are created on-demand as they need
-    // extra context information to function correctly.
-    New_3(SampleTree, thread_sampler->sample_trees[SampleType_CPU], sizeof(Sample), (ObjConstructor)Sample_Constructor, (ObjDestructor)Sample_Destructor);
-    if (error != RMT_ERROR_NONE)
-        return error;
-
-    // Create sample name string table
-    New_0(StringTable, thread_sampler->names);
-    if (error != RMT_ERROR_NONE)
-        return error;
-
-    return RMT_ERROR_NONE;
-}
-
-
-static void ThreadSampler_Destructor(ThreadSampler* ts)
-{
-    int i;
-
-    assert(ts != NULL);
-
-    Delete(StringTable, ts->names);
-
-    for (i = 0; i < SampleType_Count; i++)
-        Delete(SampleTree, ts->sample_trees[i]);
-}
-
-
-static rmtError ThreadSampler_Push(SampleTree* tree, rmtU32 name_hash, rmtU32 flags, Sample** sample)
-{
-    return SampleTree_Push(tree, name_hash, flags, sample);
-}
-
-
-static rmtBool ThreadSampler_Pop(ThreadSampler* ts, rmtMessageQueue* queue, Sample* sample)
-{
-    SampleTree* tree = ts->sample_trees[sample->type];
-    SampleTree_Pop(tree, sample);
-
-    // Are we back at the root?
-    if (tree->current_parent == tree->root)
-    {
-        // Disconnect all samples from the root and pack in the chosen message queue
-        Sample* root = tree->root;
-        root->first_child = NULL;
-        root->last_child = NULL;
-        root->nb_children = 0;
-        AddSampleTreeMessage(queue, sample, tree->allocator, ts->name, ts);
-
-        return RMT_TRUE;
-    }
-
-    return RMT_FALSE;
-}
-
-
-static rmtU32 ThreadSampler_GetNameHash(ThreadSampler* ts, rmtPStr name, rmtU32* hash_cache)
-{
-    rmtU32 name_hash = 0;
-
-    // Hash cache provided?
-    if (hash_cache != NULL)
-    {
-        // Calculate the hash first time round only
-        if (*hash_cache == 0)
-        {
-            assert(name != NULL);
-            *hash_cache = MurmurHash3_x86_32(name, (int)strnlen_s(name, 256), 0);
-
-            // Also add to the string table on its first encounter
-            StringTable_Insert(ts->names, *hash_cache, name);
-        }
-
-        return *hash_cache;
-    }
-
-    // Have to recalculate and speculatively insert the name every time when no cache storage exists
-    name_hash = MurmurHash3_x86_32(name, (int)strnlen_s(name, 256), 0);
-    StringTable_Insert(ts->names, name_hash, name);
-    return name_hash;
-}
-
-
-
-
-/*
-------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------
-   @REMOTERY: Remotery
-------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------
-*/
-
-
-
-#if RMT_USE_D3D11
-typedef struct D3D11 D3D11;
-static rmtError D3D11_Create(D3D11** d3d11);
-static void D3D11_Destructor(D3D11* d3d11);
-#endif
-
-
-#if RMT_USE_OPENGL
-typedef struct OpenGL_t OpenGL;
-static rmtError OpenGL_Create(OpenGL** opengl);
-static void OpenGL_Destructor(OpenGL* opengl);
-#endif
-
-
-#if RMT_USE_METAL
-typedef struct Metal_t Metal;
-static rmtError Metal_Create(Metal** metal);
-static void Metal_Destructor(Metal* metal);
-#endif
-
-
-struct Remotery
-{
-    Server* server;
-
-    // Microsecond accuracy timer for CPU timestamps
-    usTimer timer;
-
-    rmtTLS thread_sampler_tls_handle;
-
-    // Linked list of all known threads being sampled
-    ThreadSampler* volatile first_thread_sampler;
-
-    // Queue between clients and main remotery thread
-    rmtMessageQueue* mq_to_rmt_thread;
-
-    // A dynamically-sized buffer used for binary-encoding the sample tree and sending to the client
-    Buffer* bin_buf;
-
-    // The main server thread
-    rmtThread* thread;
-
-#if RMT_USE_CUDA
-    rmtCUDABind cuda;
-#endif
-
-#if RMT_USE_D3D11
-    D3D11* d3d11;
-#endif
-
-#if RMT_USE_OPENGL
-    OpenGL* opengl;
-#endif
-
-#if RMT_USE_METAL
-    Metal* metal;
-#endif
-};
-
-
-//
-// Global remotery context
-//
-static Remotery* g_Remotery = NULL;
-
-
-//
-// This flag marks the EXE/DLL that created the global remotery instance. We want to allow
-// only the creating EXE/DLL to destroy the remotery instance.
-//
-static rmtBool g_RemoteryCreated = RMT_FALSE;
-
-
-static void Remotery_DestroyThreadSamplers(Remotery* rmt);
-
-
-static const rmtU8 g_DecimalToHex[17] = "0123456789abcdef";
-
-
-static void GetSampleDigest(Sample* sample, rmtU32* digest_hash, rmtU32* nb_samples)
-{
-    Sample* child;
-
-    assert(sample != NULL);
-    assert(digest_hash != NULL);
-    assert(nb_samples != NULL);
-
-    // Concatenate this sample
-    (*nb_samples)++;
-    *digest_hash = MurmurHash3_x86_32(&sample->unique_id, sizeof(sample->unique_id), *digest_hash);
-
-    {
-        rmtU8 shift = 4;
-
-        // Get 6 nibbles for lower 3 bytes of the unique sample ID
-        rmtU8* sample_id = (rmtU8*)&sample->unique_id;
-        rmtU8 hex_sample_id[6];
-        hex_sample_id[0] = sample_id[0] & 15;
-        hex_sample_id[1] = sample_id[0] >> 4;
-        hex_sample_id[2] = sample_id[1] & 15;
-        hex_sample_id[3] = sample_id[1] >> 4;
-        hex_sample_id[4] = sample_id[2] & 15;
-        hex_sample_id[5] = sample_id[2] >> 4;
-
-        // As the nibbles will be used as hex colour digits, shift them up to make pastel colours
-        hex_sample_id[0] = minU8(hex_sample_id[0] + shift, 15);
-        hex_sample_id[1] = minU8(hex_sample_id[1] + shift, 15);
-        hex_sample_id[2] = minU8(hex_sample_id[2] + shift, 15);
-        hex_sample_id[3] = minU8(hex_sample_id[3] + shift, 15);
-        hex_sample_id[4] = minU8(hex_sample_id[4] + shift, 15);
-        hex_sample_id[5] = minU8(hex_sample_id[5] + shift, 15);
-
-        // Convert the nibbles to hex for the final colour
-        sample->unique_id_html_colour[1] = g_DecimalToHex[hex_sample_id[0]];
-        sample->unique_id_html_colour[2] = g_DecimalToHex[hex_sample_id[1]];
-        sample->unique_id_html_colour[3] = g_DecimalToHex[hex_sample_id[2]];
-        sample->unique_id_html_colour[4] = g_DecimalToHex[hex_sample_id[3]];
-        sample->unique_id_html_colour[5] = g_DecimalToHex[hex_sample_id[4]];
-        sample->unique_id_html_colour[6] = g_DecimalToHex[hex_sample_id[5]];
-    }
-
-    // Concatenate children
-    for (child = sample->first_child; child != NULL; child = child->next_sibling)
-        GetSampleDigest(child, digest_hash, nb_samples);
-}
-
-
-static rmtError Remotery_SendLogTextMessage(Remotery* rmt, Message* message)
-{
-    assert(rmt != NULL);
-    assert(message != NULL);
-    return Server_Send(rmt->server, message->payload, message->payload_size, 20);
-}
-
-
-static rmtError bin_SampleTree(Buffer* buffer, Msg_SampleTree* msg)
-{
-    Sample* root_sample;
-    char thread_name[64];
-    rmtU32 digest_hash = 0, nb_samples = 0;
-    rmtError error;
-
-    assert(buffer != NULL);
-    assert(msg != NULL);
-
-    // Get the message root sample
-    root_sample = msg->root_sample;
-    assert(root_sample != NULL);
-
-    // Reset the buffer position to the start
-    buffer->bytes_used = 0;
-
-    // Add any sample types as a thread name post-fix to ensure they get their own viewer
-    thread_name[0] = 0;
-    strncat_s(thread_name, sizeof(thread_name), msg->thread_name, strnlen_s(msg->thread_name, 64));
-    if (root_sample->type == SampleType_CUDA)
-        strncat_s(thread_name, sizeof(thread_name), " (CUDA)", 7);
-    if (root_sample->type == SampleType_D3D11)
-        strncat_s(thread_name, sizeof(thread_name), " (D3D11)", 8);
-    if (root_sample->type == SampleType_OpenGL)
-        strncat_s(thread_name, sizeof(thread_name), " (OpenGL)", 9);
-    if (root_sample->type == SampleType_Metal)
-        strncat_s(thread_name, sizeof(thread_name), " (Metal)", 8);
-
-    // Get digest hash of samples so that viewer can efficiently rebuild its tables
-    rmt_BeginCPUSample(GetSampleDigest, RMTSF_Aggregate);
-    GetSampleDigest(root_sample, &digest_hash, &nb_samples);
-    rmt_EndCPUSample();
-
-    // Write global message header
-    BIN_ERROR_CHECK(Buffer_Write(buffer, (void*)"SMPL    ", 8));
-
-    // Write sample message header
-    BIN_ERROR_CHECK(Buffer_WriteStringWithLength(buffer, thread_name));
-    BIN_ERROR_CHECK(Buffer_WriteU32(buffer, nb_samples));
-    BIN_ERROR_CHECK(Buffer_WriteU32(buffer, digest_hash));
-
-    // Write entire sample tree
-    BIN_ERROR_CHECK(bin_Sample(buffer, root_sample));
-
-    // Patch message size
-    U32ToByteArray(buffer->data + 4, buffer->bytes_used);
-
-    return RMT_ERROR_NONE;
-}
-
-
-
-#if RMT_USE_CUDA
-static rmtBool AreCUDASamplesReady(Sample* sample);
-static rmtBool GetCUDASampleTimes(Sample* root_sample, Sample* sample);
-#endif
-
-
-static rmtError Remotery_SendSampleTreeMessage(Remotery* rmt, Message* message)
-{
-    Msg_SampleTree* sample_tree;
-    rmtError error = RMT_ERROR_NONE;
-    Sample* sample;
-
-    assert(rmt != NULL);
-    assert(message != NULL);
-
-    // Get the message root sample
-    sample_tree = (Msg_SampleTree*)message->payload;
-    sample = sample_tree->root_sample;
-    assert(sample != NULL);
-
-    #if RMT_USE_CUDA
-    if (sample->type == SampleType_CUDA)
-    {
-        // If these CUDA samples aren't ready yet, stick them to the back of the queue and continue
-        rmtBool are_samples_ready;
-        rmt_BeginCPUSample(AreCUDASamplesReady, 0);
-        are_samples_ready = AreCUDASamplesReady(sample);
-        rmt_EndCPUSample();
-        if (!are_samples_ready)
-        {
-            AddSampleTreeMessage(rmt->mq_to_rmt_thread, sample, sample_tree->allocator, sample_tree->thread_name, message->thread_sampler);
-            return RMT_ERROR_NONE;
-        }
-
-        // Retrieve timing of all CUDA samples
-        rmt_BeginCPUSample(GetCUDASampleTimes, 0);
-        GetCUDASampleTimes(sample->parent, sample);
-        rmt_EndCPUSample();
-    }
-    #endif
-
-    // Serialise the sample tree and send to the viewer with a reasonably long timeout as the size
-    // of the sample data may be large
-    rmt_BeginCPUSample(bin_SampleTree, RMTSF_Aggregate);
-    error = bin_SampleTree(rmt->bin_buf, sample_tree);
-    rmt_EndCPUSample();
-    if (error == RMT_ERROR_NONE)
-    {
-        rmt_BeginCPUSample(Server_Send, RMTSF_Aggregate);
-        error = Server_Send(rmt->server, rmt->bin_buf->data, rmt->bin_buf->bytes_used, 50000);
-        rmt_EndCPUSample();
-    }
-
-    // Release the sample tree back to its allocator
-    FreeSampleTree(sample, sample_tree->allocator);
-
-    return error;
-}
-
-
-static rmtError Remotery_ConsumeMessageQueue(Remotery* rmt)
-{
-    rmtU32 nb_messages_sent = 0;
-    const rmtU32 maxNbMessagesPerUpdate = g_Settings.maxNbMessagesPerUpdate;
-
-    assert(rmt != NULL);
-
-    // Absorb as many messages in the queue while disconnected
-    if (Server_IsClientConnected(rmt->server) == RMT_FALSE)
-        return RMT_ERROR_NONE;
-
-    // Loop reading the max number of messages for this update
-    while( nb_messages_sent++ < maxNbMessagesPerUpdate )
-    {
-        rmtError error = RMT_ERROR_NONE;
-        Message* message = rmtMessageQueue_PeekNextMessage(rmt->mq_to_rmt_thread);
-        if (message == NULL)
-            break;
-
-        switch (message->id)
-        {
-            // This shouldn't be possible
-            case MsgID_NotReady:
-                assert(RMT_FALSE);
-                break;
-
-            // Dispatch to message handler
-            case MsgID_LogText:
-                error = Remotery_SendLogTextMessage(rmt, message);
-                break;
-            case MsgID_SampleTree:
-                rmt_BeginCPUSample(SendSampleTreeMessage, RMTSF_Aggregate);
-                error = Remotery_SendSampleTreeMessage(rmt, message);
-                rmt_EndCPUSample();
-                break;
-        }
-
-        // Consume the message before reacting to any errors
-        rmtMessageQueue_ConsumeNextMessage(rmt->mq_to_rmt_thread, message);
-        if (error != RMT_ERROR_NONE)
-            return error;
-    }
-
-    return RMT_ERROR_NONE;
-}
-
-
-static void Remotery_FlushMessageQueue(Remotery* rmt)
-{
-    assert(rmt != NULL);
-
-    // Loop reading all remaining messages
-    for (;;)
-    {
-        Message* message = rmtMessageQueue_PeekNextMessage(rmt->mq_to_rmt_thread);
-        if (message == NULL)
-            break;
-
-        switch (message->id)
-        {
-            // These can be safely ignored
-            case MsgID_NotReady:
-            case MsgID_LogText:
-                break;
-
-            // Release all samples back to their allocators
-            case MsgID_SampleTree:
-            {
-                Msg_SampleTree* sample_tree = (Msg_SampleTree*)message->payload;
-                FreeSampleTree(sample_tree->root_sample, sample_tree->allocator);
-                break;
-            }
-        }
-
-        rmtMessageQueue_ConsumeNextMessage(rmt->mq_to_rmt_thread, message);
-    }
-}
-
-
-static rmtError Remotery_ThreadMain(rmtThread* thread)
-{
-    Remotery* rmt = (Remotery*)thread->param;
-    assert(rmt != NULL);
-
-    rmt_SetCurrentThreadName("Remotery");
-
-    while (thread->request_exit == RMT_FALSE)
-    {
-        rmt_BeginCPUSample(Wakeup, 0);
-
-            rmt_BeginCPUSample(ServerUpdate, 0);
-            Server_Update(rmt->server);
-            rmt_EndCPUSample();
-
-            rmt_BeginCPUSample(ConsumeMessageQueue, 0);
-            Remotery_ConsumeMessageQueue(rmt);
-            rmt_EndCPUSample();
-
-        rmt_EndCPUSample();
-
-        //
-        // [NOTE-A]
-        //
-        // Possible sequence of user events at this point:
-        //
-        //    1. Add samples to the queue.
-        //    2. Shutdown remotery.
-        //
-        // This loop will exit with unrelease samples.
-        //
-
-        msSleep(g_Settings.msSleepBetweenServerUpdates);
-    }
-
-    // Release all samples to their allocators as a consequence of [NOTE-A]
-    Remotery_FlushMessageQueue(rmt);
-
-    return RMT_ERROR_NONE;
-}
-
-
-static rmtError Remotery_ReceiveMessage(void* context, char* message_data, rmtU32 message_length)
-{
-    Remotery* rmt = (Remotery*)context;
-
-    // Manual dispatch on 4-byte message headers (message ID is little-endian encoded)
-    #define FOURCC(a, b, c, d) (rmtU32)( ((d) << 24) | ((c) << 16) | ((b) << 8) | (a) )
-    rmtU32 message_id = *(rmtU32*)message_data;
-
-    switch (message_id)
-    {
-        case FOURCC('C', 'O', 'N', 'I'):
-        {
-            // Pass on to any registered handler
-            if (g_Settings.input_handler != NULL)
-                g_Settings.input_handler(message_data + 4, g_Settings.input_handler_context);
-
-            rmt_LogText("Console message received...");
-            rmt_LogText(message_data + 4);
-            break;
-        }
-
-        case FOURCC('G', 'S', 'M', 'P'):
-        {
-            // Convert name hash to integer
-            rmtU32 name_hash = 0;
-            const char* cur = message_data + 4;
-            const char* end = cur + message_length - 4;
-            while (cur < end)
-                name_hash = name_hash * 10 + *cur++ - '0';
-
-            // Search all threads for a matching string hash
-            ThreadSampler* ts;
-            for (ts = rmt->first_thread_sampler; ts != NULL; ts = ts->next)
-            {
-                rmtPStr name = StringTable_Find(ts->names, name_hash);
-                if (name != NULL)
-                {
-                    // Construct a response message containing the matching name
-                    rmtU8 response[256];
-                    rmtU32 name_length = (rmtU32)strnlen_s(name, 256 - 12);
-                    response[0] = 'S';
-                    response[1] = 'S';
-                    response[2] = 'M';
-                    response[3] = 'P';
-                    U32ToByteArray(response + 4, name_hash);
-                    U32ToByteArray(response + 8, name_length);
-                    memcpy(response + 12, name, name_length);
-
-                    // Send back immediately as we're on the server thread
-                    return Server_Send(rmt->server, response, 12 + name_length, 10);
-                }
-            }
-
-            break;
-        }
-    }
-
-    #undef FOURCC
-
-    return RMT_ERROR_NONE;
-}
-
-
-static rmtError Remotery_Constructor(Remotery* rmt)
-{
-    rmtError error;
-
-    assert(rmt != NULL);
-
-    // Set default state
-    rmt->server = NULL;
-    rmt->thread_sampler_tls_handle = TLS_INVALID_HANDLE;
-    rmt->first_thread_sampler = NULL;
-    rmt->mq_to_rmt_thread = NULL;
-    rmt->bin_buf = NULL;
-    rmt->thread = NULL;
-
-    #if RMT_USE_CUDA
-        rmt->cuda.CtxSetCurrent = NULL;
-        rmt->cuda.EventCreate = NULL;
-        rmt->cuda.EventDestroy = NULL;
-        rmt->cuda.EventElapsedTime = NULL;
-        rmt->cuda.EventQuery = NULL;
-        rmt->cuda.EventRecord = NULL;
-    #endif
-
-    #if RMT_USE_D3D11
-        rmt->d3d11 = NULL;
-    #endif
-
-    #if RMT_USE_OPENGL
-        rmt->opengl = NULL;
-    #endif
-
-    #if RMT_USE_METAL
-        rmt->metal = NULL;
-    #endif
-
-    // Kick-off the timer
-    usTimer_Init(&rmt->timer);
-
-    // Allocate a TLS handle for the thread sampler
-    error = tlsAlloc(&rmt->thread_sampler_tls_handle);
-    if (error != RMT_ERROR_NONE)
-        return error;
-
-    // Create the server
-    New_2(Server, rmt->server, g_Settings.port, g_Settings.limit_connections_to_localhost);
-    if (error != RMT_ERROR_NONE)
-        return error;
-
-    // Setup incoming message handler
-    rmt->server->receive_handler = Remotery_ReceiveMessage;
-    rmt->server->receive_handler_context = rmt;
-
-    // Create the main message thread with only one page
-    New_1(rmtMessageQueue, rmt->mq_to_rmt_thread, g_Settings.messageQueueSizeInBytes);
-    if (error != RMT_ERROR_NONE)
-        return error;
-
-    // Create the binary serialisation buffer
-    New_1(Buffer, rmt->bin_buf, 4096);
-    if (error != RMT_ERROR_NONE)
-        return error;
-
-    #if RMT_USE_D3D11
-        error = D3D11_Create(&rmt->d3d11);
-        if (error != RMT_ERROR_NONE)
-            return error;
-    #endif
-
-    #if RMT_USE_OPENGL
-        error = OpenGL_Create(&rmt->opengl);
-        if (error != RMT_ERROR_NONE)
-            return error;
-    #endif
-
-    #if RMT_USE_METAL
-        error = Metal_Create(&rmt->metal);
-        if (error != RMT_ERROR_NONE)
-            return error;
-    #endif
-
-
-    // Set as the global instance before creating any threads that uses it for sampling itself
-    assert(g_Remotery == NULL);
-    g_Remotery = rmt;
-    g_RemoteryCreated = RMT_TRUE;
-
-    // Ensure global instance writes complete before other threads get a chance to use it
-    WriteFence();
-
-    // Create the main update thread once everything has been defined for the global remotery object
-    New_2(rmtThread, rmt->thread, Remotery_ThreadMain, rmt);
-    return error;
-}
-
-
-static void Remotery_Destructor(Remotery* rmt)
-{
-    assert(rmt != NULL);
-
-    // Join the remotery thread before clearing the global object as the thread is profiling itself
-    Delete(rmtThread, rmt->thread);
-
-    if (g_RemoteryCreated)
-    {
-      g_Remotery = NULL;
-      g_RemoteryCreated = RMT_FALSE;
-    }
-
-    #if RMT_USE_D3D11
-        Delete(D3D11, rmt->d3d11);
-    #endif
-
-    #if RMT_USE_OPENGL
-        Delete(OpenGL, rmt->opengl);
-    #endif
-
-    #if RMT_USE_METAL
-        Delete(Metal, rmt->metal);
-    #endif
-
-    Delete(Buffer, rmt->bin_buf);
-    Delete(rmtMessageQueue, rmt->mq_to_rmt_thread);
-
-    Remotery_DestroyThreadSamplers(rmt);
-
-    Delete(Server, rmt->server);
-
-    if (rmt->thread_sampler_tls_handle != TLS_INVALID_HANDLE)
-    {
-        tlsFree(rmt->thread_sampler_tls_handle);
-        rmt->thread_sampler_tls_handle = 0;
-    }
-}
-
-
-static rmtError Remotery_GetThreadSampler(Remotery* rmt, ThreadSampler** thread_sampler)
-{
-    ThreadSampler* ts;
-
-    // Is there a thread sampler associated with this thread yet?
-    assert(rmt != NULL);
-    ts = (ThreadSampler*)tlsGet(rmt->thread_sampler_tls_handle);
-    if (ts == NULL)
-    {
-        // Allocate on-demand
-        rmtError error;
-        New_0(ThreadSampler, *thread_sampler);
-        if (error != RMT_ERROR_NONE)
-            return error;
-        ts = *thread_sampler;
-
-        // Add to the beginning of the global linked list of thread samplers
-        for (;;)
-        {
-            ThreadSampler* old_ts = rmt->first_thread_sampler;
-            ts->next = old_ts;
-
-            // If the old value is what we expect it to be then no other thread has
-            // changed it since this thread sampler was used as a candidate first list item
-            if (AtomicCompareAndSwapPointer((long* volatile*)&rmt->first_thread_sampler, (long*)old_ts, (long*)ts) == RMT_TRUE)
-                break;
-        }
-
-        tlsSet(rmt->thread_sampler_tls_handle, ts);
-    }
-
-    assert(thread_sampler != NULL);
-    *thread_sampler = ts;
-    return RMT_ERROR_NONE;
-}
-
-
-static void Remotery_BlockingDeleteSampleTree(Remotery* rmt, enum SampleType sample_type)
-{
-    ThreadSampler* ts;
-
-    // Get the attached thread sampler
-    assert(rmt != NULL);
-    if (Remotery_GetThreadSampler(rmt, &ts) == RMT_ERROR_NONE)
-    {
-        SampleTree* sample_tree = ts->sample_trees[sample_type];
-        if (sample_tree != NULL)
-        {
-            // Wait around until the Remotery server thread has sent all sample trees
-            // of this type to the client
-            while (sample_tree->allocator->nb_inuse > 1)
-                msSleep(1);
-
-            // Now free to delete
-            Delete(SampleTree, sample_tree);
-            ts->sample_trees[sample_type] = NULL;
-        }
-    }
-}
-
-
-
-static void Remotery_DestroyThreadSamplers(Remotery* rmt)
-{
-    // If the handle failed to create in the first place then it shouldn't be possible to create thread samplers
-    assert(rmt != NULL);
-    if (rmt->thread_sampler_tls_handle == TLS_INVALID_HANDLE)
-    {
-        assert(rmt->first_thread_sampler == NULL);
-        return;
-    }
-
-    // Keep popping thread samplers off the linked list until they're all gone
-    // This does not make any assumptions, making it possible for thread samplers to be created while they're all
-    // deleted. While this is erroneous calling code, this will prevent a confusing crash.
-    while (rmt->first_thread_sampler != NULL)
-    {
-        ThreadSampler* ts;
-
-        for (;;)
-        {
-            ThreadSampler* old_ts = rmt->first_thread_sampler;
-            ThreadSampler* next_ts = old_ts->next;
-
-            if (AtomicCompareAndSwapPointer((long* volatile*)&rmt->first_thread_sampler, (long*)old_ts, (long*)next_ts) == RMT_TRUE)
-            {
-                ts = old_ts;
-                break;
-            }
-        }
-
-        Delete(ThreadSampler, ts);
-    }
-}
-
-
-static void* CRTMalloc(void* mm_context, rmtU32 size)
-{
-    RMT_UNREFERENCED_PARAMETER(mm_context);
-    return malloc((size_t)size);
-}
-
-
-static void CRTFree(void* mm_context, void* ptr)
-{
-    RMT_UNREFERENCED_PARAMETER(mm_context);
-    free(ptr);
-}
-
-static void* CRTRealloc(void* mm_context, void* ptr, rmtU32 size)
-{
-    RMT_UNREFERENCED_PARAMETER(mm_context);
-    return realloc(ptr, size);
-}
-
-
-RMT_API rmtSettings* _rmt_Settings(void)
-{
-    // Default-initialize on first call
-    if( g_SettingsInitialized == RMT_FALSE )
-    {
-        g_Settings.port = 0x4597;
-        g_Settings.limit_connections_to_localhost = RMT_FALSE;
-        g_Settings.msSleepBetweenServerUpdates = 10;
-        g_Settings.messageQueueSizeInBytes = 128 * 1024;
-        g_Settings.maxNbMessagesPerUpdate = 10;
-        g_Settings.malloc = CRTMalloc;
-        g_Settings.free = CRTFree;
-        g_Settings.realloc = CRTRealloc;
-        g_Settings.input_handler = NULL;
-        g_Settings.input_handler_context = NULL;
-        g_Settings.logFilename = "rmtLog.txt";
-
-        g_SettingsInitialized = RMT_TRUE;
-    }
-
-    return &g_Settings;
-}
-
-
-RMT_API rmtError _rmt_CreateGlobalInstance(Remotery** remotery)
-{
-    rmtError error;
-
-    // Default-initialise if user has not set values
-    rmt_Settings();
-
-    // Creating the Remotery instance also records it as the global instance
-    assert(remotery != NULL);
-    New_0(Remotery, *remotery);
-    return error;
-}
-
-
-RMT_API void _rmt_DestroyGlobalInstance(Remotery* remotery)
-{
-    // Ensure this is the module that created it
-    assert(g_RemoteryCreated == RMT_TRUE);
-    assert(g_Remotery == remotery);
-    Delete(Remotery, remotery);
-}
-
-
-RMT_API void _rmt_SetGlobalInstance(Remotery* remotery)
-{
-    // Default-initialise if user has not set values
-    rmt_Settings();
-
-    g_Remotery = remotery;
-}
-
-
-RMT_API Remotery* _rmt_GetGlobalInstance(void)
-{
-    return g_Remotery;
-}
-
-
-#ifdef RMT_PLATFORM_WINDOWS
-    #pragma pack(push,8)
-    typedef struct tagTHREADNAME_INFO
-    {
-       DWORD dwType; // Must be 0x1000.
-       LPCSTR szName; // Pointer to name (in user addr space).
-       DWORD dwThreadID; // Thread ID (-1=caller thread).
-       DWORD dwFlags; // Reserved for future use, must be zero.
-    } THREADNAME_INFO;
-    #pragma pack(pop)
-#endif
-
-static void SetDebuggerThreadName(const char* name)
-{
-    #ifdef RMT_PLATFORM_WINDOWS
-        THREADNAME_INFO info;
-        info.dwType = 0x1000;
-        info.szName = name;
-        info.dwThreadID = (DWORD)-1;
-        info.dwFlags = 0;
-
-        #ifndef __MINGW32__
-        __try
-        {
-            RaiseException(0x406D1388, 0, sizeof(info)/sizeof(ULONG_PTR), (ULONG_PTR*)&info);
-        }
-        __except(1 /* EXCEPTION_EXECUTE_HANDLER */)
-        {
-        }
-        #endif
-    #else
-        RMT_UNREFERENCED_PARAMETER(name);
-    #endif
-
-    #ifdef RMT_PLATFORM_LINUX
-        // pthread_setname_np is a non-standard GNU extension.
-        char name_clamp[16];
-        name_clamp[0] = 0;
-        strncat_s(name_clamp, sizeof(name_clamp), name, 15);
-        prctl(PR_SET_NAME,name_clamp,0,0,0);
-    #endif
-}
-
-
-RMT_API void _rmt_SetCurrentThreadName(rmtPStr thread_name)
-{
-    ThreadSampler* ts;
-
-    if (g_Remotery == NULL)
-        return;
-
-    // Get data for this thread
-    if (Remotery_GetThreadSampler(g_Remotery, &ts) != RMT_ERROR_NONE)
-        return;
-
-    // Copy name and apply to the debugger
-    strcpy_s(ts->name, sizeof(ts->name), thread_name);
-    SetDebuggerThreadName(thread_name);
-}
-
-
-static rmtBool QueueLine(rmtMessageQueue* queue, unsigned char* text, rmtU32 size, struct ThreadSampler* thread_sampler)
-{
-    Message* message;
-
-    assert(queue != NULL);
-
-    // Prefix with text size
-    rmtU32 text_size = size - 8;
-    U32ToByteArray(text + 4, text_size);
-
-    // Allocate some space for the line
-    message = rmtMessageQueue_AllocMessage(queue, size, thread_sampler);
-    if (message == NULL)
-        return RMT_FALSE;
-
-    // Copy the text and commit the message
-    memcpy(message->payload, text, size);
-    rmtMessageQueue_CommitMessage(message, MsgID_LogText);
-
-    return RMT_TRUE;
-}
-
-
-RMT_API void _rmt_LogText(rmtPStr text)
-{
-    int start_offset, prev_offset, i;
-    unsigned char line_buffer[1024] = { 0 };
-    ThreadSampler* ts;
-
-    if (g_Remotery == NULL)
-        return;
-
-    Remotery_GetThreadSampler(g_Remotery, &ts);
-
-    // Start the line with the message header
-    line_buffer[0] = 'L';
-    line_buffer[1] = 'O';
-    line_buffer[2] = 'G';
-    line_buffer[3] = 'M';
-    start_offset = 8;
-
-    // There might be newlines in the buffer, so split them into multiple network calls
-    prev_offset = start_offset;
-    for (i = 0; text[i] != 0; i++)
-    {
-        char c = text[i];
-
-        // Line wrap when too long or newline encountered
-        if (prev_offset == sizeof(line_buffer) - 3 || c == '\n')
-        {
-            if (QueueLine(g_Remotery->mq_to_rmt_thread, line_buffer, prev_offset, ts) == RMT_FALSE)
-                return;
-
-            // Restart line
-            prev_offset = start_offset;
-        }
-
-        // Safe to insert 2 characters here as previous check would split lines if not enough space left
-        switch (c)
-        {
-            // Skip newline, dealt with above
-            case '\n':
-                break;
-
-            // Escape these
-            case '\\':
-                line_buffer[prev_offset++] = '\\';
-                line_buffer[prev_offset++] = '\\';
-                break;
-
-            case '\"':
-                line_buffer[prev_offset++] = '\\';
-                line_buffer[prev_offset++] = '\"';
-                break;
-
-            // Add the rest
-            default:
-                line_buffer[prev_offset++] = c;
-                break;
-        }
-    }
-
-    // Send the last line
-    if (prev_offset > start_offset)
-    {
-        assert(prev_offset < ((int)sizeof(line_buffer) - 3));
-        QueueLine(g_Remotery->mq_to_rmt_thread, line_buffer, prev_offset, ts);
-    }
-}
-
-
-RMT_API void _rmt_BeginCPUSample(rmtPStr name, rmtU32 flags, rmtU32* hash_cache)
-{
-    // 'hash_cache' stores a pointer to a sample name's hash value. Internally this is used to identify unique callstacks and it
-    // would be ideal that it's not recalculated each time the sample is used. This can be statically cached at the point
-    // of call or stored elsewhere when dynamic names are required.
-    //
-    // If 'hash_cache' is NULL then this call becomes more expensive, as it has to recalculate the hash of the name.
-
-    ThreadSampler* ts;
-
-    if (g_Remotery == NULL)
-        return;
-
-    // TODO: Time how long the bits outside here cost and subtract them from the parent
-
-    if (Remotery_GetThreadSampler(g_Remotery, &ts) == RMT_ERROR_NONE)
-    {
-        Sample* sample;
-        rmtU32 name_hash = ThreadSampler_GetNameHash(ts, name, hash_cache);
-        if (ThreadSampler_Push(ts->sample_trees[SampleType_CPU], name_hash, flags, &sample) == RMT_ERROR_NONE)
-        {
-            // If this is an aggregate sample, store the time in 'end' as we want to preserve 'start'
-            if (sample->us_length != 0)
-                sample->us_end = usTimer_Get(&g_Remotery->timer);
-            else
-                sample->us_start = usTimer_Get(&g_Remotery->timer);
-        }
-    }
-}
-
-
-RMT_API void _rmt_EndCPUSample(void)
-{
-    ThreadSampler* ts;
-
-    if (g_Remotery == NULL)
-        return;
-
-    if (Remotery_GetThreadSampler(g_Remotery, &ts) == RMT_ERROR_NONE)
-    {
-        Sample* sample = ts->sample_trees[SampleType_CPU]->current_parent;
-
-        rmtU64 us_end = usTimer_Get(&g_Remotery->timer);
-
-        // Is this an aggregate sample?
-        if (sample->us_length != 0)
-        {
-            sample->us_length += (us_end - sample->us_end);
-            sample->us_end = us_end;
-        }
-        else
-        {
-            sample->us_end = us_end;
-            sample->us_length = (us_end - sample->us_start);
-        }
-
-        sample->us_end = usTimer_Get(&g_Remotery->timer);
-        ThreadSampler_Pop(ts, g_Remotery->mq_to_rmt_thread, sample);
-    }
-}
-
-
-
-/*
-------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------
-   @CUDA: CUDA event sampling
-------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------
-*/
-
-
-
-#if RMT_USE_CUDA
-
-
-typedef struct CUDASample
-{
-    // IS-A inheritance relationship
-    Sample Sample;
-
-    // Pair of events that wrap the sample
-    CUevent event_start;
-    CUevent event_end;
-
-} CUDASample;
-
-
-static rmtError MapCUDAResult(CUresult result)
-{
-    switch (result)
-    {
-        case CUDA_SUCCESS: return RMT_ERROR_NONE;
-        case CUDA_ERROR_DEINITIALIZED: return RMT_ERROR_CUDA_DEINITIALIZED;
-        case CUDA_ERROR_NOT_INITIALIZED: return RMT_ERROR_CUDA_NOT_INITIALIZED;
-        case CUDA_ERROR_INVALID_CONTEXT: return RMT_ERROR_CUDA_INVALID_CONTEXT;
-        case CUDA_ERROR_INVALID_VALUE: return RMT_ERROR_CUDA_INVALID_VALUE;
-        case CUDA_ERROR_INVALID_HANDLE: return RMT_ERROR_CUDA_INVALID_HANDLE;
-        case CUDA_ERROR_OUT_OF_MEMORY: return RMT_ERROR_CUDA_OUT_OF_MEMORY;
-        case CUDA_ERROR_NOT_READY: return RMT_ERROR_ERROR_NOT_READY;
-        default: return RMT_ERROR_CUDA_UNKNOWN;
-    }
-}
-
-
-#define CUDA_MAKE_FUNCTION(name, params)                    \
-    typedef CUresult (CUDAAPI *name##Ptr) params;           \
-    name##Ptr name = (name##Ptr)g_Remotery->cuda.name;
-
-
-#define CUDA_GUARD(call)                \
-    {                                   \
-        rmtError error = call;     \
-        if (error != RMT_ERROR_NONE)    \
-            return error;               \
-    }
-
-
-// Wrappers around CUDA driver functions that manage the active context.
-static rmtError CUDASetContext(void* context)
-{
-    CUDA_MAKE_FUNCTION(CtxSetCurrent, (CUcontext ctx));
-    assert(CtxSetCurrent != NULL);
-    return MapCUDAResult(CtxSetCurrent((CUcontext)context));
-}
-static rmtError CUDAGetContext(void** context)
-{
-    CUDA_MAKE_FUNCTION(CtxGetCurrent, (CUcontext* ctx));
-    assert(CtxGetCurrent != NULL);
-    return MapCUDAResult(CtxGetCurrent((CUcontext*)context));
-}
-static rmtError CUDAEnsureContext()
-{
-    void* current_context;
-    CUDA_GUARD(CUDAGetContext(&current_context));
-
-    assert(g_Remotery != NULL);
-    if (current_context != g_Remotery->cuda.context)
-        CUDA_GUARD(CUDASetContext(g_Remotery->cuda.context));
-
-    return RMT_ERROR_NONE;
-}
-
-
-// Wrappers around CUDA driver functions that manage events
-static rmtError CUDAEventCreate(CUevent* phEvent, unsigned int Flags)
-{
-    CUDA_MAKE_FUNCTION(EventCreate, (CUevent *phEvent, unsigned int Flags));
-    CUDA_GUARD(CUDAEnsureContext());
-    return MapCUDAResult(EventCreate(phEvent, Flags));
-}
-static rmtError CUDAEventDestroy(CUevent hEvent)
-{
-    CUDA_MAKE_FUNCTION(EventDestroy, (CUevent hEvent));
-    CUDA_GUARD(CUDAEnsureContext());
-    return MapCUDAResult(EventDestroy(hEvent));
-}
-static rmtError CUDAEventRecord(CUevent hEvent, void* hStream)
-{
-    CUDA_MAKE_FUNCTION(EventRecord, (CUevent hEvent, CUstream hStream));
-    CUDA_GUARD(CUDAEnsureContext());
-    return MapCUDAResult(EventRecord(hEvent, (CUstream)hStream));
-}
-static rmtError CUDAEventQuery(CUevent hEvent)
-{
-    CUDA_MAKE_FUNCTION(EventQuery,  (CUevent hEvent));
-    CUDA_GUARD(CUDAEnsureContext());
-    return MapCUDAResult(EventQuery(hEvent));
-}
-static rmtError CUDAEventElapsedTime(float* pMilliseconds, CUevent hStart, CUevent hEnd)
-{
-    CUDA_MAKE_FUNCTION(EventElapsedTime, (float *pMilliseconds, CUevent hStart, CUevent hEnd));
-    CUDA_GUARD(CUDAEnsureContext());
-    return MapCUDAResult(EventElapsedTime(pMilliseconds, hStart, hEnd));
-}
-
-
-static rmtError CUDASample_Constructor(CUDASample* sample)
-{
-    rmtError error;
-
-    assert(sample != NULL);
-
-    // Chain to sample constructor
-    Sample_Constructor((Sample*)sample);
-    sample->Sample.type = SampleType_CUDA;
-    sample->Sample.size_bytes = sizeof(CUDASample);
-    sample->event_start = NULL;
-    sample->event_end = NULL;
-
-    // Create non-blocking events with timing
-    assert(g_Remotery != NULL);
-    error = CUDAEventCreate(&sample->event_start, CU_EVENT_DEFAULT);
-    if (error == RMT_ERROR_NONE)
-        error = CUDAEventCreate(&sample->event_end, CU_EVENT_DEFAULT);
-    return error;
-}
-
-
-static void CUDASample_Destructor(CUDASample* sample)
-{
-    assert(sample != NULL);
-
-    // Destroy events
-    if (sample->event_start != NULL)
-        CUDAEventDestroy(sample->event_start);
-    if (sample->event_end != NULL)
-        CUDAEventDestroy(sample->event_end);
-
-    Sample_Destructor((Sample*)sample);
-}
-
-
-static rmtBool AreCUDASamplesReady(Sample* sample)
-{
-    rmtError error;
-    Sample* child;
-
-    CUDASample* cuda_sample = (CUDASample*)sample;
-    assert(sample->type == SampleType_CUDA);
-
-    // Check to see if both of the CUDA events have been processed
-    error = CUDAEventQuery(cuda_sample->event_start);
-    if (error != RMT_ERROR_NONE)
-        return RMT_FALSE;
-    error = CUDAEventQuery(cuda_sample->event_end);
-    if (error != RMT_ERROR_NONE)
-        return RMT_FALSE;
-
-    // Check child sample events
-    for (child = sample->first_child; child != NULL; child = child->next_sibling)
-    {
-        if (!AreCUDASamplesReady(child))
-            return RMT_FALSE;
-    }
-
-    return RMT_TRUE;
-}
-
-
-static rmtBool GetCUDASampleTimes(Sample* root_sample, Sample* sample)
-{
-    Sample* child;
-
-    CUDASample* cuda_root_sample = (CUDASample*)root_sample;
-    CUDASample* cuda_sample = (CUDASample*)sample;
-
-    float ms_start, ms_end;
-
-    assert(root_sample != NULL);
-    assert(sample != NULL);
-
-    // Get millisecond timing of each sample event, relative to initial root sample
-    if (CUDAEventElapsedTime(&ms_start, cuda_root_sample->event_start, cuda_sample->event_start) != RMT_ERROR_NONE)
-        return RMT_FALSE;
-    if (CUDAEventElapsedTime(&ms_end, cuda_root_sample->event_start, cuda_sample->event_end) != RMT_ERROR_NONE)
-        return RMT_FALSE;
-
-    // Convert to microseconds and add to the sample
-    sample->us_start = (rmtU64)(ms_start * 1000);
-    sample->us_end = (rmtU64)(ms_end * 1000);
-    sample->us_length = sample->us_end - sample->us_start;
-
-    // Get child sample times
-    for (child = sample->first_child; child != NULL; child = child->next_sibling)
-    {
-        if (!GetCUDASampleTimes(root_sample, child))
-            return RMT_FALSE;
-    }
-
-    return RMT_TRUE;
-}
-
-
-RMT_API void _rmt_BindCUDA(const rmtCUDABind* bind)
-{
-    assert(bind != NULL);
-    if (g_Remotery != NULL)
-        g_Remotery->cuda = *bind;
-}
-
-
-RMT_API void _rmt_BeginCUDASample(rmtPStr name, rmtU32* hash_cache, void* stream)
-{
-    ThreadSampler* ts;
-
-    if (g_Remotery == NULL)
-        return;
-
-    if (Remotery_GetThreadSampler(g_Remotery, &ts) == RMT_ERROR_NONE)
-    {
-        rmtError error;
-        Sample* sample;
-        rmtU32 name_hash = ThreadSampler_GetNameHash(ts, name, hash_cache);
-
-        // Create the CUDA tree on-demand as the tree needs an up-front-created root.
-        // This is not possible to create on initialisation as a CUDA binding is not yet available.
-        SampleTree** cuda_tree = &ts->sample_trees[SampleType_CUDA];
-        if (*cuda_tree == NULL)
-        {
-            CUDASample* root_sample;
-
-            New_3(SampleTree, *cuda_tree, sizeof(CUDASample), (ObjConstructor)CUDASample_Constructor, (ObjDestructor)CUDASample_Destructor);
-            if (error != RMT_ERROR_NONE)
-                return;
-
-            // Record an event once on the root sample, used to measure absolute sample
-            // times since this point
-            root_sample = (CUDASample*)(*cuda_tree)->root;
-            error = CUDAEventRecord(root_sample->event_start, stream);
-            if (error != RMT_ERROR_NONE)
-                return;
-        }
-
-        // Push the same and record its event
-        if (ThreadSampler_Push(*cuda_tree, name_hash, 0, &sample) == RMT_ERROR_NONE)
-        {
-            CUDASample* cuda_sample = (CUDASample*)sample;
-            CUDAEventRecord(cuda_sample->event_start, stream);
-        }
-    }
-}
-
-
-RMT_API void _rmt_EndCUDASample(void* stream)
-{
-    ThreadSampler* ts;
-
-    if (g_Remotery == NULL)
-        return;
-
-    if (Remotery_GetThreadSampler(g_Remotery, &ts) == RMT_ERROR_NONE)
-    {
-        CUDASample* sample = (CUDASample*)ts->sample_trees[SampleType_CUDA]->current_parent;
-        CUDAEventRecord(sample->event_end, stream);
-        ThreadSampler_Pop(ts, g_Remotery->mq_to_rmt_thread, (Sample*)sample);
-    }
-}
-
-
-#endif  // RMT_USE_CUDA
-
-
-
-/*
-------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------
-   @D3D11: Direct3D 11 event sampling
-------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------
-*/
-
-
-
-#if RMT_USE_D3D11
-
-
-// As clReflect has no way of disabling C++ compile mode, this forces C interfaces everywhere...
-#define CINTERFACE
-
-// ...unfortunately these C++ helpers aren't wrapped by the same macro but they can be disabled individually
-#define D3D11_NO_HELPERS
-
-// Allow use of the D3D11 helper macros for accessing the C-style vtable
-#define COBJMACROS
-
-#include <d3d11.h>
-
-
-typedef struct D3D11
-{
-    // Context set by user
-    ID3D11Device* device;
-    ID3D11DeviceContext* context;
-
-    HRESULT last_error;
-
-    // Queue to the D3D 11 main update thread
-    // Given that BeginSample/EndSample need to be called from the same thread that does the update, there
-    // is really no need for this to be a thread-safe queue. I'm using it for its convenience.
-    rmtMessageQueue* mq_to_d3d11_main;
-
-    // Mark the first time so that remaining timestamps are offset from this
-    rmtU64 first_timestamp;
-} D3D11;
-
-
-static rmtError D3D11_Create(D3D11** d3d11)
-{
-    rmtError error;
-
-    assert(d3d11 != NULL);
-
-    // Allocate space for the D3D11 data
-    *d3d11 = (D3D11*)rmtMalloc(sizeof(D3D11));
-    if (*d3d11 == NULL)
-        return RMT_ERROR_MALLOC_FAIL;
-
-    // Set defaults
-    (*d3d11)->device = NULL;
-    (*d3d11)->context = NULL;
-    (*d3d11)->last_error = S_OK;
-    (*d3d11)->mq_to_d3d11_main = NULL;
-    (*d3d11)->first_timestamp = 0;
-
-    New_1(rmtMessageQueue, (*d3d11)->mq_to_d3d11_main, g_Settings.messageQueueSizeInBytes);
-    if (error != RMT_ERROR_NONE)
-    {
-        Delete(D3D11, *d3d11);
-        return error;
-    }
-
-    return RMT_ERROR_NONE;
-}
-
-
-static void D3D11_Destructor(D3D11* d3d11)
-{
-    assert(d3d11 != NULL);
-    Delete(rmtMessageQueue, d3d11->mq_to_d3d11_main);
-}
-
-
-typedef struct D3D11Timestamp
-{
-    // Inherit so that timestamps can be quickly allocated
-    ObjectLink Link;
-
-    // Pair of timestamp queries that wrap the sample
-    ID3D11Query* query_start;
-    ID3D11Query* query_end;
-
-    // A disjoint to measure frequency/stability
-    // TODO: Does *each* sample need one of these?
-    ID3D11Query* query_disjoint;
-} D3D11Timestamp;
-
-
-static rmtError D3D11Timestamp_Constructor(D3D11Timestamp* stamp)
-{
-    D3D11_QUERY_DESC timestamp_desc;
-    D3D11_QUERY_DESC disjoint_desc;
-    ID3D11Device* device;
-    HRESULT* last_error;
-
-    assert(stamp != NULL);
-
-    ObjectLink_Constructor((ObjectLink*)stamp);
-
-    // Set defaults
-    stamp->query_start = NULL;
-    stamp->query_end = NULL;
-    stamp->query_disjoint = NULL;
-
-    assert(g_Remotery != NULL);
-    assert(g_Remotery->d3d11 != NULL);
-    device = g_Remotery->d3d11->device;
-    last_error = &g_Remotery->d3d11->last_error;
-
-    // Create start/end timestamp queries
-    timestamp_desc.Query = D3D11_QUERY_TIMESTAMP;
-    timestamp_desc.MiscFlags = 0;
-    *last_error = ID3D11Device_CreateQuery(device, &timestamp_desc, &stamp->query_start);
-    if (*last_error != S_OK)
-        return RMT_ERROR_D3D11_FAILED_TO_CREATE_QUERY;
-    *last_error = ID3D11Device_CreateQuery(device, &timestamp_desc, &stamp->query_end);
-    if (*last_error != S_OK)
-        return RMT_ERROR_D3D11_FAILED_TO_CREATE_QUERY;
-
-    // Create disjoint query
-    disjoint_desc.Query = D3D11_QUERY_TIMESTAMP_DISJOINT;
-    disjoint_desc.MiscFlags = 0;
-    *last_error = ID3D11Device_CreateQuery(device, &disjoint_desc, &stamp->query_disjoint);
-    if (*last_error != S_OK)
-        return RMT_ERROR_D3D11_FAILED_TO_CREATE_QUERY;
-
-    return RMT_ERROR_NONE;
-}
-
-
-static void D3D11Timestamp_Destructor(D3D11Timestamp* stamp)
-{
-    assert(stamp != NULL);
-
-    // Destroy queries
-    if (stamp->query_disjoint != NULL)
-        ID3D11Query_Release(stamp->query_disjoint);
-    if (stamp->query_end != NULL)
-        ID3D11Query_Release(stamp->query_end);
-    if (stamp->query_start != NULL)
-        ID3D11Query_Release(stamp->query_start);
-}
-
-
-static void D3D11Timestamp_Begin(D3D11Timestamp* stamp, ID3D11DeviceContext* context)
-{
-    assert(stamp != NULL);
-
-    // Start of disjoint and first query
-    ID3D11DeviceContext_Begin(context, (ID3D11Asynchronous*)stamp->query_disjoint);
-    ID3D11DeviceContext_End(context, (ID3D11Asynchronous*)stamp->query_start);
-}
-
-
-static void D3D11Timestamp_End(D3D11Timestamp* stamp, ID3D11DeviceContext* context)
-{
-    assert(stamp != NULL);
-
-    // End of disjoint and second query
-    ID3D11DeviceContext_End(context, (ID3D11Asynchronous*)stamp->query_end);
-    ID3D11DeviceContext_End(context, (ID3D11Asynchronous*)stamp->query_disjoint);
-}
-
-
-static HRESULT D3D11Timestamp_GetData(D3D11Timestamp* stamp, ID3D11DeviceContext* context, rmtU64* out_start, rmtU64* out_end, rmtU64* out_first_timestamp)
-{
-    ID3D11Asynchronous* query_start;
-    ID3D11Asynchronous* query_end;
-    ID3D11Asynchronous* query_disjoint;
-    HRESULT result;
-
-    UINT64 start;
-    UINT64 end;
-    D3D11_QUERY_DATA_TIMESTAMP_DISJOINT disjoint;
-
-    assert(stamp != NULL);
-    query_start = (ID3D11Asynchronous*)stamp->query_start;
-    query_end = (ID3D11Asynchronous*)stamp->query_end;
-    query_disjoint = (ID3D11Asynchronous*)stamp->query_disjoint;
-
-    // Check to see if all queries are ready
-    // If any fail to arrive, wait until later
-    result = ID3D11DeviceContext_GetData(context, query_start, &start, sizeof(start), D3D11_ASYNC_GETDATA_DONOTFLUSH);
-    if (result != S_OK)
-        return result;
-    result = ID3D11DeviceContext_GetData(context, query_end, &end, sizeof(end), D3D11_ASYNC_GETDATA_DONOTFLUSH);
-    if (result != S_OK)
-        return result;
-    result = ID3D11DeviceContext_GetData(context, query_disjoint, &disjoint, sizeof(disjoint), D3D11_ASYNC_GETDATA_DONOTFLUSH);
-    if (result != S_OK)
-        return result;
-
-    if (disjoint.Disjoint == FALSE)
-    {
-        double frequency = disjoint.Frequency / 1000000.0;
-
-        // Mark the first timestamp
-        assert(out_first_timestamp != NULL);
-        if (*out_first_timestamp == 0)
-            *out_first_timestamp = start;
-
-        // Calculate start and end timestamps from the disjoint info
-        *out_start = (rmtU64)((start - *out_first_timestamp) / frequency);
-        *out_end = (rmtU64)((end - *out_first_timestamp) / frequency);
-    }
-
-    return S_OK;
-}
-
-
-typedef struct D3D11Sample
-{
-    // IS-A inheritance relationship
-    Sample Sample;
-
-    D3D11Timestamp* timestamp;
-
-} D3D11Sample;
-
-
-static rmtError D3D11Sample_Constructor(D3D11Sample* sample)
-{
-    rmtError error;
-
-    assert(sample != NULL);
-
-    // Chain to sample constructor
-    Sample_Constructor((Sample*)sample);
-    sample->Sample.type = SampleType_D3D11;
-    sample->Sample.size_bytes = sizeof(D3D11Sample);
-    New_0(D3D11Timestamp, sample->timestamp);
-
-    return RMT_ERROR_NONE;
-}
-
-
-static void D3D11Sample_Destructor(D3D11Sample* sample)
-{
-    Delete(D3D11Timestamp, sample->timestamp);
-    Sample_Destructor((Sample*)sample);
-}
-
-
-RMT_API void _rmt_BindD3D11(void* device, void* context)
-{
-    if (g_Remotery != NULL)
-    {
-        assert(g_Remotery->d3d11 != NULL);
-
-        assert(device != NULL);
-        g_Remotery->d3d11->device = (ID3D11Device*)device;
-        assert(context != NULL);
-        g_Remotery->d3d11->context = (ID3D11DeviceContext*)context;
-    }
-}
-
-
-static void UpdateD3D11Frame(void);
-
-
-RMT_API void _rmt_UnbindD3D11(void)
-{
-    if (g_Remotery != NULL)
-    {
-        D3D11* d3d11 = g_Remotery->d3d11;
-        assert(d3d11 != NULL);
-
-        // Stall waiting for the D3D queue to empty into the Remotery queue
-        while (!rmtMessageQueue_IsEmpty(d3d11->mq_to_d3d11_main))
-            UpdateD3D11Frame();
-
-        // Inform sampler to not add any more samples
-        d3d11->device = NULL;
-        d3d11->context = NULL;
-
-        // Forcefully delete sample tree on this thread to release time stamps from
-        // the same thread that created them
-        Remotery_BlockingDeleteSampleTree(g_Remotery, SampleType_D3D11);
-    }
-}
-
-
-RMT_API void _rmt_BeginD3D11Sample(rmtPStr name, rmtU32* hash_cache)
-{
-    ThreadSampler* ts;
-    D3D11* d3d11;
-
-    if (g_Remotery == NULL)
-        return;
-
-    // Has D3D11 been unbound?
-    d3d11 = g_Remotery->d3d11;
-    assert(d3d11 != NULL);
-    if (d3d11->device == NULL || d3d11->context == NULL)
-        return;
-
-    if (Remotery_GetThreadSampler(g_Remotery, &ts) == RMT_ERROR_NONE)
-    {
-        Sample* sample;
-        rmtU32 name_hash = ThreadSampler_GetNameHash(ts, name, hash_cache);
-
-        // Create the D3D11 tree on-demand as the tree needs an up-front-created root.
-        // This is not possible to create on initialisation as a D3D11 binding is not yet available.
-        SampleTree** d3d_tree = &ts->sample_trees[SampleType_D3D11];
-        if (*d3d_tree == NULL)
-        {
-            rmtError error;
-            New_3(SampleTree, *d3d_tree, sizeof(D3D11Sample), (ObjConstructor)D3D11Sample_Constructor, (ObjDestructor)D3D11Sample_Destructor);
-            if (error != RMT_ERROR_NONE)
-                return;
-        }
-
-        // Push the sample and activate the timestamp
-        if (ThreadSampler_Push(*d3d_tree, name_hash, 0, &sample) == RMT_ERROR_NONE)
-        {
-            D3D11Sample* d3d_sample = (D3D11Sample*)sample;
-            D3D11Timestamp_Begin(d3d_sample->timestamp, d3d11->context);
-        }
-    }
-}
-
-
-static rmtBool GetD3D11SampleTimes(Sample* sample, rmtU64* out_first_timestamp)
-{
-    Sample* child;
-
-    D3D11Sample* d3d_sample = (D3D11Sample*)sample;
-
-    assert(sample != NULL);
-    if (d3d_sample->timestamp != NULL)
-    {
-        HRESULT result;
-
-        D3D11* d3d11 = g_Remotery->d3d11;
-        assert(d3d11 != NULL);
-
-        result = D3D11Timestamp_GetData(
-            d3d_sample->timestamp,
-            d3d11->context,
-            &sample->us_start,
-            &sample->us_end,
-            out_first_timestamp);
-
-        if (result != S_OK)
-        {
-            d3d11->last_error = result;
-            return RMT_FALSE;
-        }
-
-        sample->us_length = sample->us_end - sample->us_start;
-    }
-
-    // Get child sample times
-    for (child = sample->first_child; child != NULL; child = child->next_sibling)
-    {
-        if (!GetD3D11SampleTimes(child, out_first_timestamp))
-            return RMT_FALSE;
-    }
-
-    return RMT_TRUE;
-}
-
-
-static void UpdateD3D11Frame(void)
-{
-    D3D11* d3d11;
-
-    if (g_Remotery == NULL)
-        return;
-
-    d3d11 = g_Remotery->d3d11;
-    assert(d3d11 != NULL);
-
-    rmt_BeginCPUSample(rmt_UpdateD3D11Frame, 0);
-
-    // Process all messages in the D3D queue
-    for (;;)
-    {
-        Msg_SampleTree* sample_tree;
-        Sample* sample;
-
-        Message* message = rmtMessageQueue_PeekNextMessage(d3d11->mq_to_d3d11_main);
-        if (message == NULL)
-            break;
-
-        // There's only one valid message type in this queue
-        assert(message->id == MsgID_SampleTree);
-        sample_tree = (Msg_SampleTree*)message->payload;
-        sample = sample_tree->root_sample;
-        assert(sample->type == SampleType_D3D11);
-
-        // Retrieve timing of all D3D11 samples
-        // If they aren't ready leave the message unconsumed, holding up later frames and maintaining order
-        if (!GetD3D11SampleTimes(sample, &d3d11->first_timestamp))
-            break;
-
-        // Pass samples onto the remotery thread for sending to the viewer
-        AddSampleTreeMessage(g_Remotery->mq_to_rmt_thread, sample, sample_tree->allocator, sample_tree->thread_name, message->thread_sampler);
-        rmtMessageQueue_ConsumeNextMessage(d3d11->mq_to_d3d11_main, message);
-    }
-
-    rmt_EndCPUSample();
-}
-
-
-RMT_API void _rmt_EndD3D11Sample(void)
-{
-    ThreadSampler* ts;
-    D3D11* d3d11;
-
-    if (g_Remotery == NULL)
-        return;
-
-    // Has D3D11 been unbound?
-    d3d11 = g_Remotery->d3d11;
-    assert(d3d11 != NULL);
-    if (d3d11->device == NULL || d3d11->context == NULL)
-        return;
-
-    if (Remotery_GetThreadSampler(g_Remotery, &ts) == RMT_ERROR_NONE)
-    {
-        // Close the timestamp
-        D3D11Sample* d3d_sample = (D3D11Sample*)ts->sample_trees[SampleType_D3D11]->current_parent;
-        if (d3d_sample->timestamp != NULL)
-            D3D11Timestamp_End(d3d_sample->timestamp, d3d11->context);
-
-        // Send to the update loop for ready-polling
-        if (ThreadSampler_Pop(ts, d3d11->mq_to_d3d11_main, (Sample*)d3d_sample))
-            // Perform ready-polling on popping of the root sample
-            UpdateD3D11Frame();
-    }
-}
-
-
-#endif  // RMT_USE_D3D11
-
-
-
-/*
-------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------
-@OpenGL: OpenGL event sampling
-------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------
-*/
-
-
-
-#if RMT_USE_OPENGL
-
-
-#ifndef APIENTRY
-#  if defined(__MINGW32__) || defined(__CYGWIN__)
-#    define APIENTRY __stdcall
-#  elif (defined(_MSC_VER) && (_MSC_VER >= 800)) || defined(_STDCALL_SUPPORTED) || defined(__BORLANDC__)
-#    define APIENTRY __stdcall
-#  else
-#    define APIENTRY
-#  endif
-#endif
-
-#ifndef GLAPI
-#  if defined(__MINGW32__) || defined(__CYGWIN__)
-#    define GLAPI extern
-#  elif defined (_WIN32)
-#    define GLAPI WINGDIAPI
-#  else
-#    define GLAPI extern
-#  endif
-#endif
-
-#ifndef GLAPIENTRY
-#define GLAPIENTRY APIENTRY
-#endif
-
-typedef rmtU32 GLenum;
-typedef rmtU32 GLuint;
-typedef rmtS32 GLint;
-typedef rmtS32 GLsizei;
-typedef rmtU64 GLuint64;
-typedef rmtS64 GLint64;
-typedef unsigned char GLubyte;
-
-typedef GLenum (GLAPIENTRY * PFNGLGETERRORPROC) (void);
-typedef void (GLAPIENTRY * PFNGLGENQUERIESPROC) (GLsizei n, GLuint* ids);
-typedef void (GLAPIENTRY * PFNGLDELETEQUERIESPROC) (GLsizei n, const GLuint* ids);
-typedef void (GLAPIENTRY * PFNGLBEGINQUERYPROC) (GLenum target, GLuint id);
-typedef void (GLAPIENTRY * PFNGLENDQUERYPROC) (GLenum target);
-typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTIVPROC) (GLuint id, GLenum pname, GLint* params);
-typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTUIVPROC) (GLuint id, GLenum pname, GLuint* params);
-typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTI64VPROC) (GLuint id, GLenum pname, GLint64* params);
-typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTUI64VPROC) (GLuint id, GLenum pname, GLuint64* params);
-typedef void (GLAPIENTRY * PFNGLQUERYCOUNTERPROC) (GLuint id, GLenum target);
-
-#define GL_NO_ERROR 0
-#define GL_QUERY_RESULT 0x8866
-#define GL_QUERY_RESULT_AVAILABLE 0x8867
-#define GL_TIME_ELAPSED 0x88BF
-#define GL_TIMESTAMP 0x8E28
-
-#define RMT_GL_GET_FUN(x) assert(g_Remotery->opengl->x != NULL); g_Remotery->opengl->x
-
-#define rmtglGenQueries RMT_GL_GET_FUN(__glGenQueries)
-#define rmtglDeleteQueries RMT_GL_GET_FUN(__glDeleteQueries)
-#define rmtglBeginQuery RMT_GL_GET_FUN(__glBeginQuery)
-#define rmtglEndQuery RMT_GL_GET_FUN(__glEndQuery)
-#define rmtglGetQueryObjectiv RMT_GL_GET_FUN(__glGetQueryObjectiv)
-#define rmtglGetQueryObjectuiv RMT_GL_GET_FUN(__glGetQueryObjectuiv)
-#define rmtglGetQueryObjecti64v RMT_GL_GET_FUN(__glGetQueryObjecti64v)
-#define rmtglGetQueryObjectui64v RMT_GL_GET_FUN(__glGetQueryObjectui64v)
-#define rmtglQueryCounter RMT_GL_GET_FUN(__glQueryCounter)
-
-
-struct OpenGL_t
-{
-    // Handle to the OS OpenGL DLL
-    void* dll_handle;
-
-    PFNGLGETERRORPROC __glGetError;
-    PFNGLGENQUERIESPROC __glGenQueries;
-    PFNGLDELETEQUERIESPROC __glDeleteQueries;
-    PFNGLBEGINQUERYPROC __glBeginQuery;
-    PFNGLENDQUERYPROC __glEndQuery;
-    PFNGLGETQUERYOBJECTIVPROC __glGetQueryObjectiv;
-    PFNGLGETQUERYOBJECTUIVPROC __glGetQueryObjectuiv;
-    PFNGLGETQUERYOBJECTI64VPROC __glGetQueryObjecti64v;
-    PFNGLGETQUERYOBJECTUI64VPROC __glGetQueryObjectui64v;
-    PFNGLQUERYCOUNTERPROC __glQueryCounter;
-
-    // Queue to the OpenGL main update thread
-    // Given that BeginSample/EndSample need to be called from the same thread that does the update, there
-    // is really no need for this to be a thread-safe queue. I'm using it for its convenience.
-    rmtMessageQueue* mq_to_opengl_main;
-
-    // Mark the first time so that remaining timestamps are offset from this
-    rmtU64 first_timestamp;
-};
-
-
-static GLenum rmtglGetError(void)
-{
-    if (g_Remotery != NULL)
-    {
-        assert(g_Remotery->opengl != NULL);
-        if (g_Remotery->opengl->__glGetError != NULL)
-            return g_Remotery->opengl->__glGetError();
-    }
-
-    return (GLenum)0;
-}
-
-
-#ifdef RMT_PLATFORM_LINUX
-    #ifdef __cplusplus
-        extern "C" void* glXGetProcAddressARB(const GLubyte*);
-    #else
-        extern void* glXGetProcAddressARB(const GLubyte*);
-    #endif
-#endif
-
-
-static void* rmtglGetProcAddress(OpenGL* opengl, const char* symbol)
-{
-    #if defined(RMT_PLATFORM_WINDOWS)
-    {
-        // Get OpenGL extension-loading function for each call
-        typedef void* (*wglGetProcAddressFn)(LPCSTR);
-        {
-            assert(opengl != NULL);
-            wglGetProcAddressFn wglGetProcAddress = (wglGetProcAddressFn)rmtGetProcAddress(opengl->dll_handle, "wglGetProcAddress");
-            if (wglGetProcAddress != NULL)
-                return wglGetProcAddress(symbol);
-        }
-    }
-
-    #elif defined(RMT_PLATFORM_MACOS) && !defined(GLEW_APPLE_GLX)
-
-        return rmtGetProcAddress(opengl->dll_handle, symbol);
-
-    #elif defined(RMT_PLATFORM_LINUX)
-
-        return glXGetProcAddressARB((const GLubyte*)symbol);
-
-    #endif
-
-    return NULL;
-}
-
-
-static rmtError OpenGL_Create(OpenGL** opengl)
-{
-    rmtError error;
-
-    assert(opengl != NULL);
-
-    *opengl = (OpenGL*)rmtMalloc(sizeof(OpenGL));
-    if (*opengl == NULL)
-        return RMT_ERROR_MALLOC_FAIL;
-
-    (*opengl)->dll_handle = NULL;
-
-    (*opengl)->__glGetError = NULL;
-    (*opengl)->__glGenQueries = NULL;
-    (*opengl)->__glDeleteQueries = NULL;
-    (*opengl)->__glBeginQuery = NULL;
-    (*opengl)->__glEndQuery = NULL;
-    (*opengl)->__glGetQueryObjectiv = NULL;
-    (*opengl)->__glGetQueryObjectuiv = NULL;
-    (*opengl)->__glGetQueryObjecti64v = NULL;
-    (*opengl)->__glGetQueryObjectui64v = NULL;
-    (*opengl)->__glQueryCounter = NULL;
-
-    (*opengl)->mq_to_opengl_main = NULL;
-    (*opengl)->first_timestamp = 0;
-
-    New_1(rmtMessageQueue, (*opengl)->mq_to_opengl_main, g_Settings.messageQueueSizeInBytes);
-    return error;
-}
-
-
-static void OpenGL_Destructor(OpenGL* opengl)
-{
-    assert(opengl != NULL);
-    Delete(rmtMessageQueue, opengl->mq_to_opengl_main);
-}
-
-
-typedef struct OpenGLTimestamp
-{
-    // Inherit so that timestamps can be quickly allocated
-    ObjectLink Link;
-
-    // Pair of timestamp queries that wrap the sample
-    GLuint queries[2];
-} OpenGLTimestamp;
-
-
-static rmtError OpenGLTimestamp_Constructor(OpenGLTimestamp* stamp)
-{
-    int error;
-
-    assert(stamp != NULL);
-
-    ObjectLink_Constructor((ObjectLink*)stamp);
-
-    // Set defaults
-    stamp->queries[0] = stamp->queries[1] = 0;
-
-    // Create start/end timestamp queries
-    assert(g_Remotery != NULL);
-    rmtglGenQueries(2, stamp->queries);
-    error = rmtglGetError();
-    if (error != GL_NO_ERROR)
-        return RMT_ERROR_OPENGL_ERROR;
-
-    return RMT_ERROR_NONE;
-}
-
-
-static void OpenGLTimestamp_Destructor(OpenGLTimestamp* stamp)
-{
-    assert(stamp != NULL);
-
-    // Destroy queries
-    if (stamp->queries[0] != 0)
-    {
-        int error;
-        rmtglDeleteQueries(2, stamp->queries);
-        error = rmtglGetError();
-        assert(error == GL_NO_ERROR);
-    }
-}
-
-
-static void OpenGLTimestamp_Begin(OpenGLTimestamp* stamp)
-{
-    assert(stamp != NULL);
-
-    // First query
-    assert(g_Remotery != NULL);
-    rmtglQueryCounter(stamp->queries[0], GL_TIMESTAMP);
-}
-
-
-static void OpenGLTimestamp_End(OpenGLTimestamp* stamp)
-{
-    assert(stamp != NULL);
-
-    // Second query
-    assert(g_Remotery != NULL);
-    rmtglQueryCounter(stamp->queries[1], GL_TIMESTAMP);
-}
-
-
-static rmtBool OpenGLTimestamp_GetData(OpenGLTimestamp* stamp, rmtU64* out_start, rmtU64* out_end, rmtU64* out_first_timestamp)
-{
-    GLuint64 start = 0, end = 0;
-    GLint startAvailable = 0, endAvailable = 0;
-    int error;
-
-    assert(g_Remotery != NULL);
-
-    assert(stamp != NULL);
-    assert(stamp->queries[0] != 0 && stamp->queries[1] != 0);
-
-    // Check to see if all queries are ready
-    // If any fail to arrive, wait until later
-    rmtglGetQueryObjectiv(stamp->queries[0], GL_QUERY_RESULT_AVAILABLE, &startAvailable);
-    error = rmtglGetError();
-    assert(error == GL_NO_ERROR);
-    if (!startAvailable)
-        return RMT_FALSE;
-    rmtglGetQueryObjectiv(stamp->queries[1], GL_QUERY_RESULT_AVAILABLE, &endAvailable);
-    error = rmtglGetError();
-    assert(error == GL_NO_ERROR);
-    if (!endAvailable)
-        return RMT_FALSE;
-
-    rmtglGetQueryObjectui64v(stamp->queries[0], GL_QUERY_RESULT, &start);
-    error = rmtglGetError();
-    assert(error == GL_NO_ERROR);
-    rmtglGetQueryObjectui64v(stamp->queries[1], GL_QUERY_RESULT, &end);
-    error = rmtglGetError();
-    assert(error == GL_NO_ERROR);
-
-    // Mark the first timestamp
-    assert(out_first_timestamp != NULL);
-    if (*out_first_timestamp == 0)
-        *out_first_timestamp = start;
-
-    // Calculate start and end timestamps (we want us, the queries give us ns)
-    *out_start = (rmtU64)(start - *out_first_timestamp) / 1000ULL;
-    *out_end = (rmtU64)(end - *out_first_timestamp) / 1000ULL;
-
-    return RMT_TRUE;
-}
-
-
-typedef struct OpenGLSample
-{
-    // IS-A inheritance relationship
-    Sample m_sample;
-
-    OpenGLTimestamp* timestamp;
-
-} OpenGLSample;
-
-
-static rmtError OpenGLSample_Constructor(OpenGLSample* sample)
-{
-	rmtError error;
-
-    assert(sample != NULL);
-
-    // Chain to sample constructor
-    Sample_Constructor((Sample*)sample);
-    sample->m_sample.type = SampleType_OpenGL;
-    sample->m_sample.size_bytes = sizeof(OpenGLSample);
-	New_0(OpenGLTimestamp, sample->timestamp);
-
-    return RMT_ERROR_NONE;
-}
-
-
-static void OpenGLSample_Destructor(OpenGLSample* sample)
-{
-	Delete(OpenGLTimestamp, sample->timestamp);
-    Sample_Destructor((Sample*)sample);
-}
-
-
-RMT_API void _rmt_BindOpenGL()
-{
-    if (g_Remotery != NULL)
-    {
-        OpenGL* opengl = g_Remotery->opengl;
-        assert(opengl != NULL);
-
-        #if defined (RMT_PLATFORM_WINDOWS)
-            opengl->dll_handle = rmtLoadLibrary("opengl32.dll");
-        #elif defined (RMT_PLATFORM_MACOS)
-            opengl->dll_handle = rmtLoadLibrary("/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL");
-        #endif
-
-        opengl->__glGetError = (PFNGLGETERRORPROC)rmtGetProcAddress(opengl->dll_handle, "glGetError");
-        opengl->__glGenQueries = (PFNGLGENQUERIESPROC)rmtglGetProcAddress(opengl, "glGenQueries");
-        opengl->__glDeleteQueries = (PFNGLDELETEQUERIESPROC)rmtglGetProcAddress(opengl, "glDeleteQueries");
-        opengl->__glBeginQuery = (PFNGLBEGINQUERYPROC)rmtglGetProcAddress(opengl, "glBeginQuery");
-        opengl->__glEndQuery = (PFNGLENDQUERYPROC)rmtglGetProcAddress(opengl, "glEndQuery");
-        opengl->__glGetQueryObjectiv = (PFNGLGETQUERYOBJECTIVPROC)rmtglGetProcAddress(opengl, "glGetQueryObjectiv");
-        opengl->__glGetQueryObjectuiv = (PFNGLGETQUERYOBJECTUIVPROC)rmtglGetProcAddress(opengl, "glGetQueryObjectuiv");
-        opengl->__glGetQueryObjecti64v = (PFNGLGETQUERYOBJECTI64VPROC)rmtglGetProcAddress(opengl, "glGetQueryObjecti64v");
-        opengl->__glGetQueryObjectui64v = (PFNGLGETQUERYOBJECTUI64VPROC)rmtglGetProcAddress(opengl, "glGetQueryObjectui64v");
-        opengl->__glQueryCounter = (PFNGLQUERYCOUNTERPROC)rmtglGetProcAddress(opengl, "glQueryCounter");
-    }
-}
-
-
-static void UpdateOpenGLFrame(void);
-
-
-RMT_API void _rmt_UnbindOpenGL(void)
-{
-    if (g_Remotery != NULL)
-    {
-        OpenGL* opengl = g_Remotery->opengl;
-        assert(opengl != NULL);
-
-		// Stall waiting for the OpenGL queue to empty into the Remotery queue
-		while (!rmtMessageQueue_IsEmpty(opengl->mq_to_opengl_main))
-			UpdateOpenGLFrame();
-
-		// Forcefully delete sample tree on this thread to release time stamps from
-		// the same thread that created them
-		Remotery_BlockingDeleteSampleTree(g_Remotery, SampleType_OpenGL);
-
-        // Release reference to the OpenGL DLL
-        if (opengl->dll_handle != NULL)
-        {
-            rmtFreeLibrary(opengl->dll_handle);
-            opengl->dll_handle = NULL;
-        }
-    }
-}
-
-
-RMT_API void _rmt_BeginOpenGLSample(rmtPStr name, rmtU32* hash_cache)
-{
-    ThreadSampler* ts;
-
-    if (g_Remotery == NULL)
-        return;
-
-    if (Remotery_GetThreadSampler(g_Remotery, &ts) == RMT_ERROR_NONE)
-    {
-        Sample* sample;
-        rmtU32 name_hash = ThreadSampler_GetNameHash(ts, name, hash_cache);
-
-        // Create the OpenGL tree on-demand as the tree needs an up-front-created root.
-        // This is not possible to create on initialisation as a OpenGL binding is not yet available.
-        SampleTree** ogl_tree = &ts->sample_trees[SampleType_OpenGL];
-        if (*ogl_tree == NULL)
-        {
-			rmtError error;
-			New_3(SampleTree, *ogl_tree, sizeof(OpenGLSample), (ObjConstructor)OpenGLSample_Constructor, (ObjDestructor)OpenGLSample_Destructor);
-            if (error != RMT_ERROR_NONE)
-                return;
-        }
-
-        // Push the sample and activate the timestamp
-        if (ThreadSampler_Push(*ogl_tree, name_hash, 0, &sample) == RMT_ERROR_NONE)
-        {
-            OpenGLSample* ogl_sample = (OpenGLSample*)sample;
-            OpenGLTimestamp_Begin(ogl_sample->timestamp);
-        }
-    }
-}
-
-
-static rmtBool GetOpenGLSampleTimes(Sample* sample, rmtU64* out_first_timestamp)
-{
-    Sample* child;
-
-    OpenGLSample* ogl_sample = (OpenGLSample*)sample;
-
-    assert(sample != NULL);
-    if (ogl_sample->timestamp != NULL)
-    {
-        if (!OpenGLTimestamp_GetData(ogl_sample->timestamp, &sample->us_start, &sample->us_end, out_first_timestamp))
-            return RMT_FALSE;
-
-        sample->us_length = sample->us_end - sample->us_start;
-    }
-
-    // Get child sample times
-    for (child = sample->first_child; child != NULL; child = child->next_sibling)
-    {
-        if (!GetOpenGLSampleTimes(child, out_first_timestamp))
-            return RMT_FALSE;
-    }
-
-    return RMT_TRUE;
-}
-
-
-static void UpdateOpenGLFrame(void)
-{
-    OpenGL* opengl;
-
-    if (g_Remotery == NULL)
-        return;
-
-    opengl = g_Remotery->opengl;
-    assert(opengl != NULL);
-
-    rmt_BeginCPUSample(rmt_UpdateOpenGLFrame, 0);
-
-    // Process all messages in the OpenGL queue
-    while (1)
-    {
-        Msg_SampleTree* sample_tree;
-        Sample* sample;
-
-        Message* message = rmtMessageQueue_PeekNextMessage(opengl->mq_to_opengl_main);
-        if (message == NULL)
-            break;
-
-        // There's only one valid message type in this queue
-        assert(message->id == MsgID_SampleTree);
-        sample_tree = (Msg_SampleTree*)message->payload;
-        sample = sample_tree->root_sample;
-        assert(sample->type == SampleType_OpenGL);
-
-        // Retrieve timing of all OpenGL samples
-        // If they aren't ready leave the message unconsumed, holding up later frames and maintaining order
-        if (!GetOpenGLSampleTimes(sample, &opengl->first_timestamp))
-            break;
-
-        // Pass samples onto the remotery thread for sending to the viewer
-        AddSampleTreeMessage(g_Remotery->mq_to_rmt_thread, sample, sample_tree->allocator, sample_tree->thread_name, message->thread_sampler);
-        rmtMessageQueue_ConsumeNextMessage(opengl->mq_to_opengl_main, message);
-    }
-
-    rmt_EndCPUSample();
-}
-
-
-RMT_API void _rmt_EndOpenGLSample(void)
-{
-    ThreadSampler* ts;
-
-    if (g_Remotery == NULL)
-        return;
-
-    if (Remotery_GetThreadSampler(g_Remotery, &ts) == RMT_ERROR_NONE)
-    {
-        // Close the timestamp
-        OpenGLSample* ogl_sample = (OpenGLSample*)ts->sample_trees[SampleType_OpenGL]->current_parent;
-        if (ogl_sample->timestamp != NULL)
-            OpenGLTimestamp_End(ogl_sample->timestamp);
-
-        // Send to the update loop for ready-polling
-        if (ThreadSampler_Pop(ts, g_Remotery->opengl->mq_to_opengl_main, (Sample*)ogl_sample))
-            // Perform ready-polling on popping of the root sample
-            UpdateOpenGLFrame();
-    }
-}
-
-
-
-#endif  // RMT_USE_OPENGL
-
-
-
-/*
- ------------------------------------------------------------------------------------------------------------------------
- ------------------------------------------------------------------------------------------------------------------------
- @Metal: Metal event sampling
- ------------------------------------------------------------------------------------------------------------------------
- ------------------------------------------------------------------------------------------------------------------------
- */
-
-
-
-#if RMT_USE_METAL
-
-
-
-struct Metal_t
-{
-    // Queue to the Metal main update thread
-    // Given that BeginSample/EndSample need to be called from the same thread that does the update, there
-    // is really no need for this to be a thread-safe queue. I'm using it for its convenience.
-    rmtMessageQueue* mq_to_metal_main;
-};
-
-
-static rmtError Metal_Create(Metal** metal)
-{
-    rmtError error;
-
-    assert(metal != NULL);
-
-    *metal = (Metal*)rmtMalloc(sizeof(Metal));
-    if (*metal == NULL)
-        return RMT_ERROR_MALLOC_FAIL;
-
-    (*metal)->mq_to_metal_main = NULL;
-
-    New_1(rmtMessageQueue, (*metal)->mq_to_metal_main, g_Settings.messageQueueSizeInBytes);
-    return error;
-}
-
-
-static void Metal_Destructor(Metal* metal)
-{
-    assert(metal != NULL);
-    Delete(rmtMessageQueue, metal->mq_to_metal_main);
-}
-
-
-typedef struct MetalTimestamp
-{
-    // Inherit so that timestamps can be quickly allocated
-    ObjectLink Link;
-
-    // Output from GPU callbacks
-    rmtU64 start;
-    rmtU64 end;
-    rmtBool ready;
-} MetalTimestamp;
-
-
-static rmtError MetalTimestamp_Constructor(MetalTimestamp* stamp)
-{
-    assert(stamp != NULL);
-
-    ObjectLink_Constructor((ObjectLink*)stamp);
-
-    // Set defaults
-    stamp->start = 0;
-    stamp->end = 0;
-    stamp->ready = RMT_FALSE;
-
-    return RMT_ERROR_NONE;
-}
-
-
-static void MetalTimestamp_Destructor(MetalTimestamp* stamp)
-{
-    assert(stamp != NULL);
-}
-
-
-rmtU64 rmtMetal_usGetTime()
-{
-    // Share the CPU timer for auto-sync
-    assert(g_Remotery != NULL);
-    return usTimer_Get(&g_Remotery->timer);
-}
-
-
-void rmtMetal_MeasureCommandBuffer(unsigned long long* out_start, unsigned long long* out_end, unsigned int* out_ready);
-
-
-static void MetalTimestamp_Begin(MetalTimestamp* stamp)
-{
-    assert(stamp != NULL);
-    stamp->ready = RMT_FALSE;
-
-    // Metal can currently only issue callbacks at the command buffer level
-    // So for now measure execution of the entire command buffer
-    rmtMetal_MeasureCommandBuffer(&stamp->start, &stamp->end, &stamp->ready);
-}
-
-
-static void MetalTimestamp_End(MetalTimestamp* stamp)
-{
-    assert(stamp != NULL);
-
-    // As Metal can currently only measure entire command buffers, this function is a no-op
-    // as the completed handler was already issued in Begin
-}
-
-
-static rmtBool MetalTimestamp_GetData(MetalTimestamp* stamp, rmtU64* out_start, rmtU64* out_end)
-{
-    assert(g_Remotery != NULL);
-    assert(stamp != NULL);
-
-    // GPU writes ready flag when complete handler is called
-    if (stamp->ready == RMT_FALSE)
-        return RMT_FALSE;
-
-    *out_start = stamp->start;
-    *out_end = stamp->end;
-
-    return RMT_TRUE;
-}
-
-
-typedef struct MetalSample
-{
-    // IS-A inheritance relationship
-    Sample m_sample;
-
-    MetalTimestamp* timestamp;
-
-} MetalSample;
-
-
-static rmtError MetalSample_Constructor(MetalSample* sample)
-{
-    rmtError error;
-
-    assert(sample != NULL);
-
-    // Chain to sample constructor
-    Sample_Constructor((Sample*)sample);
-    sample->m_sample.type = SampleType_Metal;
-    sample->m_sample.size_bytes = sizeof(MetalSample);
-    New_0(MetalTimestamp, sample->timestamp);
-
-    return RMT_ERROR_NONE;
-}
-
-
-static void MetalSample_Destructor(MetalSample* sample)
-{
-    Delete(MetalTimestamp, sample->timestamp);
-    Sample_Destructor((Sample*)sample);
-}
-
-
-static void UpdateOpenGLFrame(void);
-
-
-/*RMT_API void _rmt_UnbindMetal(void)
-{
-    if (g_Remotery != NULL)
-    {
-        Metal* metal = g_Remotery->metal;
-        assert(metal != NULL);
-
-        // Stall waiting for the Metal queue to empty into the Remotery queue
-        while (!rmtMessageQueue_IsEmpty(metal->mq_to_metal_main))
-            UpdateMetalFrame();
-
-        // Forcefully delete sample tree on this thread to release time stamps from
-        // the same thread that created them
-        Remotery_BlockingDeleteSampleTree(g_Remotery, SampleType_Metal);
-    }
-}*/
-
-
-RMT_API void _rmt_BeginMetalSample(rmtPStr name, rmtU32* hash_cache)
-{
-    ThreadSampler* ts;
-
-    if (g_Remotery == NULL)
-        return;
-
-    if (Remotery_GetThreadSampler(g_Remotery, &ts) == RMT_ERROR_NONE)
-    {
-        Sample* sample;
-        rmtU32 name_hash = ThreadSampler_GetNameHash(ts, name, hash_cache);
-
-        // Create the Metal tree on-demand as the tree needs an up-front-created root.
-        // This is not possible to create on initialisation as a Metal binding is not yet available.
-        SampleTree** metal_tree = &ts->sample_trees[SampleType_Metal];
-        if (*metal_tree == NULL)
-        {
-            rmtError error;
-            New_3(SampleTree, *metal_tree, sizeof(MetalSample), (ObjConstructor)MetalSample_Constructor, (ObjDestructor)MetalSample_Destructor);
-            if (error != RMT_ERROR_NONE)
-                return;
-        }
-
-        // Push the sample and activate the timestamp
-        if (ThreadSampler_Push(*metal_tree, name_hash, 0, &sample) == RMT_ERROR_NONE)
-        {
-            MetalSample* metal_sample = (MetalSample*)sample;
-            MetalTimestamp_Begin(metal_sample->timestamp);
-        }
-    }
-}
-
-
-static rmtBool GetMetalSampleTimes(Sample* sample)
-{
-    Sample* child;
-
-    MetalSample* metal_sample = (MetalSample*)sample;
-
-    assert(sample != NULL);
-    if (metal_sample->timestamp != NULL)
-    {
-        if (!MetalTimestamp_GetData(metal_sample->timestamp, &sample->us_start, &sample->us_end))
-            return RMT_FALSE;
-
-        sample->us_length = sample->us_end - sample->us_start;
-    }
-
-    // Get child sample times
-    for (child = sample->first_child; child != NULL; child = child->next_sibling)
-    {
-        if (!GetMetalSampleTimes(child))
-            return RMT_FALSE;
-    }
-
-    return RMT_TRUE;
-}
-
-
-static void UpdateMetalFrame(void)
-{
-    Metal* metal;
-
-    if (g_Remotery == NULL)
-        return;
-
-    metal = g_Remotery->metal;
-    assert(metal != NULL);
-
-    rmt_BeginCPUSample(rmt_UpdateMetalFrame, 0);
-
-    // Process all messages in the Metal queue
-    while (1)
-    {
-        Msg_SampleTree* sample_tree;
-        Sample* sample;
-
-        Message* message = rmtMessageQueue_PeekNextMessage(metal->mq_to_metal_main);
-        if (message == NULL)
-            break;
-
-        // There's only one valid message type in this queue
-        assert(message->id == MsgID_SampleTree);
-        sample_tree = (Msg_SampleTree*)message->payload;
-        sample = sample_tree->root_sample;
-        assert(sample->type == SampleType_Metal);
-
-        // Retrieve timing of all Metal samples
-        // If they aren't ready leave the message unconsumed, holding up later frames and maintaining order
-        if (!GetMetalSampleTimes(sample))
-            break;
-
-        // Pass samples onto the remotery thread for sending to the viewer
-        AddSampleTreeMessage(g_Remotery->mq_to_rmt_thread, sample, sample_tree->allocator, sample_tree->thread_name, message->thread_sampler);
-        rmtMessageQueue_ConsumeNextMessage(metal->mq_to_metal_main, message);
-    }
-
-    rmt_EndCPUSample();
-}
-
-
-RMT_API void _rmt_EndMetalSample(void)
-{
-    ThreadSampler* ts;
-
-    if (g_Remotery == NULL)
-        return;
-
-    if (Remotery_GetThreadSampler(g_Remotery, &ts) == RMT_ERROR_NONE)
-    {
-        // Close the timestamp
-        MetalSample* metal_sample = (MetalSample*)ts->sample_trees[SampleType_Metal]->current_parent;
-        if (metal_sample->timestamp != NULL)
-            MetalTimestamp_End(metal_sample->timestamp);
-        
-        // Send to the update loop for ready-polling
-        if (ThreadSampler_Pop(ts, g_Remotery->metal->mq_to_metal_main, (Sample*)metal_sample))
-            // Perform ready-polling on popping of the root sample
-            UpdateMetalFrame();
-    }
-}
-
-
-
-#endif  // RMT_USE_METAL
-
-
-#endif // RMT_ENABLED
-

+ 0 - 620
3rdparty/remotery/lib/Remotery.h

@@ -1,620 +0,0 @@
-
-
-/*
-Copyright 2014 Celtoys Ltd
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-
-/*
-
-Compiling
----------
-
-* Windows (MSVC) - add lib/Remotery.c and lib/Remotery.h to your program. Set include
-  directories to add Remotery/lib path. The required library ws2_32.lib should be picked
-  up through the use of the #pragma comment(lib, "ws2_32.lib") directive in Remotery.c.
-
-* Mac OS X (XCode) - simply add lib/Remotery.c and lib/Remotery.h to your program.
-
-* Linux (GCC) - add the source in lib folder. Compilation of the code requires -pthreads for
-  library linkage. For example to compile the same run: cc lib/Remotery.c sample/sample.c
-  -I lib -pthread -lm
-
-You can define some extra macros to modify what features are compiled into Remotery. These are
-documented just below this comment.
-
-*/
-
-
-#ifndef RMT_INCLUDED_H
-#define RMT_INCLUDED_H
-
-
-// Set to 0 to not include any bits of Remotery in your build
-#ifndef RMT_ENABLED
-#define RMT_ENABLED 1
-#endif
-
-// Used by the Celtoys TinyCRT library (not released yet)
-#ifndef RMT_USE_TINYCRT
-#define RMT_USE_TINYCRT 0
-#endif
-
-// Assuming CUDA headers/libs are setup, allow CUDA profiling
-#ifndef RMT_USE_CUDA
-#define RMT_USE_CUDA 0
-#endif
-
-// Assuming Direct3D 11 headers/libs are setup, allow D3D11 profiling
-#ifndef RMT_USE_D3D11
-#define RMT_USE_D3D11 0
-#endif
-
-// Allow OpenGL profiling
-#ifndef RMT_USE_OPENGL
-#define RMT_USE_OPENGL 0
-#endif
-
-// Allow Metal profiling
-#ifndef RMT_USE_METAL
-#define RMT_USE_METAL 0
-#endif
-
-// Initially use POSIX thread names to name threads instead of Thread0, 1, ...
-#ifndef RMT_USE_POSIX_THREADNAMES
-#define RMT_USE_POSIX_THREADNAMES 0
-#endif
-
-
-/*
-------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------
-   Compiler/Platform Detection and Preprocessor Utilities
-------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------
-*/
-
-
-// Platform identification
-#if defined(_WINDOWS) || defined(_WIN32)
-    #define RMT_PLATFORM_WINDOWS
-#elif defined(__linux__)
-    #define RMT_PLATFORM_LINUX
-    #define RMT_PLATFORM_POSIX
-#elif defined(__APPLE__)
-    #define RMT_PLATFORM_MACOS
-    #define RMT_PLATFORM_POSIX
-#endif
-
-#ifdef RMT_DLL
-    #if defined (RMT_PLATFORM_WINDOWS)
-        #if defined (RMT_IMPL)
-            #define RMT_API __declspec(dllexport)
-        #else
-            #define RMT_API __declspec(dllimport)
-        #endif
-    #elif defined (RMT_PLATFORM_POSIX)
-        #if defined (RMT_IMPL)
-            #define RMT_API __attribute__((visibility("default")))
-        #else
-            #define RMT_API
-        #endif
-    #endif
-#else
-    #define RMT_API
-#endif
-
-// Allows macros to be written that can work around the inability to do: #define(x) #ifdef x
-// with the C preprocessor.
-#if RMT_ENABLED
-    #define IFDEF_RMT_ENABLED(t, f) t
-#else
-    #define IFDEF_RMT_ENABLED(t, f) f
-#endif
-#if RMT_ENABLED && RMT_USE_CUDA
-    #define IFDEF_RMT_USE_CUDA(t, f) t
-#else
-    #define IFDEF_RMT_USE_CUDA(t, f) f
-#endif
-#if RMT_ENABLED && RMT_USE_D3D11
-    #define IFDEF_RMT_USE_D3D11(t, f) t
-#else
-    #define IFDEF_RMT_USE_D3D11(t, f) f
-#endif
-#if RMT_ENABLED && RMT_USE_OPENGL
-    #define IFDEF_RMT_USE_OPENGL(t, f) t
-#else
-    #define IFDEF_RMT_USE_OPENGL(t, f) f
-#endif
-#if RMT_ENABLED && RMT_USE_METAL
-    #define IFDEF_RMT_USE_METAL(t, f) t
-#else
-    #define IFDEF_RMT_USE_METAL(t, f) f
-#endif
-
-
-// Public interface is written in terms of these macros to easily enable/disable itself
-#define RMT_OPTIONAL(macro, x) IFDEF_ ## macro(x, )
-#define RMT_OPTIONAL_RET(macro, x, y) IFDEF_ ## macro(x, (y))
-
-
-
-/*
-------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------
-   Types
-------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------
-*/
-
-
-
-// Boolean
-typedef unsigned int rmtBool;
-#define RMT_TRUE ((rmtBool)1)
-#define RMT_FALSE ((rmtBool)0)
-
-
-// Unsigned integer types
-typedef unsigned char rmtU8;
-typedef unsigned short rmtU16;
-typedef unsigned int rmtU32;
-typedef unsigned long long rmtU64;
-
-
-// Signed integer types
-typedef char rmtS8;
-typedef short rmtS16;
-typedef int rmtS32;
-typedef long long rmtS64;
-
-
-// Const, null-terminated string pointer
-typedef const char* rmtPStr;
-
-
-// Handle to the main remotery instance
-typedef struct Remotery Remotery;
-
-
-// All possible error codes
-typedef enum rmtError
-{
-    RMT_ERROR_NONE,
-
-    // System errors
-    RMT_ERROR_MALLOC_FAIL,                      // Malloc call within remotery failed
-    RMT_ERROR_TLS_ALLOC_FAIL,                   // Attempt to allocate thread local storage failed
-    RMT_ERROR_VIRTUAL_MEMORY_BUFFER_FAIL,       // Failed to create a virtual memory mirror buffer
-    RMT_ERROR_CREATE_THREAD_FAIL,               // Failed to create a thread for the server
-
-    // Network TCP/IP socket errors
-    RMT_ERROR_SOCKET_INIT_NETWORK_FAIL,         // Network initialisation failure (e.g. on Win32, WSAStartup fails)
-    RMT_ERROR_SOCKET_CREATE_FAIL,               // Can't create a socket for connection to the remote viewer
-    RMT_ERROR_SOCKET_BIND_FAIL,                 // Can't bind a socket for the server
-    RMT_ERROR_SOCKET_LISTEN_FAIL,               // Created server socket failed to enter a listen state
-    RMT_ERROR_SOCKET_SET_NON_BLOCKING_FAIL,     // Created server socket failed to switch to a non-blocking state
-    RMT_ERROR_SOCKET_INVALID_POLL,              // Poll attempt on an invalid socket
-    RMT_ERROR_SOCKET_SELECT_FAIL,               // Server failed to call select on socket
-    RMT_ERROR_SOCKET_POLL_ERRORS,               // Poll notified that the socket has errors
-    RMT_ERROR_SOCKET_ACCEPT_FAIL,               // Server failed to accept connection from client
-    RMT_ERROR_SOCKET_SEND_TIMEOUT,              // Timed out trying to send data
-    RMT_ERROR_SOCKET_SEND_FAIL,                 // Unrecoverable error occured while client/server tried to send data
-    RMT_ERROR_SOCKET_RECV_NO_DATA,              // No data available when attempting a receive
-    RMT_ERROR_SOCKET_RECV_TIMEOUT,              // Timed out trying to receive data
-    RMT_ERROR_SOCKET_RECV_FAILED,               // Unrecoverable error occured while client/server tried to receive data
-
-    // WebSocket errors
-    RMT_ERROR_WEBSOCKET_HANDSHAKE_NOT_GET,      // WebSocket server handshake failed, not HTTP GET
-    RMT_ERROR_WEBSOCKET_HANDSHAKE_NO_VERSION,   // WebSocket server handshake failed, can't locate WebSocket version
-    RMT_ERROR_WEBSOCKET_HANDSHAKE_BAD_VERSION,  // WebSocket server handshake failed, unsupported WebSocket version
-    RMT_ERROR_WEBSOCKET_HANDSHAKE_NO_HOST,      // WebSocket server handshake failed, can't locate host
-    RMT_ERROR_WEBSOCKET_HANDSHAKE_BAD_HOST,     // WebSocket server handshake failed, host is not allowed to connect
-    RMT_ERROR_WEBSOCKET_HANDSHAKE_NO_KEY,       // WebSocket server handshake failed, can't locate WebSocket key
-    RMT_ERROR_WEBSOCKET_HANDSHAKE_BAD_KEY,      // WebSocket server handshake failed, WebSocket key is ill-formed
-    RMT_ERROR_WEBSOCKET_HANDSHAKE_STRING_FAIL,  // WebSocket server handshake failed, internal error, bad string code
-    RMT_ERROR_WEBSOCKET_DISCONNECTED,           // WebSocket server received a disconnect request and closed the socket
-    RMT_ERROR_WEBSOCKET_BAD_FRAME_HEADER,       // Couldn't parse WebSocket frame header
-    RMT_ERROR_WEBSOCKET_BAD_FRAME_HEADER_SIZE,  // Partially received wide frame header size
-    RMT_ERROR_WEBSOCKET_BAD_FRAME_HEADER_MASK,  // Partially received frame header data mask
-    RMT_ERROR_WEBSOCKET_RECEIVE_TIMEOUT,        // Timeout receiving frame header
-
-    RMT_ERROR_REMOTERY_NOT_CREATED,             // Remotery object has not been created
-    RMT_ERROR_SEND_ON_INCOMPLETE_PROFILE,       // An attempt was made to send an incomplete profile tree to the client
-
-    // CUDA error messages
-    RMT_ERROR_CUDA_DEINITIALIZED,               // This indicates that the CUDA driver is in the process of shutting down
-    RMT_ERROR_CUDA_NOT_INITIALIZED,             // This indicates that the CUDA driver has not been initialized with cuInit() or that initialization has failed
-    RMT_ERROR_CUDA_INVALID_CONTEXT,             // This most frequently indicates that there is no context bound to the current thread
-    RMT_ERROR_CUDA_INVALID_VALUE,               // This indicates that one or more of the parameters passed to the API call is not within an acceptable range of values
-    RMT_ERROR_CUDA_INVALID_HANDLE,              // This indicates that a resource handle passed to the API call was not valid
-    RMT_ERROR_CUDA_OUT_OF_MEMORY,               // The API call failed because it was unable to allocate enough memory to perform the requested operation
-    RMT_ERROR_ERROR_NOT_READY,                  // This indicates that a resource handle passed to the API call was not valid
-
-    // Direct3D 11 error messages
-    RMT_ERROR_D3D11_FAILED_TO_CREATE_QUERY,     // Failed to create query for sample
-
-    // OpenGL error messages
-    RMT_ERROR_OPENGL_ERROR,                     // Generic OpenGL error, no need to expose detail since app will need an OpenGL error callback registered
-
-    RMT_ERROR_CUDA_UNKNOWN,
-} rmtError;
-
-
-typedef enum rmtSampleFlags
-{
-    // Default behaviour
-    RMTSF_None          = 0,
-
-    // Search parent for same-named samples and merge timing instead of adding a new sample
-    RMTSF_Aggregate     = 1,
-} rmtSampleFlags;
-
-
-/*
-------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------
-   Public Interface
-------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------
-*/
-
-
-
-// Can call remotery functions on a null pointer
-// TODO: Can embed extern "C" in these macros?
-
-#define rmt_Settings()                                                              \
-    RMT_OPTIONAL_RET(RMT_ENABLED, _rmt_Settings(), NULL )
-
-#define rmt_CreateGlobalInstance(rmt)                                               \
-    RMT_OPTIONAL_RET(RMT_ENABLED, _rmt_CreateGlobalInstance(rmt), RMT_ERROR_NONE)
-
-#define rmt_DestroyGlobalInstance(rmt)                                              \
-    RMT_OPTIONAL(RMT_ENABLED, _rmt_DestroyGlobalInstance(rmt))
-
-#define rmt_SetGlobalInstance(rmt)                                                  \
-    RMT_OPTIONAL(RMT_ENABLED, _rmt_SetGlobalInstance(rmt))
-
-#define rmt_GetGlobalInstance()                                                     \
-    RMT_OPTIONAL_RET(RMT_ENABLED, _rmt_GetGlobalInstance(), NULL)
-
-#define rmt_SetCurrentThreadName(rmt)                                               \
-    RMT_OPTIONAL(RMT_ENABLED, _rmt_SetCurrentThreadName(rmt))
-
-#define rmt_LogText(text)                                                           \
-    RMT_OPTIONAL(RMT_ENABLED, _rmt_LogText(text))
-
-#define rmt_BeginCPUSample(name, flags)                                             \
-    RMT_OPTIONAL(RMT_ENABLED, {                                                     \
-        static rmtU32 rmt_sample_hash_##name = 0;                                   \
-        _rmt_BeginCPUSample(#name, flags, &rmt_sample_hash_##name);                 \
-    })
-
-#define rmt_BeginCPUSampleDynamic(namestr, flags)                                   \
-    RMT_OPTIONAL(RMT_ENABLED, _rmt_BeginCPUSample(namestr, flags, NULL))
-
-#define rmt_EndCPUSample()                                                          \
-    RMT_OPTIONAL(RMT_ENABLED, _rmt_EndCPUSample())
-
-
-// Callback function pointer types
-typedef void* (*rmtMallocPtr)(void* mm_context, rmtU32 size);
-typedef void* (*rmtReallocPtr)(void* mm_context, void* ptr, rmtU32 size);
-typedef void (*rmtFreePtr)(void* mm_context, void* ptr);
-typedef void (*rmtInputHandlerPtr)(const char* text, void* context);
-
-
-// Struture to fill in to modify Remotery default settings
-typedef struct rmtSettings
-{
-    // Which port to listen for incoming connections on
-    rmtU16 port;
-
-    // Only allow connections on localhost?
-    // For dev builds you may want to access your game from other devices but if
-    // you distribute a game to your players with Remotery active, probably best
-    // to limit connections to localhost.
-    rmtBool limit_connections_to_localhost;
-
-    // How long to sleep between server updates, hopefully trying to give
-    // a little CPU back to other threads.
-    rmtU32 msSleepBetweenServerUpdates;
-
-    // Size of the internal message queues Remotery uses
-    // Will be rounded to page granularity of 64k
-    rmtU32 messageQueueSizeInBytes;
-
-    // If the user continuously pushes to the message queue, the server network
-    // code won't get a chance to update unless there's an upper-limit on how
-    // many messages can be consumed per loop.
-    rmtU32 maxNbMessagesPerUpdate;
-
-    // Callback pointers for memory allocation
-    rmtMallocPtr malloc;
-    rmtReallocPtr realloc;
-    rmtFreePtr free;
-    void* mm_context;
-
-    // Callback pointer for receiving input from the Remotery console
-    rmtInputHandlerPtr input_handler;
-
-    // Context pointer that gets sent to Remotery console callback function
-    void* input_handler_context;
-
-    rmtPStr logFilename;
-} rmtSettings;
-
-
-// Structure to fill in when binding CUDA to Remotery
-typedef struct rmtCUDABind
-{
-    // The main context that all driver functions apply before each call
-    void* context;
-
-    // Driver API function pointers that need to be pointed to
-    // Untyped so that the CUDA headers are not required in this file
-    // NOTE: These are named differently to the CUDA functions because the CUDA API has a habit of using
-    // macros to point function calls to different versions, e.g. cuEventDestroy is a macro for
-    // cuEventDestroy_v2.
-    void* CtxSetCurrent;
-    void* CtxGetCurrent;
-    void* EventCreate;
-    void* EventDestroy;
-    void* EventRecord;
-    void* EventQuery;
-    void* EventElapsedTime;
-
-} rmtCUDABind;
-
-
-// Call once after you've initialised CUDA to bind it to Remotery
-#define rmt_BindCUDA(bind)                                                  \
-    RMT_OPTIONAL(RMT_USE_CUDA, _rmt_BindCUDA(bind))
-
-// Mark the beginning of a CUDA sample on the specified asynchronous stream
-#define rmt_BeginCUDASample(name, stream)                                   \
-    RMT_OPTIONAL(RMT_USE_CUDA, {                                            \
-        static rmtU32 rmt_sample_hash_##name = 0;                           \
-        _rmt_BeginCUDASample(#name, &rmt_sample_hash_##name, stream);       \
-    })
-
-// Mark the end of a CUDA sample on the specified asynchronous stream
-#define rmt_EndCUDASample(stream)                                           \
-    RMT_OPTIONAL(RMT_USE_CUDA, _rmt_EndCUDASample(stream))
-
-
-#define rmt_BindD3D11(device, context)                                      \
-    RMT_OPTIONAL(RMT_USE_D3D11, _rmt_BindD3D11(device, context))
-
-#define rmt_UnbindD3D11()                                                   \
-    RMT_OPTIONAL(RMT_USE_D3D11, _rmt_UnbindD3D11())
-
-#define rmt_BeginD3D11Sample(name)                                          \
-    RMT_OPTIONAL(RMT_USE_D3D11, {                                           \
-        static rmtU32 rmt_sample_hash_##name = 0;                           \
-        _rmt_BeginD3D11Sample(#name, &rmt_sample_hash_##name);              \
-    })
-
-#define rmt_BeginD3D11SampleDynamic(namestr)                                \
-    RMT_OPTIONAL(RMT_USE_D3D11, _rmt_BeginD3D11Sample(namestr, NULL))
-
-#define rmt_EndD3D11Sample()                                                \
-    RMT_OPTIONAL(RMT_USE_D3D11, _rmt_EndD3D11Sample())
-
-
-#define rmt_BindOpenGL()                                                    \
-    RMT_OPTIONAL(RMT_USE_OPENGL, _rmt_BindOpenGL())
-
-#define rmt_UnbindOpenGL()                                                  \
-    RMT_OPTIONAL(RMT_USE_OPENGL, _rmt_UnbindOpenGL())
-
-#define rmt_BeginOpenGLSample(name)                                         \
-    RMT_OPTIONAL(RMT_USE_OPENGL, {                                          \
-        static rmtU32 rmt_sample_hash_##name = 0;                           \
-        _rmt_BeginOpenGLSample(#name, &rmt_sample_hash_##name);             \
-    })
-
-#define rmt_BeginOpenGLSampleDynamic(namestr)                               \
-    RMT_OPTIONAL(RMT_USE_OPENGL, _rmt_BeginOpenGLSample(namestr, NULL))
-
-#define rmt_EndOpenGLSample()                                               \
-    RMT_OPTIONAL(RMT_USE_OPENGL, _rmt_EndOpenGLSample())
-
-
-#define rmt_BindMetal(command_buffer)                                       \
-    RMT_OPTIONAL(RMT_USE_METAL, _rmt_BindMetal(command_buffer));
-
-#define rmt_UnbindMetal()                                                   \
-    RMT_OPTIONAL(RMT_USE_METAL, _rmt_UnbindMetal());
-
-#define rmt_BeginMetalSample(name)                                          \
-    RMT_OPTIONAL(RMT_USE_METAL, {                                           \
-        static rmtU32 rmt_sample_hash_##name = 0;                           \
-        _rmt_BeginMetalSample(#name, &rmt_sample_hash_##name);              \
-    })
-
-#define rmt_BeginMetalSampleDynamic(namestr)                                \
-    RMT_OPTIONAL(RMT_USE_METAL, _rmt_BeginMetalSample(namestr, NULL))
-
-#define rmt_EndMetalSample()                                                \
-    RMT_OPTIONAL(RMT_USE_METAL, _rmt_EndMetalSample())
-
-
-
-
-/*
-------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------
-   C++ Public Interface Extensions
-------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------
-*/
-
-
-
-#ifdef __cplusplus
-
-
-#if RMT_ENABLED
-
-// Types that end samples in their destructors
-extern "C" RMT_API void _rmt_EndCPUSample(void);
-struct rmt_EndCPUSampleOnScopeExit
-{
-    ~rmt_EndCPUSampleOnScopeExit()
-    {
-        _rmt_EndCPUSample();
-    }
-};
-#if RMT_USE_CUDA
-extern "C" RMT_API void _rmt_EndCUDASample(void* stream);
-struct rmt_EndCUDASampleOnScopeExit
-{
-    rmt_EndCUDASampleOnScopeExit(void* stream) : stream(stream)
-    {
-    }
-    ~rmt_EndCUDASampleOnScopeExit()
-    {
-        _rmt_EndCUDASample(stream);
-    }
-    void* stream;
-};
-#endif
-#if RMT_USE_D3D11
-extern "C" RMT_API void _rmt_EndD3D11Sample(void);
-struct rmt_EndD3D11SampleOnScopeExit
-{
-    ~rmt_EndD3D11SampleOnScopeExit()
-    {
-        _rmt_EndD3D11Sample();
-    }
-};
-#endif
-
-#if RMT_USE_OPENGL
-extern "C" RMT_API void _rmt_EndOpenGLSample(void);
-struct rmt_EndOpenGLSampleOnScopeExit
-{
-    ~rmt_EndOpenGLSampleOnScopeExit()
-    {
-        _rmt_EndOpenGLSample();
-    }
-};
-#endif
-
-#if RMT_USE_METAL
-extern "C" RMT_API void _rmt_EndMetalSample(void);
-struct rmt_EndMetalSampleOnScopeExit
-{
-    ~rmt_EndMetalSampleOnScopeExit()
-    {
-        _rmt_EndMetalSample();
-    }
-};
-#endif
-
-#endif
-
-
-
-// Pairs a call to rmt_Begin<TYPE>Sample with its call to rmt_End<TYPE>Sample when leaving scope
-#define rmt_ScopedCPUSample(name, flags)                                                                \
-        RMT_OPTIONAL(RMT_ENABLED, rmt_BeginCPUSample(name, flags));                                     \
-        RMT_OPTIONAL(RMT_ENABLED, rmt_EndCPUSampleOnScopeExit rmt_ScopedCPUSample##name);
-#define rmt_ScopedCUDASample(name, stream)                                                              \
-        RMT_OPTIONAL(RMT_USE_CUDA, rmt_BeginCUDASample(name, stream));                                  \
-        RMT_OPTIONAL(RMT_USE_CUDA, rmt_EndCUDASampleOnScopeExit rmt_ScopedCUDASample##name(stream));
-#define rmt_ScopedD3D11Sample(name)                                                                     \
-        RMT_OPTIONAL(RMT_USE_D3D11, rmt_BeginD3D11Sample(name));                                        \
-        RMT_OPTIONAL(RMT_USE_D3D11, rmt_EndD3D11SampleOnScopeExit rmt_ScopedD3D11Sample##name);
-#define rmt_ScopedOpenGLSample(name)                                                                    \
-        RMT_OPTIONAL(RMT_USE_OPENGL, rmt_BeginOpenGLSample(name));                                      \
-        RMT_OPTIONAL(RMT_USE_OPENGL, rmt_EndOpenGLSampleOnScopeExit rmt_ScopedOpenGLSample##name);
-#define rmt_ScopedMetalSample(name)                                                                     \
-        RMT_OPTIONAL(RMT_USE_METAL, rmt_BeginMetalSample(name));                                        \
-        RMT_OPTIONAL(RMT_USE_METAL, rmt_EndMetalSampleOnScopeExit rmt_ScopedMetalSample##name);
-
-#endif
-
-
-
-/*
-------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------
-   Private Interface - don't directly call these
-------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------
-*/
-
-
-
-#if RMT_ENABLED
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-RMT_API rmtSettings* _rmt_Settings( void );
-RMT_API enum rmtError _rmt_CreateGlobalInstance(Remotery** remotery);
-RMT_API void _rmt_DestroyGlobalInstance(Remotery* remotery);
-RMT_API void _rmt_SetGlobalInstance(Remotery* remotery);
-RMT_API Remotery* _rmt_GetGlobalInstance(void);
-RMT_API void _rmt_SetCurrentThreadName(rmtPStr thread_name);
-RMT_API void _rmt_LogText(rmtPStr text);
-RMT_API void _rmt_BeginCPUSample(rmtPStr name, rmtU32 flags, rmtU32* hash_cache);
-RMT_API void _rmt_EndCPUSample(void);
-
-#if RMT_USE_CUDA
-RMT_API void _rmt_BindCUDA(const rmtCUDABind* bind);
-RMT_API void _rmt_BeginCUDASample(rmtPStr name, rmtU32* hash_cache, void* stream);
-RMT_API void _rmt_EndCUDASample(void* stream);
-#endif
-
-#if RMT_USE_D3D11
-RMT_API void _rmt_BindD3D11(void* device, void* context);
-RMT_API void _rmt_UnbindD3D11(void);
-RMT_API void _rmt_BeginD3D11Sample(rmtPStr name, rmtU32* hash_cache);
-RMT_API void _rmt_EndD3D11Sample(void);
-#endif
-
-#if RMT_USE_OPENGL
-RMT_API void _rmt_BindOpenGL();
-RMT_API void _rmt_UnbindOpenGL(void);
-RMT_API void _rmt_BeginOpenGLSample(rmtPStr name, rmtU32* hash_cache);
-RMT_API void _rmt_EndOpenGLSample(void);
-#endif
-
-#if RMT_USE_METAL
-RMT_API void _rmt_BeginMetalSample(rmtPStr name, rmtU32* hash_cache);
-RMT_API void _rmt_EndMetalSample(void);
-#endif
-
-#ifdef __cplusplus
-
-}
-#endif
-
-#if RMT_USE_METAL
-#ifdef __OBJC__
-RMT_API void _rmt_BindMetal(id command_buffer);
-RMT_API void _rmt_UnbindMetal();
-#endif
-#endif
-
-#endif  // RMT_ENABLED
-
-
-#endif

+ 0 - 49
3rdparty/remotery/lib/RemoteryMetal.mm

@@ -1,49 +0,0 @@
-
-#include <Foundation/NSThread.h>
-#include <Foundation/NSDictionary.h>
-#include <Foundation/NSString.h>
-
-#import <Metal/Metal.h>
-
-
-// Store command buffer in thread-local so that each thread can point to its own
-void SetCommandBuffer(id command_buffer)
-{
-    NSMutableDictionary* thread_data = [[NSThread currentThread] threadDictionary];
-    thread_data[@"rmtMTLCommandBuffer"] = command_buffer;
-}
-id GetCommandBuffer()
-{
-    NSMutableDictionary* thread_data = [[NSThread currentThread] threadDictionary];
-    return thread_data[@"rmtMTLCommandBuffer"];
-}
-
-
-void _rmt_BindMetal(id command_buffer)
-{
-    SetCommandBuffer(command_buffer);
-}
-
-
-void _rmt_UnbindMetal()
-{
-    SetCommandBuffer(0);
-}
-
-
-// Needs to be in the same lib for this to work
-unsigned long long rmtMetal_usGetTime();
-
-
-static void SetTimestamp(void* data)
-{
-    *((unsigned long long*)data) = rmtMetal_usGetTime();
-}
-
-
-void rmtMetal_MeasureCommandBuffer(unsigned long long* out_start, unsigned long long* out_end, unsigned int* out_ready)
-{
-    id command_buffer = GetCommandBuffer();
-    [command_buffer addScheduledHandler:^(id <MTLCommandBuffer>){ SetTimestamp(out_start); }];
-    [command_buffer addCompletedHandler:^(id <MTLCommandBuffer>){ SetTimestamp(out_end); *out_ready = 1; }];
-}

+ 0 - 216
3rdparty/remotery/readme.md

@@ -1,216 +0,0 @@
-Remotery
---------
-
-A realtime CPU/GPU profiler hosted in a single C file with a viewer that runs in a web browser.
-
-![screenshot](screenshot.png?raw=true)
-
-Supported features:
-
-* Lightweight instrumentation of multiple threads running on the CPU.
-* Web viewer that runs in Chrome, Firefox and Safari. Custom WebSockets server
-  transmits sample data to the browser on a latent thread.
-* Profiles itself and shows how it's performing in the viewer.
-* Can optionally sample CUDA/D3D11/OpenGL GPU activity.
-* Console output for logging text.
-* Console input for sending commands to your game.
-
-
-Compiling
----------
-
-* Windows (MSVC) - add lib/Remotery.c and lib/Remotery.h to your program. Set include
-  directories to add Remotery/lib path. The required library ws2_32.lib should be picked
-  up through the use of the #pragma comment(lib, "ws2_32.lib") directive in Remotery.c.
-
-* Mac OS X (XCode) - simply add lib/Remotery.c, lib/Remotery.h and lib/Remotery.mm to your program.
-
-* Linux (GCC) - add the source in lib folder. Compilation of the code requires -pthreads for
-  library linkage. For example to compile the same run: cc lib/Remotery.c sample/sample.c
-  -I lib -pthread -lm
-
-You can define some extra macros to modify what features are compiled into Remotery:
-
-    Macro               Default     Description
-
-    RMT_ENABLED         1           Disable this to not include any bits of Remotery in your build
-    RMT_USE_TINYCRT     0           Used by the Celtoys TinyCRT library (not released yet)
-    RMT_USE_CUDA        0           Assuming CUDA headers/libs are setup, allow CUDA profiling
-    RMT_USE_D3D11       0           Assuming Direct3D 11 headers/libs are setup, allow D3D11 GPU profiling
-    RMT_USE_OPENGL      0           Allow OpenGL GPU profiling (dynamically links OpenGL libraries on available platforms)
-    RMT_USE_METAL       0           Allow Metal profiling of command buffers
-
-
-Basic Use
----------
-
-See the sample directory for further examples. A quick example:
-
-    int main()
-    {
-        // Create the main instance of Remotery.
-        // You need only do this once per program.
-        Remotery* rmt;
-        rmt_CreateGlobalInstance(&rmt);
-
-        // Explicit begin/end for C
-        {
-            rmt_BeginCPUSample(LogText, 0);
-            rmt_LogText("Time me, please!");
-            rmt_EndCPUSample();
-        }
-
-        // Scoped begin/end for C++
-        {
-            rmt_ScopedCPUSample(LogText, 0);
-            rmt_LogText("Time me, too!");
-        }
-
-        // Destroy the main instance of Remotery.
-        rmt_DestroyGlobalInstance(rmt);
-    }
-
-
-Running the Viewer
-------------------
-
-Double-click or launch `vis/index.html` from the browser.
-
-
-Sampling CUDA GPU activity
---------------------------
-
-Remotery allows for profiling multiple threads of CUDA execution using different asynchronous streams
-that must all share the same context. After initialising both Remotery and CUDA you need to bind the
-two together using the call:
-
-    rmtCUDABind bind;
-    bind.context = m_Context;
-    bind.CtxSetCurrent = &cuCtxSetCurrent;
-    bind.CtxGetCurrent = &cuCtxGetCurrent;
-    bind.EventCreate = &cuEventCreate;
-    bind.EventDestroy = &cuEventDestroy;
-    bind.EventRecord = &cuEventRecord;
-    bind.EventQuery = &cuEventQuery;
-    bind.EventElapsedTime = &cuEventElapsedTime;
-    rmt_BindCUDA(&bind);
-
-Explicitly pointing to the CUDA interface allows Remotery to be included anywhere in your project without
-need for you to link with the required CUDA libraries. After the bind completes you can safely sample any
-CUDA activity:
-
-    CUstream stream;
-
-    // Explicit begin/end for C
-    {
-        rmt_BeginCUDASample(UnscopedSample, stream);
-        // ... CUDA code ...
-        rmt_EndCUDASample(stream);
-    }
-
-    // Scoped begin/end for C++
-    {
-        rmt_ScopedCUDASample(ScopedSample, stream);
-        // ... CUDA code ...
-    }
-
-Remotery supports only one context for all threads and will use cuCtxGetCurrent and cuCtxSetCurrent to
-ensure the current thread has the context you specify in rmtCUDABind.context.
-
-
-Sampling Direct3D 11 GPU activity
----------------------------------
-
-Remotery allows sampling of GPU activity on your main D3D11 context. After initialising Remotery, you need
-to bind it to D3D11 with a single call from the thread that owns the device context:
-
-    // Parameters are ID3D11Device* and ID3D11DeviceContext*
-    rmt_BindD3D11(d3d11_device, d3d11_context);
-
-Sampling is then a simple case of:
-
-    // Explicit begin/end for C
-    {
-        rmt_BeginD3D11Sample(UnscopedSample);
-        // ... D3D code ...
-        rmt_EndD3D11Sample();
-    }
-
-    // Scoped begin/end for C++
-    {
-        rmt_ScopedD3D11Sample(ScopedSample);
-        // ... D3D code ...
-    }
-
-Support for multiple contexts can be added pretty easily if there is demand for the feature. When you shutdown
-your D3D11 device and context, ensure you notify Remotery before shutting down Remotery itself:
-
-    rmt_UnbindD3D11();
-
-
-Sampling OpenGL GPU activity
-----------------------------
-
-Remotery allows sampling of GPU activity on your main OpenGL context. After initialising Remotery, you need
-to bind it to OpenGL with the single call:
-
-    rmt_BindOpenGL();
-
-Sampling is then a simple case of:
-
-    // Explicit begin/end for C
-    {
-        rmt_BeginOpenGLSample(UnscopedSample);
-        // ... OpenGL code ...
-        rmt_EndOpenGLSample();
-    }
-
-    // Scoped begin/end for C++
-    {
-        rmt_ScopedOpenGLSample(ScopedSample);
-        // ... OpenGL code ...
-    }
-
-Support for multiple contexts can be added pretty easily if there is demand for the feature. When you shutdown
-your OpenGL device and context, ensure you notify Remotery before shutting down Remotery itself:
-
-    rmt_UnbindOpenGL();
-
-
-Sampling Metal GPU activity
----------------------------
-
-Remotery can sample Metal command buffers issued to the GPU from multiple threads. As the Metal API does not
-support finer grained profiling, samples will return only the timing of the bound command buffer, irrespective
-of how many you issue. As such, make sure you bind and sample the command buffer for each call site:
-
-    rmt_BindMetal(mtl_command_buffer);
-    rmt_ScopedMetalSample(command_buffer_name);
-
-The C API supports begin/end also:
-
-    rmt_BindMetal(mtl_command_buffer);
-    rmt_BeginMetalSample(command_buffer_name);
-    ...
-    rmt_EndMetalSample();
-
-
-Applying Configuration Settings
--------------------------------
-
-Before creating your Remotery instance, you can configure its behaviour by retrieving its settings object:
-
-    rmtSettings* settings = rmt_Settings();
-
-Some important settings are:
-
-    // Redirect any Remotery allocations to your own malloc/free, with an additional context pointer
-    // that gets passed to your callbacks.
-    settings->malloc;
-    settings->free;
-    settings->mm_context;
-
-    // Specify an input handler that receives text input from the Remotery console, with an additional
-    // context pointer that gets passed to your callback.
-    settings->input_handler;
-    settings->input_handler_context;

+ 0 - 45
3rdparty/remotery/sample/sample.c

@@ -1,45 +0,0 @@
-#include <stdlib.h>
-#include <math.h>
-#include <signal.h>
-#include <stdio.h>
-#include "Remotery.h"
-
-double delay() {
-    int i, end;
-    double j = 0;
-
-    rmt_BeginCPUSample(delay, 0);
-    for( i = 0, end = rand()/100; i < end; ++i ) {
-        j += sin(i);
-    }
-    rmt_EndCPUSample();
-    return j;
-}
-
-int sig = 0;
-
-/// Allow to close cleanly with ctrl + c
-void sigintHandler(int sig_num) {
-    sig = sig_num;
-    printf("Interrupted\n");
-}
-
-int main( ) {
-    signal(SIGINT, sigintHandler);
-
-    Remotery *rmt;
-
-    if( RMT_ERROR_NONE != rmt_CreateGlobalInstance(&rmt) ) {
-        return -1;
-    }
-
-    while (sig == 0) {
-        rmt_LogText("start profiling");
-        delay();
-        rmt_LogText("end profiling");
-    }
-
-    rmt_DestroyGlobalInstance(rmt);
-    printf("Cleaned up and quit\n");
-    return 0;
-}

BIN
3rdparty/remotery/screenshot.png


+ 0 - 194
3rdparty/remotery/vis/Code/Console.js

@@ -1,194 +0,0 @@
-
-Console = (function()
-{
-	var BORDER = 10;
-	var HEIGHT = 200;
-
-
-	function Console(wm, server)
-	{
-		// Create the window and its controls
-		this.Window = wm.AddWindow("Console", 10, 10, 100, 100);
-		this.PageContainer = this.Window.AddControlNew(new WM.Container(10, 10, 400, 160));
-		DOM.Node.AddClass(this.PageContainer.Node, "ConsoleText");
-		this.AppContainer = this.Window.AddControlNew(new WM.Container(10, 10, 400, 160));
-		DOM.Node.AddClass(this.AppContainer.Node, "ConsoleText");
-		this.UserInput = this.Window.AddControlNew(new WM.EditBox(10, 5, 400, 30, "Input", ""));
-		this.UserInput.SetChangeHandler(Bind(ProcessInput, this));
-		this.Window.ShowNoAnim();
-
-		// This accumulates log text as fast as is required
-		this.PageTextBuffer = "";
-		this.LastPageTextBufferLen = 0;
-		this.AppTextBuffer = "";
-		this.LastAppTextBufferLen = 0;
-
-		// Setup command history control
-		this.CommandHistory = LocalStore.Get("App", "Global", "CommandHistory", [ ]);
-		this.CommandIndex = 0;
-		this.MaxNbCommands = 200;
-		DOM.Event.AddHandler(this.UserInput.EditNode, "keydown", Bind(OnKeyPress, this));
-		DOM.Event.AddHandler(this.UserInput.EditNode, "focus", Bind(OnFocus, this));
-
-		// At a much lower frequency this will update the console window
-		window.setInterval(Bind(UpdateHTML, this), 500);
-
-		// Setup log requests from the server
-		this.Server = server;
-		server.SetConsole(this);
-		server.AddMessageHandler("LOGM", Bind(OnLog, this));
-	}
-
-
-	Console.prototype.Log = function(text)
-	{
-		this.PageTextBuffer = LogText(this.PageTextBuffer, text);
-	}
-
-
-	Console.prototype.WindowResized = function(width, height)
-	{
-		// Place window
-		this.Window.SetPosition(BORDER, height - BORDER - 200);
-		this.Window.SetSize(width - 2 * BORDER, HEIGHT);
-
-		// Place controls
-		var parent_size = this.Window.Size;
-		var mid_w = parent_size[0] / 3;
-		this.UserInput.SetPosition(BORDER, parent_size[1] - 2 * BORDER - 30);
-		this.UserInput.SetSize(parent_size[0] - 100, 18);
-		var output_height = this.UserInput.Position[1] - 2 * BORDER;
-		this.PageContainer.SetPosition(BORDER, BORDER);
-		this.PageContainer.SetSize(mid_w - 2 * BORDER, output_height);
-		this.AppContainer.SetPosition(mid_w, BORDER);
-		this.AppContainer.SetSize(parent_size[0] - mid_w - BORDER, output_height);
-	}
-
-
-	function OnLog(self, socket, data_view)
-	{
-	    var data_view_reader = new DataViewReader(data_view, 4);
-	    var text = data_view_reader.GetString();
-	    self.AppTextBuffer = LogText(self.AppTextBuffer, text);
-	}
-
-
-	function LogText(existing_text, new_text)
-	{
-		// Filter the text a little to make it safer
-		if (new_text == null)
-			new_text = "NULL";
-
-		// Find and convert any HTML entities, ensuring the browser doesn't parse any embedded HTML code
-		// This also allows the log to contain arbitrary C++ code (e.g. assert comparison operators)
-		new_text = Convert.string_to_html_entities(new_text);
-
-		// Prefix date and end with new line
-		var d = new Date();
-		new_text = "[" + d.toLocaleTimeString() + "] " + new_text + "<br>";
-
-		// Append to local text buffer and ensure clip the oldest text to ensure a max size
-		existing_text = existing_text + new_text;
-		var max_len = 10 * 1024;
-		var len = existing_text.length;
-		if (len > max_len)
-			existing_text = existing_text.substr(len - max_len, max_len);
-
-		return existing_text;
-	}
-
-
-	function UpdateHTML(self)
-	{
-		// Reset the current text buffer as html
-
-		if (self.LastPageTextBufferLen != self.PageTextBuffer.length)
-		{
-			var page_node = self.PageContainer.Node;
-			page_node.innerHTML = self.PageTextBuffer;
-			page_node.scrollTop = page_node.scrollHeight;
-			self.LastPageTextBufferLen = self.PageTextBuffer.length;
-		}
-
-		if (self.LastAppTextBufferLen != self.AppTextBuffer.length)
-		{		
-			var app_node = self.AppContainer.Node;
-			app_node.innerHTML = self.AppTextBuffer;
-			app_node.scrollTop = app_node.scrollHeight;
-			self.LastAppTextBufferLen = self.AppTextBuffer.length;
-		}
-	}
-
-
-	function ProcessInput(self, node)
-	{
-		// Send the message exactly
-		var msg = node.value;
-		self.Server.Send("CONI" + msg);
-
-		// Emit to console and clear
-		self.Log("> " + msg);
-		self.UserInput.SetValue("");
-
-		// Keep track of recently issued commands, with an upper bound
-		self.CommandHistory.push(msg);
-		var extra_commands = self.CommandHistory.length - self.MaxNbCommands;
-		if (extra_commands > 0)
-			self.CommandHistory.splice(0, extra_commands);
-
-		// Set command history index to the most recent command
-		self.CommandIndex = self.CommandHistory.length;
-
-		// Backup to local store
-		LocalStore.Set("App", "Global", "CommandHistory", self.CommandHistory);
-
-		// Keep focus with the edit box
-		return true;
-	}
-
-
-	function OnKeyPress(self, evt)
-	{
-		evt = DOM.Event.Get(evt);
-
-		if (evt.keyCode == Keyboard.Codes.UP)
-		{
-			if (self.CommandHistory.length > 0)
-			{
-				// Cycle backwards through the command history
-				self.CommandIndex--;
-				if (self.CommandIndex < 0)
-					self.CommandIndex = self.CommandHistory.length - 1;
-				var command = self.CommandHistory[self.CommandIndex];
-				self.UserInput.SetValue(command);
-			}
-
-			// Stops default behaviour of moving cursor to the beginning
-			DOM.Event.StopDefaultAction(evt);
-		}
-
-		else if (evt.keyCode == Keyboard.Codes.DOWN)
-		{
-			if (self.CommandHistory.length > 0)
-			{
-				// Cycle fowards through the command history
-				self.CommandIndex = (self.CommandIndex + 1) % self.CommandHistory.length;
-				var command = self.CommandHistory[self.CommandIndex];
-				self.UserInput.SetValue(command);
-			}
-
-			// Stops default behaviour of moving cursor to the end
-			DOM.Event.StopDefaultAction(evt);
-		}
-	}
-
-
-	function OnFocus(self)
-	{
-		// Reset command index on focus
-		self.CommandIndex = self.CommandHistory.length;
-	}
-
-
-	return Console;
-})();

+ 0 - 47
3rdparty/remotery/vis/Code/DataViewReader.js

@@ -1,47 +0,0 @@
-
-//
-// Simple wrapper around DataView that auto-advances the read offset and provides
-// a few common data type conversions specific to this app
-//
-DataViewReader = (function ()
-{
-    function DataViewReader(data_view, offset)
-    {
-        this.DataView = data_view;
-        this.Offset = offset;
-    }
-
-    DataViewReader.prototype.GetUInt32 = function ()
-    {
-        var v = this.DataView.getUint32(this.Offset, true);
-        this.Offset += 4;
-        return v;
-    }
-
-    DataViewReader.prototype.GetUInt64 = function ()
-    {
-        var v = this.DataView.getFloat64(this.Offset, true);
-        this.Offset += 8;
-        return v;
-    }
-
-    DataViewReader.prototype.GetStringOfLength = function (string_length)
-    {
-        var string = "";
-        for (var i = 0; i < string_length; i++)
-        {
-            string += String.fromCharCode(this.DataView.getInt8(this.Offset));
-            this.Offset++;
-        }
-
-        return string;
-    }
-
-    DataViewReader.prototype.GetString = function ()
-    {
-        var string_length = this.GetUInt32();
-        return this.GetStringOfLength(string_length);
-    }
-
-    return DataViewReader;
-})();

+ 0 - 61
3rdparty/remotery/vis/Code/PixelTimeRange.js

@@ -1,61 +0,0 @@
-
-
-PixelTimeRange = (function()
-{
-	function PixelTimeRange(start_us, span_us, span_px)
-	{
-		this.Span_px = span_px;
-		this.Set(start_us, span_us);
-	}
-
-
-	PixelTimeRange.prototype.Set = function(start_us, span_us)
-	{
-		this.Start_us = start_us;
-		this.Span_us = span_us;
-		this.End_us = this.Start_us + span_us;
-		this.usPerPixel = this.Span_px / this.Span_us;
-	}
-
-
-	PixelTimeRange.prototype.SetStart = function(start_us)
-	{
-		this.Start_us = start_us;
-		this.End_us = start_us + this.Span_us;
-	}
-
-
-	PixelTimeRange.prototype.SetEnd = function(end_us)
-	{
-		this.End_us = end_us;
-		this.Start_us = end_us - this.Span_us;
-	}
-
-
-	PixelTimeRange.prototype.SetPixelSpan = function(span_px)
-	{
-		this.Span_px = span_px;
-		this.usPerPixel = this.Span_px / this.Span_us;
-	}
-
-
-	PixelTimeRange.prototype.PixelOffset = function(time_us)
-	{
-		return Math.floor((time_us - this.Start_us) * this.usPerPixel);
-	}
-
-
-	PixelTimeRange.prototype.PixelSize = function(time_us)
-	{
-		return Math.floor(time_us * this.usPerPixel);
-	}
-
-
-	PixelTimeRange.prototype.Clone = function()
-	{
-		return new PixelTimeRange(this.Start_us, this.Span_us, this.Span_px);
-	}
-
-
-	return PixelTimeRange;
-})();

+ 0 - 330
3rdparty/remotery/vis/Code/Remotery.js

@@ -1,330 +0,0 @@
-
-//
-// TODO: Window resizing needs finer-grain control
-// TODO: Take into account where user has moved the windows
-// TODO: Controls need automatic resizing within their parent windows
-//
-
-
-Settings = (function()
-{
-	function Settings()
-	{
-		this.IsPaused = false;
-	}
-
-	return Settings;
-
-})();
-
-
-Remotery = (function()
-{
-	// crack the url and get the parameter we want
-	var getUrlParameter = function getUrlParameter( search_param) 
-	{
-		var page_url = decodeURIComponent( window.location.search.substring(1) ),
-						url_vars = page_url.split('&'),
-						param_name,
-						i;
-
-		for (i = 0; i < url_vars.length; i++) 
-		{
-			param_name = url_vars[i].split('=');
-
-			if (param_name[0] === search_param) 
-			{
-				return param_name[1] === undefined ? true : param_name[1];
-			}
-		}
-	};
-
-	function Remotery()
-	{
-		this.WindowManager = new WM.WindowManager();
-		this.Settings = new Settings();
-
-		// "addr" param is ip:port and will override the local store version if passed in the URL
-		var addr = getUrlParameter( "addr" );
-		if ( addr != null )
-			this.ConnectionAddress = "ws://" + addr + "/rmt";
-		else
-			this.ConnectionAddress = LocalStore.Get("App", "Global", "ConnectionAddress", "ws://127.0.0.1:17815/rmt");
-
-		this.Server = new WebSocketConnection();
-		this.Server.AddConnectHandler(Bind(OnConnect, this));
-
-		// Create the console up front as everything reports to it
-		this.Console = new Console(this.WindowManager, this.Server);
-
-		// Create required windows
-		this.TitleWindow = new TitleWindow(this.WindowManager, this.Settings, this.Server, this.ConnectionAddress);
-		this.TitleWindow.SetConnectionAddressChanged(Bind(OnAddressChanged, this));
-		this.TimelineWindow = new TimelineWindow(this.WindowManager, this.Settings, this.Server, Bind(OnTimelineCheck, this));
-		this.TimelineWindow.SetOnHover(Bind(OnSampleHover, this));
-		this.TimelineWindow.SetOnSelected(Bind(OnSampleSelected, this));
-
-		this.NbSampleWindows = 0;
-		this.SampleWindows = { };
-		this.FrameHistory = { };
-		this.SelectedFrames = { };
-		this.NameMap = { };
-
-		this.Server.AddMessageHandler("SMPL", Bind(OnSamples, this));
-		this.Server.AddMessageHandler("SSMP", Bind(OnSampleName, this));
-
-		// Kick-off the auto-connect loop
-		AutoConnect(this);
-
-		// Hook up resize event handler
-		DOM.Event.AddHandler(window, "resize", Bind(OnResizeWindow, this));
-		OnResizeWindow(this);
-
-		// Hook up browser-native canvas refresh
-		this.DisplayFrame = 0;
-		this.LastKnownPause = this.Settings.IsPaused;
-		var self = this;
-		(function display_loop()
-		{
-			window.requestAnimationFrame(display_loop);
-			DrawTimeline(self);
-		})();
-	}
-
-
-	function AutoConnect(self)
-	{
-		// Only attempt to connect if there isn't already a connection or an attempt to connect
-		if (!self.Server.Connected())
-			self.Server.Connect(self.ConnectionAddress);
-
-		// Always schedule another check
-		window.setTimeout(Bind(AutoConnect, self), 2000);
-	}
-
-
-	function OnConnect(self)
-	{
-		// Connection address has been validated
-		LocalStore.Set("App", "Global", "ConnectionAddress", self.ConnectionAddress);
-	}
-
-
-	function OnAddressChanged(self, node)
-	{
-		// Update and disconnect, relying on auto-connect to reconnect
-		self.ConnectionAddress = node.value;
-		self.Server.Disconnect();
-
-		// Give input focus away
-		return false;
-	}
-
-
-	function DrawTimeline(self)
-	{
-		// Has pause state changed?
-		if (self.Settings.IsPaused != self.LastKnownPaused)
-		{
-			// When switching TO paused, draw one last frame to ensure the sample text gets drawn
-			self.LastKnownPaused = self.Settings.IsPaused;
-			self.TimelineWindow.DrawAllRows();
-			return;
-		}
-
-		// Don't waste time drawing the timeline when paused
-		if (self.Settings.IsPaused)
-			return;
-
-		// requestAnimationFrame can run up to 60hz which is way too much for drawing the timeline
-		// Assume it's running at 60hz and skip frames to achieve 10hz instead
-	    // Doing this instead of using setTimeout because it's better for browser rendering (or; will be once WebGL is in use)
-        // TODO: Expose as config variable because high refresh rate is great when using a separate viewiing machine
-		if ((self.DisplayFrame % 10) == 0)
-			self.TimelineWindow.DrawAllRows();
-
-		self.DisplayFrame++;
-	}
-
-
-	function DecodeSample(self, data_view_reader)
-	{
-	    var sample = {};
-
-        // Get name hash and lookup name it map
-	    sample.name_hash = data_view_reader.GetUInt32();
-	    sample.name = self.NameMap[sample.name_hash];
-
-        // If the name doesn't exist in the map yet, request it from the server
-	    if (sample.name == undefined)
-	    {
-            // Meanwhile, store the hash as the name
-	        sample.name = sample.name_hash;
-	        self.Server.Send("GSMP" + sample.name);
-	    }
-
-        // Get the rest of the sample data
-	    sample.id = data_view_reader.GetUInt32();
-	    sample.colour = data_view_reader.GetStringOfLength(7);
-	    sample.us_start = data_view_reader.GetUInt64();
-	    sample.us_length = data_view_reader.GetUInt64();
-
-        // Recurse into children
-	    sample.children = [];
-	    DecodeSampleArray(self, data_view_reader, sample.children);
-
-	    return sample;
-	}
-
-
-	function DecodeSampleArray(self, data_view_reader, samples)
-	{
-	    var nb_samples = data_view_reader.GetUInt32();
-	    for (var i = 0; i < nb_samples; i++)
-	    {
-	        var sample = DecodeSample(self, data_view_reader);
-            samples.push(sample)
-	    }
-	}
-
-
-	function DecodeSamples(self, data_view_reader)
-	{
-        // Message-specific header
-	    var message = { };
-	    message.thread_name = data_view_reader.GetString();
-	    message.nb_samples = data_view_reader.GetUInt32();
-	    message.sample_digest = data_view_reader.GetUInt32();
-
-        // Read samples
-	    message.samples = [];
-	    message.samples.push(DecodeSample(self, data_view_reader));
-
-	    return message;
-	}
-
-
-	function OnSamples(self, socket, data_view)
-	{
-		// Discard any new samples while paused
-		if (self.Settings.IsPaused)
-		    return;
-
-        // Binary decode incoming sample data
-		var message = DecodeSamples(self, new DataViewReader(data_view, 8));
-		var name = message.thread_name;
-
-	    // Add to frame history for this thread
-		var thread_frame = new ThreadFrame(message);
-		if (!(name in self.FrameHistory))
-			self.FrameHistory[name] = [ ];
-		var frame_history = self.FrameHistory[name];
-		frame_history.push(thread_frame);
-
-		// Discard old frames to keep memory-use constant
-		var max_nb_frames = 10000;
-		var extra_frames = frame_history.length - max_nb_frames;
-		if (extra_frames > 0)
-		    frame_history.splice(0, extra_frames);
-
-		// Create sample windows on-demand
-		if (!(name in self.SampleWindows))
-		{
-			self.SampleWindows[name] = new SampleWindow(self.WindowManager, name, self.NbSampleWindows);
-			self.SampleWindows[name].WindowResized(self.TimelineWindow.Window, self.Console.Window);
-			self.NbSampleWindows++;
-			MoveSampleWindows(this);
-		}
-
-		// Set on the window and timeline
-		self.SampleWindows[name].OnSamples(message.nb_samples, message.sample_digest, message.samples);
-		self.TimelineWindow.OnSamples(name, frame_history);
-	}
-
-
-	function OnSampleName(self, socket, data_view)
-	{
-        // Add any names sent by the server to the local map
-	    var data_view_reader = new DataViewReader(data_view, 4);
-	    var name_hash = data_view_reader.GetUInt32();
-	    var name = data_view_reader.GetString();
-	    self.NameMap[name_hash] = name;
-	}
-
-
-	function OnTimelineCheck(self, name, evt)
-	{
-		// Show/hide the equivalent sample window and move all the others to occupy any left-over space
-		var target = DOM.Event.GetNode(evt);
-		self.SampleWindows[name].SetVisible(target.checked);
-		MoveSampleWindows(self);
-	}
-
-
-	function MoveSampleWindows(self)
-	{
-		// Stack all windows next to each other
-		var xpos = 0;
-		for (var i in self.SampleWindows)
-		{
-			var sample_window = self.SampleWindows[i];
-			if (sample_window.Visible)
-				sample_window.SetXPos(xpos++, self.TimelineWindow.Window, self.Console.Window);
-		}
-	}
-
-
-	function OnSampleHover(self, thread_name, hover)
-	{
-		// Hover only changes sample window contents when paused
-		var sample_window = self.SampleWindows[thread_name];
-		if (sample_window && self.Settings.IsPaused)
-		{
-			if (hover == null)
-			{
-				// When there's no hover, go back to the selected frame
-				if (self.SelectedFrames[thread_name])
-				{
-					var frame = self.SelectedFrames[thread_name];
-					sample_window.OnSamples(frame.NbSamples, frame.SampleDigest, frame.Samples);
-				}
-			}
-
-			else
-			{
-				// Populate with sample under hover
-				var frame = hover[0];
-				sample_window.OnSamples(frame.NbSamples, frame.SampleDigest, frame.Samples);
-			}
-		}
-	}
-
-
-	function OnSampleSelected(self, thread_name, select)
-	{
-		// Lookup sample window set the frame samples on it
-		if (select && thread_name in self.SampleWindows)
-		{
-			var sample_window = self.SampleWindows[thread_name];
-			var frame = select[0];
-			self.SelectedFrames[thread_name] = frame;
-			sample_window.OnSamples(frame.NbSamples, frame.SampleDigest, frame.Samples);
-		}
-	}
-
-
-	function OnResizeWindow(self)
-	{
-		// Resize windows
-		var w = window.innerWidth;
-		var h = window.innerHeight;
-		self.Console.WindowResized(w, h);
-		self.TitleWindow.WindowResized(w, h);
-		self.TimelineWindow.WindowResized(w, h, self.TitleWindow.Window);
-		for (var i in self.SampleWindows)
-			self.SampleWindows[i].WindowResized(self.TimelineWindow.Window, self.Console.Window);
-	}
-
-
-	return Remotery;
-})();

+ 0 - 178
3rdparty/remotery/vis/Code/SampleWindow.js

@@ -1,178 +0,0 @@
-
-SampleWindow = (function()
-{
-	function SampleWindow(wm, name, offset)
-	{
-		// Sample digest for checking if grid needs to be repopulated
-		this.NbSamples = 0;
-		this.SampleDigest = null;
-
-		this.XPos = 10 + offset * 410;
-		this.Window = wm.AddWindow(name, 100, 100, 100, 100);
-		this.Window.Show();
-		this.Visible = true;
-
-		// Create a grid that's indexed by the unique sample ID
-		this.Grid = this.Window.AddControlNew(new WM.Grid(0, 0, 380, 400));
-		this.RootRow = this.Grid.Rows.Add({ "Name": "Samples" }, "GridGroup", { "Name": "GridGroup" });
-		this.RootRow.Rows.AddIndex("_ID");
-	}
-
-
-	SampleWindow.prototype.SetXPos = function(xpos, top_window, bottom_window)
-	{
-		Anim.Animate(
-			Bind(AnimatedMove, this, top_window, bottom_window),
-			this.XPos, 10 + xpos * 410, 0.25);
-	}
-
-
-	function AnimatedMove(self, top_window, bottom_window, val)
-	{
-		self.XPos = val;
-		self.WindowResized(top_window, bottom_window);
-	}
-
-
-	SampleWindow.prototype.SetVisible = function(visible)
-	{
-		if (visible != this.Visible)
-		{
-			if (visible == true)
-				this.Window.Show();
-			else
-				this.Window.Hide();
-
-			this.Visible = visible;
-		}
-	}
-
-
-	SampleWindow.prototype.WindowResized = function(top_window, bottom_window)
-	{
-		var top = top_window.Position[1] + top_window.Size[1] + 10;
-		this.Window.SetPosition(this.XPos, top_window.Position[1] + top_window.Size[1] + 10);
-		this.Window.SetSize(400, bottom_window.Position[1] - 10 - top);
-	}
-
-
-	SampleWindow.prototype.OnSamples = function(nb_samples, sample_digest, samples)
-	{
-		if (!this.Visible)
-			return;
-
-		// Recreate all the HTML if the number of samples gets bigger
-		if (nb_samples > this.NbSamples)
-		{
-			GrowGrid(this.RootRow, nb_samples);
-			this.NbSamples = nb_samples;
-		}
-
-		// If the content of the samples changes from previous update, update them all
-		if (this.SampleDigest != sample_digest)
-		{
-			this.RootRow.Rows.ClearIndex("_ID");
-			var index = UpdateAllSampleFields(this.RootRow, samples, 0, "");
-			this.SampleDigest = sample_digest;
-
-			// Clear out any left-over rows
-			for (var i = index; i < this.RootRow.Rows.Rows.length; i++)
-			{
-				var row = this.RootRow.Rows.Rows[i];
-				DOM.Node.Hide(row.Node);
-			}
-		}
-
-		else if (this.Visible)
-		{
-			// Otherwise just update the existing sample fields
-		    UpdateChangedSampleFields(this.RootRow, samples, "");
-		}
-	}
-
-
-	function GrowGrid(parent_row, nb_samples)
-	{
-		parent_row.Rows.Clear();
-
-		for (var i = 0; i < nb_samples; i++)
-		{
-			var cell_data =
-			{
-			    _ID: i,
-				Name: "",
-				Control: new WM.Label()
-			};
-
-			var cell_classes =
-			{
-				Name: "SampleNameCell",
-			};
-
-			parent_row.Rows.Add(cell_data, null, cell_classes);
-		}
-	}
-
-
-	function UpdateAllSampleFields(parent_row, samples, index, indent)
-	{
-		for (var i in samples)
-		{
-			var sample = samples[i];
-
-			// Match row allocation in GrowGrid
-			var row = parent_row.Rows.Rows[index++];
-
-			// Sample row may have been hidden previously
-			DOM.Node.Show(row.Node);
-			
-			// Assign unique ID so that the common fast path of updating sample times only
-			// can lookup target samples in the grid
-			row.CellData._ID = sample.id;
-			parent_row.Rows.AddRowToIndex("_ID", sample.id, row);
-
-            // Record sample name for later comparison
-			row.CellData.Name = sample.name;
-			
-		    // Set sample name and colour
-			var name_node = row.CellNodes["Name"];
-			name_node.innerHTML = indent + sample.name;
-			DOM.Node.SetColour(name_node, sample.colour);
-
-			row.CellData.Control.SetText(sample.us_length);
-
-			index = UpdateAllSampleFields(parent_row, sample.children, index, indent + "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;");
-		}
-
-		return index;
-	}
-
-
-	function UpdateChangedSampleFields(parent_row, samples, indent)
-	{
-		for (var i in samples)
-		{
-			var sample = samples[i];
-
-			var row = parent_row.Rows.GetBy("_ID", sample.id);
-			if (row)
-			{
-			    row.CellData.Control.SetText(sample.us_length);
-
-			    // Sample name will change when it switches from hash ID to network-retrieved 
-                // name. Quickly check that before re-applying the HTML for the name.
-			    if (row.CellData.Name != sample.name)
-			    {
-			        var name_node = row.CellNodes["Name"];
-			        row.CellData.Name = sample.name;
-			        name_node.innerHTML = indent + sample.name;
-			    }
-			}
-
-			UpdateChangedSampleFields(parent_row, sample.children, indent + "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;");
-		}
-	}
-
-
-	return SampleWindow;
-})();

+ 0 - 28
3rdparty/remotery/vis/Code/ThreadFrame.js

@@ -1,28 +0,0 @@
-
-
-ThreadFrame = (function()
-{
-	function ThreadFrame(message)
-	{
-		// Persist the required message data
-		this.NbSamples = message.nb_samples;
-		this.SampleDigest = message.sample_digest;
-		this.Samples = message.samples;
-
-		// Calculate the frame start/end times
-		this.StartTime_us = 0;
-		this.EndTime_us = 0;
-		var nb_root_samples = this.Samples.length;
-		if (nb_root_samples > 0)
-		{
-			var last_sample = this.Samples[nb_root_samples - 1];
-			this.StartTime_us = this.Samples[0].us_start;
-			this.EndTime_us = last_sample.us_start + last_sample.us_length;
-		}
-
-		this.Length_us = this.EndTime_us - this.StartTime_us;
-	}
-
-
-	return ThreadFrame;
-})();

+ 0 - 376
3rdparty/remotery/vis/Code/TimelineRow.js

@@ -1,376 +0,0 @@
-
-
-TimelineRow = (function()
-{
-	var row_template = function(){/*
-		<div class='TimelineRow'>
-			<div class='TimelineRowCheck TimelineBox'>
-				<input class='TimelineRowCheckbox' type='checkbox' />
-			</div>
-			<div class='TimelineRowExpand TimelineBox NoSelect'>
-				<div class='TimelineRowExpandButton'>+</div>
-			</div>
-			<div class='TimelineRowExpand TimelineBox NoSelect'>
-				<div class='TimelineRowExpandButton'>-</div>
-			</div>
-			<div class='TimelineRowLabel TimelineBox'></div>
-			<canvas class='TimelineRowCanvas'></canvas>
-			<div style="clear:left"></div>
-		</div>
-*/}.toString().split(/\n/).slice(1, -1).join("\n");
-
-
-	var CANVAS_Y_OFFSET = 0;
-	var CANVAS_BORDER = 1;
-	var SAMPLE_HEIGHT = 16;
-	var SAMPLE_BORDER = 1;
-	var SAMPLE_Y_SPACING = SAMPLE_HEIGHT + SAMPLE_BORDER * 2;
-	var SAMPLE_Y_OFFSET = CANVAS_Y_OFFSET + CANVAS_BORDER + 1;
-
-
-	function TimelineRow(name, width, parent_node, frame_history, check_handler)
-	{
-		this.Name = name;
-
-		// Create the row HTML and add to the parent
-		this.ContainerNode = DOM.Node.CreateHTML(row_template);
-		this.Node = DOM.Node.FindWithClass(this.ContainerNode, "TimelineRowData");
-		this.LabelNode = DOM.Node.FindWithClass(this.ContainerNode, "TimelineRowLabel");
-		this.LabelNode.innerHTML = name;
-		this.CheckboxNode = DOM.Node.FindWithClass(this.ContainerNode, "TimelineRowCheckbox");
-		var expand_node_0 = DOM.Node.FindWithClass(this.ContainerNode, "TimelineRowExpand", 0);
-		var expand_node_1 = DOM.Node.FindWithClass(this.ContainerNode, "TimelineRowExpand", 1);
-		this.IncNode = DOM.Node.FindWithClass(expand_node_0, "TimelineRowExpandButton");
-		this.DecNode = DOM.Node.FindWithClass(expand_node_1, "TimelineRowExpandButton");
-		this.CanvasNode = DOM.Node.FindWithClass(this.ContainerNode, "TimelineRowCanvas");
-		parent_node.appendChild(this.ContainerNode);
-
-		// All sample view windows visible by default
-		this.CheckboxNode.checked = true;
-		DOM.Event.AddHandler(this.CheckboxNode, "change", function(evt) { check_handler(name, evt); });
-
-		// Manually hook-up events to simulate div:active
-		// I can't get the equivalent CSS to work in Firefox, so...
-		DOM.Event.AddHandler(this.IncNode, "mousedown", ExpandButtonDown);
-		DOM.Event.AddHandler(this.IncNode, "mouseup", ExpandButtonUp);
-		DOM.Event.AddHandler(this.IncNode, "mouseleave", ExpandButtonUp);
-		DOM.Event.AddHandler(this.DecNode, "mousedown", ExpandButtonDown);
-		DOM.Event.AddHandler(this.DecNode, "mouseup", ExpandButtonUp);
-		DOM.Event.AddHandler(this.DecNode, "mouseleave", ExpandButtonUp);
-
-		// Pressing +/i increases/decreases depth
-		DOM.Event.AddHandler(this.IncNode, "click", Bind(IncDepth, this));
-		DOM.Event.AddHandler(this.DecNode, "click", Bind(DecDepth, this));
-
-		// Setup the canvas
-		this.Depth = 1;
-		this.Ctx = this.CanvasNode.getContext("2d");
-		this.SetSize(width);
-		this.Clear();
-
-		// Frame index to start at when looking for first visible sample
-		this.StartFrameIndex = 0;
-
-		this.FrameHistory = frame_history;
-		this.VisibleFrames = [ ];
-		this.VisibleTimeRange = null;
-
-		// Sample the mouse is currently hovering over
-		this.HoverSample = null;
-		this.HoverSampleDepth = 0;
-
-		// Currently selected sample
-		this.SelectedSample = null;
-		this.SelectedSampleDepth = 0;
-	}
-
-
-	TimelineRow.prototype.SetSize = function(width)
-	{
-		// Must ALWAYS set the width/height properties together. Setting one on its own has weird side-effects.
-		this.CanvasNode.width = width;
-		this.CanvasNode.height = CANVAS_BORDER + SAMPLE_BORDER + SAMPLE_Y_SPACING * this.Depth;
-		this.Draw(true);
-	}
-
-
-	TimelineRow.prototype.Clear = function()
-	{
-		// Fill box that shows the boundary between thread rows
-		this.Ctx.fillStyle = "#666"
-		var b = CANVAS_BORDER;
-		this.Ctx.fillRect(b, b, this.CanvasNode.width - b * 2, this.CanvasNode.height - b * 2);
-	}
-
-
-	TimelineRow.prototype.SetVisibleFrames = function(time_range)
-	{
-		// Clear previous visible list
-		this.VisibleFrames = [ ];
-		if (this.FrameHistory.length == 0)
-			return;
-
-		// Store a copy of the visible time range rather than referencing it
-		// This prevents external modifications to the time range from affecting rendering/selection
-		time_range = time_range.Clone();
-		this.VisibleTimeRange = time_range;
-
-		// The frame history can be reset outside this class
-		// This also catches the overflow to the end of the frame list below when a thread stops sending samples
-		var max_frame = Math.max(this.FrameHistory.length - 1, 0);
-		var start_frame_index = Math.min(this.StartFrameIndex, max_frame);
-
-		// First do a back-track in case the time range moves negatively
-		while (start_frame_index > 0)
-		{
-			var frame = this.FrameHistory[start_frame_index];
-			if (time_range.Start_us > frame.StartTime_us)
-				break;
-			start_frame_index--;
-		}
-
-		// Then search from this point for the first visible frame
-		while (start_frame_index < this.FrameHistory.length)
-		{
-			var frame = this.FrameHistory[start_frame_index];
-			if (frame.EndTime_us > time_range.Start_us)
-				break;
-			start_frame_index++;
-		}
-
-		// Gather all frames up to the end point
-		this.StartFrameIndex = start_frame_index;
-		for (var i = start_frame_index; i < this.FrameHistory.length; i++)
-		{
-			var frame = this.FrameHistory[i];
-			if (frame.StartTime_us > time_range.End_us)
-				break;
-			this.VisibleFrames.push(frame);
-		}
-	}
-
-
-	TimelineRow.prototype.Draw = function(draw_text)
-	{
-		this.Clear();
-
-		// Draw all root samples in the visible frame set
-		for (var i in this.VisibleFrames)
-		{
-			var frame = this.VisibleFrames[i];
-			DrawSamples(this, frame.Samples, 1, draw_text);
-		}
-	}
-
-
-	function DrawSamples(self, samples, depth, draw_text)
-	{
-		for (var i in samples)
-		{
-			var sample = samples[i];
-			DrawSample(self, sample, depth, draw_text);
-
-			if (depth < self.Depth && sample.children != null)
-				DrawSamples(self, sample.children, depth + 1, draw_text);
-		}
-	}
-
-
-	TimelineRow.prototype.UpdateHoverSample = function(mouse_state, x_offset)
-	{
-		var hover = GetSampleAtPosition(this, mouse_state, x_offset);
-		if (hover)
-			this.SetHoverSample(hover[1], hover[2]);
-		return hover;
-	}
-
-
-	TimelineRow.prototype.UpdateSelectedSample = function(mouse_state, x_offset)
-	{
-		var select = GetSampleAtPosition(this, mouse_state, x_offset);
-		if (select)
-			this.SetSelectedSample(select[1], select[2]);
-		return select;
-	}
-
-
-	TimelineRow.prototype.SetHoverSample = function(sample, sample_depth)
-	{
-		if (sample != this.HoverSample)
-		{
-			// Discard old highlight
-			// TODO: When zoomed right out, tiny samples are anti-aliased and this becomes inaccurate
-			var old_sample = this.HoverSample;
-			var old_sample_depth = this.HoverSampleDepth;
-			this.HoverSample = null;
-			this.HoverSampleDepth = 0;
-			DrawSample(this, old_sample, old_sample_depth, true);
-
-			// Add new highlight
-			this.HoverSample = sample;
-			this.HoverSampleDepth = sample_depth;
-			DrawSample(this, sample, sample_depth, true);
-		}
-	}
-
-
-	TimelineRow.prototype.SetSelectedSample = function(sample, sample_depth)
-	{
-		if (sample != this.SelectedSample)
-		{
-			// Discard old highlight
-			// TODO: When zoomed right out, tiny samples are anti-aliased and this becomes inaccurate
-			var old_sample = this.SelectedSample;
-			var old_sample_depth = this.SelectedSampleDepth;
-			this.SelectedSample = null;
-			this.SelectedSampleDepth = 0;
-			DrawSample(this, old_sample, old_sample_depth, true);
-
-			// Add new highlight
-			this.SelectedSample = sample;
-			this.SelectedSampleDepth = sample_depth;
-			DrawSample(this, sample, sample_depth, true);
-		}
-	}
-
-
-	function ExpandButtonDown(evt)
-	{
-		var node = DOM.Event.GetNode(evt);
-		DOM.Node.AddClass(node, "TimelineRowExpandButtonActive");
-	}
-
-
-	function ExpandButtonUp(evt)
-	{
-		var node = DOM.Event.GetNode(evt);
-		DOM.Node.RemoveClass(node, "TimelineRowExpandButtonActive");
-	}
-
-
-	function IncDepth(self)
-	{
-		self.Depth++;
-		self.SetSize(self.CanvasNode.width);
-	}
-
-
-	function DecDepth(self)
-	{
-		if (self.Depth > 1)
-		{
-			self.Depth--;
-			self.SetSize(self.CanvasNode.width);
-		}
-	}
-
-
-	function GetSampleAtPosition(self, mouse_state, x_offset)
-	{
-		// Mouse movement can occur before any data is sent to a timeline row
-		var time_range = self.VisibleTimeRange;
-		if (time_range == null)
-			return;
-
-		// Get the time the mouse is over
-		var x = mouse_state.Position[0] - x_offset;
-		var time_us = time_range.Start_us + x / time_range.usPerPixel;
-
-		var canvas_y_offset = DOM.Node.GetPosition(self.CanvasNode)[1];
-		var mouse_y_offset = mouse_state.Position[1] - canvas_y_offset;
-		mouse_y_offset = Math.min(Math.max(mouse_y_offset, 0), self.CanvasNode.height);
-		var depth = Math.floor(mouse_y_offset / SAMPLE_Y_SPACING) + 1;
-		
-		// Search for the first frame to intersect this time
-		for (var i in self.VisibleFrames)
-		{
-			var frame = self.VisibleFrames[i];
-			if (time_us >= frame.StartTime_us && time_us < frame.EndTime_us)
-			{
-				var found_sample = FindSample(self, frame.Samples, time_us, depth, 1);
-				if (found_sample != null)
-					return [ frame, found_sample[0], found_sample[1] ];
-			}
-		}
-
-		return null;
-	}
-
-
-	function FindSample(self, samples, time_us, target_depth, depth)
-	{
-		for (var i in samples)
-		{
-			var sample = samples[i];
-			if (depth == target_depth)
-			{
-				if (time_us >= sample.us_start && time_us < sample.us_start + sample.us_length)
-					return [ sample, depth ];
-			}
-
-			else if (depth < target_depth && sample.children != null)
-			{
-				var found_sample = FindSample(self, sample.children, time_us, target_depth, depth + 1);
-				if (found_sample != null)
-					return found_sample;
-			}
-		}
-
-		return null;
-	}
-
-
-	function DrawSample(self, sample, depth, draw_text)
-	{
-		if (sample == null)
-			return;
-
-		// Determine pixel range of the sample
-		var time_range = self.VisibleTimeRange;
-		var x0 = time_range.PixelOffset(sample.us_start);
-		var x1 = x0 + time_range.PixelSize(sample.us_length);
-
-		// Clip to padded timeline row
-		var min_x = 3;
-		var max_x = self.CanvasNode.width - 5;
-		x0 = Math.min(Math.max(x0, min_x), max_x);
-		x1 = Math.min(Math.max(x1, min_x), max_x);
-
-		var offset_x = x0;
-		var offset_y = SAMPLE_Y_OFFSET + (depth - 1) * SAMPLE_Y_SPACING;
-		var size_x = x1 - x0;
-		var size_y = SAMPLE_HEIGHT;
-
-		// Normal rendering
-		var ctx = self.Ctx;
-		ctx.fillStyle = sample.colour;
-		ctx.fillRect(offset_x, offset_y, size_x, size_y);
-
-		// Highlight rendering
-		var b = (sample == self.HoverSample) ? 255 : 0;
-		var r = (sample == self.SelectedSample) ? 255 : 0;
-		if (b + r > 0)
-		{
-			ctx.lineWidth = 1;
-			ctx.strokeStyle = "rgb(" + r + ", 0, " + b + ")";
-			ctx.strokeRect(offset_x + 0.5, offset_y + 0.5, size_x - 1, size_y - 1);
-		}
-
-	    // Draw sample names clipped to the bounds of the sample
-	    // Also reject tiny samples with no space to render text
-		if (draw_text && size_x > 8)
-		{
-			ctx.save();
-			ctx.beginPath();
-			ctx.rect(offset_x + 2.5, offset_y + 1.5, size_x - 5, size_y - 3);
-			ctx.clip();
-			ctx.font = "9px verdana";
-			ctx.fillStyle = "black";
-			ctx.fillText(sample.name, offset_x + 5.5, offset_y + 1.5 + 9);
-			ctx.restore();
-		}
-	}
-
-
-	return TimelineRow;
-})();

+ 0 - 270
3rdparty/remotery/vis/Code/TimelineWindow.js

@@ -1,270 +0,0 @@
-
-//
-// TODO: Use WebGL and instancing for quicker renders
-//
-
-
-TimelineWindow = (function()
-{
-	var BORDER = 10;
-
-	var ROW_START_SIZE = 210;
-
-	var ROW_END_SIZE = 20;  // make room for scrollbar
-
-	var box_template = "<div class='TimelineBox'></div>";
-
-
-	function TimelineWindow(wm, settings, server, check_handler)
-	{
-		this.Settings = settings;
-
-		// Ordered list of thread rows on the timeline
-		this.ThreadRows = [ ];
-
-		// Create window and containers
-		this.Window = wm.AddWindow("Timeline", 10, 20, 100, 100);
-		this.Window.ShowNoAnim();
-		this.TimelineContainer = this.Window.AddControlNew(new WM.Container(10, 10, 800, 160));
-		DOM.Node.AddClass(this.TimelineContainer.Node, "TimelineContainer");
-
-		var mouse_wheel_event = (/Firefox/i.test(navigator.userAgent)) ? "DOMMouseScroll" : "mousewheel";
-		DOM.Event.AddHandler(this.TimelineContainer.Node, mouse_wheel_event, Bind(OnMouseScroll, this));
-
-		// Setup timeline manipulation
-		this.MouseDown = false;
-		this.TimelineMoved = false;
-		this.OnHoverHandler = null;
-		this.OnSelectedHandler = null;
-		DOM.Event.AddHandler(this.TimelineContainer.Node, "mousedown", Bind(OnMouseDown, this));
-		DOM.Event.AddHandler(this.TimelineContainer.Node, "mouseup", Bind(OnMouseUp, this));
-		DOM.Event.AddHandler(this.TimelineContainer.Node, "mousemove", Bind(OnMouseMove, this));		
-
-		// Set time range AFTER the window has been created, as it uses the window to determine pixel coverage
-		this.TimeRange = new PixelTimeRange(0, 200 * 1000, RowWidth(this));
-
-		this.CheckHandler = check_handler;
-	}
-
-
-	TimelineWindow.prototype.SetOnHover = function(handler)
-	{
-		this.OnHoverHandler = handler;
-	}
-
-
-	TimelineWindow.prototype.SetOnSelected = function(handler)
-	{
-		this.OnSelectedHandler = handler;
-	}
-
-
-	TimelineWindow.prototype.WindowResized = function(width, height, top_window)
-	{
-		// Resize window
-		var top = top_window.Position[1] + top_window.Size[1] + 10;
-		this.Window.SetPosition(10, top);
-		this.Window.SetSize(width - 2 * 10, 200);
-
-		// Resize controls
-		var parent_size = this.Window.Size;
-		this.TimelineContainer.SetPosition(BORDER, 10);
-		this.TimelineContainer.SetSize(parent_size[0] - 2 * BORDER, 160);
-
-		// Resize rows
-		var row_width = RowWidth(this);
-		for (var i in this.ThreadRows)
-		{
-			var row = this.ThreadRows[i];
-			row.SetSize(row_width);
-		}
-
-		// Adjust time range to new width
-		this.TimeRange.SetPixelSpan(row_width);
-		this.DrawAllRows();
-	}
-
-
-	TimelineWindow.prototype.ResetTimeRange = function()
-	{
-		this.TimeRange.SetStart(0);
-	}
-
-
-	TimelineWindow.prototype.OnSamples = function(thread_name, frame_history)
-	{
-		// Shift the timeline to the last entry on this thread
-		// As multiple threads come through here with different end frames, only do this for the latest
-		var last_frame = frame_history[frame_history.length - 1];
-		if (last_frame.EndTime_us > this.TimeRange.End_us)
-			this.TimeRange.SetEnd(last_frame.EndTime_us);
-
-		// Search for the index of this thread
-		var thread_index = -1;
-		for (var i in this.ThreadRows)
-		{
-			if (this.ThreadRows[i].Name == thread_name)
-			{
-				thread_index = i;
-				break;
-			}
-		}
-
-		// If this thread has not been seen before, add a new row to the list and re-sort
-		if (thread_index == -1)
-		{
-			var row = new TimelineRow(thread_name, RowWidth(this), this.TimelineContainer.Node, frame_history, this.CheckHandler);
-			this.ThreadRows.push(row);
-			this.ThreadRows.sort(function(a, b) { return b.Name.localeCompare(a.Name); });
-		}
-	}
-
-
-	TimelineWindow.prototype.DrawAllRows = function()
-	{
-		var time_range = this.TimeRange;
-		var draw_text = this.Settings.IsPaused;
-		for (var i in this.ThreadRows)
-		{
-			var thread_row = this.ThreadRows[i];
-			thread_row.SetVisibleFrames(time_range);
-			thread_row.Draw(draw_text);
-		}
-	}
-
-
-	function RowXOffset(self)
-	{
-		// Add sizing of the label
-		// TODO: Use computed size
-		return DOM.Node.GetPosition(self.TimelineContainer.Node)[0] + ROW_START_SIZE;
-	}
-
-
-	function RowWidth(self)
-	{
-		// Subtract sizing of the label
-		// TODO: Use computed size
-		return self.TimelineContainer.Size[0] - (ROW_START_SIZE + ROW_END_SIZE);
-	}
-
-
-	function OnMouseScroll(self, evt)
-	{
-		var mouse_state = new Mouse.State(evt);
-		var scale = 1.11;
-			if (mouse_state.WheelDelta > 0)
-				scale = 1 / scale;
-
-		// What time is the mouse hovering over?
-		var x = mouse_state.Position[0] - RowXOffset(self);
-		var time_us = self.TimeRange.Start_us + x / self.TimeRange.usPerPixel;
-
-		// Calculate start time relative to the mouse hover position
-		var time_start_us = self.TimeRange.Start_us - time_us;
-
-		// Scale and offset back to the hover time
-		self.TimeRange.Set(time_start_us * scale + time_us, self.TimeRange.Span_us * scale);
-		self.DrawAllRows();
-
-		// Prevent vertical scrolling on mouse-wheel
-		DOM.Event.StopDefaultAction(evt);
-	}
-
-
-	function OnMouseDown(self, evt)
-	{
-		// Only manipulate the timelime when paused
-		if (!self.Settings.IsPaused)
-			return;
-
-		self.MouseDown = true;
-		self.TimelineMoved = false;
-		DOM.Event.StopDefaultAction(evt);
-	}
-
-
-	function OnMouseUp(self, evt)
-	{
-		// Only manipulate the timelime when paused
-		if (!self.Settings.IsPaused)
-			return;
-
-		var mouse_state = new Mouse.State(evt);
-
-		self.MouseDown = false;
-
-		if (!self.TimelineMoved)
-		{
-			// Search for the row being clicked and update its selection
-			var row_node = DOM.Event.GetNode(evt);
-			for (var i in self.ThreadRows)
-			{
-				var thread_row = self.ThreadRows[i];
-				if (thread_row.CanvasNode == row_node)
-				{
-					var select = thread_row.UpdateSelectedSample(mouse_state, RowXOffset(self));
-
-					// Call any selection handlers
-					if (self.OnSelectedHandler)
-						self.OnSelectedHandler(thread_row.Name, select);
-
-					break;
-				}
-			}
-		}
-	}
-
-
-	function OnMouseMove(self, evt)
-	{
-		// Only manipulate the timelime when paused
-		if (!self.Settings.IsPaused)
-			return;
-
-		var mouse_state = new Mouse.State(evt);
-
-		if (self.MouseDown)
-		{
-			// Get the time the mouse is over
-			var x = mouse_state.Position[0] - RowXOffset(self);
-			var time_us = self.TimeRange.Start_us + x / self.TimeRange.usPerPixel;
-
-			// Shift the visible time range with mouse movement
-			var time_offset_us = mouse_state.PositionDelta[0] / self.TimeRange.usPerPixel;
-			if (time_offset_us)
-			{
-				self.TimeRange.SetStart(self.TimeRange.Start_us - time_offset_us);
-				self.DrawAllRows();
-				self.TimelineMoved = true;
-			}
-		}
-
-		else
-		{
-			// Highlight any samples the mouse moves over
-			var row_node = DOM.Event.GetNode(evt);
-			for (var i in self.ThreadRows)
-			{
-				var thread_row = self.ThreadRows[i];
-				if (thread_row.CanvasNode == row_node)
-				{
-					var hover = thread_row.UpdateHoverSample(mouse_state, RowXOffset(self));
-
-					if (self.OnHoverHandler)
-						self.OnHoverHandler(thread_row.Name, hover);
-				}
-				else
-				{
-					thread_row.SetHoverSample(null, 0);
-					if (self.OnHoverHandler)
-						self.OnHoverHandler(thread_row.Name, null);
-				}
-			}
-		}
-	}
-
-
-	return TimelineWindow;
-})();
-

+ 0 - 59
3rdparty/remotery/vis/Code/TitleWindow.js

@@ -1,59 +0,0 @@
-
-TitleWindow = (function()
-{
-	function TitleWindow(wm, settings, server, connection_address)
-	{
-		this.Settings = settings;
-
-		this.Window = wm.AddWindow("&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Remotery", 10, 10, 100, 100);
-		this.Window.ShowNoAnim();
-
-		this.PingContainer = this.Window.AddControlNew(new WM.Container(4, -13, 10, 10));
-		DOM.Node.AddClass(this.PingContainer.Node, "PingContainer");
-
-		this.EditBox = this.Window.AddControlNew(new WM.EditBox(10, 5, 300, 18, "Connection Address", connection_address));
-
-		// Setup pause button
-		this.PauseButton = this.Window.AddControlNew(new WM.Button("Pause", 5, 5, { toggle: true }));
-		this.PauseButton.SetOnClick(Bind(OnPausePressed, this));
-
-		server.AddMessageHandler("PING", Bind(OnPing, this));
-	}
-
-
-	TitleWindow.prototype.SetConnectionAddressChanged = function(handler)
-	{
-		this.EditBox.SetChangeHandler(handler);
-	}
-
-
-	TitleWindow.prototype.WindowResized = function(width, height)
-	{
-		this.Window.SetSize(width - 2 * 10, 50);
-		this.PauseButton.SetPosition(width - 80, 5);
-	}
-
-
-	function OnPausePressed(self)
-	{
-		self.Settings.IsPaused = self.PauseButton.IsPressed();
-		if (self.Settings.IsPaused)
-			self.PauseButton.SetText("Paused");
-		else
-			self.PauseButton.SetText("Pause");
-	}
-
-
-	function OnPing(self, server)
-	{
-		// Set the ping container as active and take it off half a second later
-		DOM.Node.AddClass(self.PingContainer.Node, "PingContainerActive");
-		window.setTimeout(Bind(function(self)
-		{
-			DOM.Node.RemoveClass(self.PingContainer.Node, "PingContainerActive");
-		}, self), 500);
-	}
-
-
-	return TitleWindow;
-})();

+ 0 - 137
3rdparty/remotery/vis/Code/WebSocketConnection.js

@@ -1,137 +0,0 @@
-
-WebSocketConnection = (function()
-{
-	function WebSocketConnection()
-	{
-		this.MessageHandlers = { };
-		this.Socket = null;
-		this.Console = null;
-	}
-
-
-	WebSocketConnection.prototype.SetConsole = function(console)
-	{
-		this.Console = console;
-	}
-
-
-	WebSocketConnection.prototype.Connected = function()
-	{
-		// Will return true if the socket is also in the process of connecting
-		return this.Socket != null;
-	}
-
-
-	WebSocketConnection.prototype.AddConnectHandler = function(handler)
-	{
-		this.AddMessageHandler("__OnConnect__", handler);
-	}
-
-
-	WebSocketConnection.prototype.AddDisconnectHandler = function(handler)
-	{
-		this.AddMessageHandler("__OnDisconnect__", handler);
-	}
-
-
-	WebSocketConnection.prototype.AddMessageHandler = function(message_name, handler)
-	{
-		// Create the message handler array on-demand
-		if (!(message_name in this.MessageHandlers))
-			this.MessageHandlers[message_name] = [ ];
-		this.MessageHandlers[message_name].push(handler);
-	}
-
-
-	WebSocketConnection.prototype.Connect = function(address)
-	{
-		// Disconnect if already connected
-		if (this.Connected())
-			this.Disconnect();
-
-		Log(this, "Connecting to " + address);
-
-		this.Socket = new WebSocket(address);
-		this.Socket.binaryType = "arraybuffer";
-		this.Socket.onopen = Bind(OnOpen, this);
-		this.Socket.onmessage = Bind(OnMessage, this);
-		this.Socket.onclose = Bind(OnClose, this);
-		this.Socket.onerror = Bind(OnError, this);
-	}
-
-
-	WebSocketConnection.prototype.Disconnect = function()
-	{
-		Log(this, "Disconnecting");
-		if (this.Connected())
-			this.Socket.close();
-	}
-
-
-	WebSocketConnection.prototype.Send = function(msg)
-	{
-		if (this.Connected())
-			this.Socket.send(msg);
-	}
-
-
-	function Log(self, message)
-	{
-		self.Console.Log(message);
-	}
-
-
-	function CallMessageHandlers(self, message_name, data_view)
-	{
-		if (message_name in self.MessageHandlers)
-		{
-			var handlers = self.MessageHandlers[message_name];
-			for (var i in handlers)
-			    handlers[i](self, data_view);
-		}
-	}
-
-
-	function OnOpen(self, event)
-	{
-		Log(self, "Connected");
-		CallMessageHandlers(self, "__OnConnect__");
-	}
-
-
-	function OnClose(self, event)
-	{
-		// Clear all references
-		self.Socket.onopen = null;
-		self.Socket.onmessage = null;
-		self.Socket.onclose = null;
-		self.Socket.onerror = null;
-		self.Socket = null;
-
-		Log(self, "Disconnected");
-		CallMessageHandlers(self, "__OnDisconnect__");
-	}
-
-
-	function OnError(self, event)
-	{
-		Log(self, "Connection Error ");
-	}
-
-
-	function OnMessage(self, event)
-	{
-	    var data_view = new DataView(event.data);
-
-	    var id = String.fromCharCode(
-            data_view.getInt8(0),
-            data_view.getInt8(1),
-            data_view.getInt8(2),
-            data_view.getInt8(3));
-
-        CallMessageHandlers(self, id, data_view);
-	}
-
-
-	return WebSocketConnection;
-})();

+ 0 - 212
3rdparty/remotery/vis/Styles/Remotery.css

@@ -1,212 +0,0 @@
-
-body
-{
-    /* Take up the full page */
-    width: 100%;
-    height: 100%;
-    margin: 0px;
-
-    background-color: #AAA;
-}
-
-
-.NoSelect
-{
-    /* Disable text selection so that it doesn't interfere with faux-button clicking */
-    -webkit-touch-callout: none;
-    -webkit-user-select: none;
-    -khtml-user-select: none;
-    -moz-user-select: none;
-    -ms-user-select: none;
-    user-select: none;
-
-    /* Stops the text cursor over the label */
-    cursor:default;
-}
-
-
-/* Override default window styles to remove 3D effect */
-.Window
-{
-    background: #555;
-    box-shadow: none;
-    border-radius: 3px;
-}
-/*.WindowTitleBar
-{
-    border-bottom: none;
-    border-radius: 0px;
-}
-.WindowBody
-{
-    border-top: none;
-}*/
-
-
-/* Override default container style to remove 3D effect */
-.Container
-{
-    border: none;
-    box-shadow: none;
-}
-
-
-/* Override default edit box style to remove 3D effect */
-.EditBox
-{
-    border: none;
-    box-shadow: none;
-    width:200;
-}
-
-
-
-.ConsoleText
-{
-    overflow:auto;
-    color: #BBB;
-    font: 9px Verdana;
-    margin: 2px;
-    white-space: pre;
-}
-
-
-.PingContainer
-{
-    background-color: #F55;
-    border-radius: 2px;
-
-    /* Transition from green is gradual */
-    transition: background-color 0.25s ease-in;
-}
-
-
-.PingContainerActive
-{
-    background-color: #5F5;
-
-    /* Transition to green is instant */
-    transition: none;
-}
-
-
-.SampleNameCell
-{
-    width:300px;
-}
-
-
-.TimelineBox
-{
-    /* Following style generally copies GridRowCell.GridGroup from BrowserLib */
-
-    padding: 1px 1px 1px 2px;
-    margin: 1px;
-
-    border: 1px solid;
-    border-radius: 2px;
-    border-top-color:#555;
-    border-left-color:#555;
-    border-bottom-color:#111;
-    border-right-color:#111;
-
-    background: #222;
-
-    font: 9px Verdana;
-    color: #BBB;
-}
-.TimelineRow
-{
-    width: 100%;
-}
-.TimelineRowCheckbox
-{
-    width: 12px;
-    height: 12px;
-    margin: 0px;
-}
-.TimelineRowCheck
-{
-    /* Pull .TimelineRowExpand to the right of the checkbox */
-    float:left;
-
-    width: 14px;
-    height: 14px;
-}
-.TimelineRowExpand
-{
-    /* Pull .TimelineRowLabel to the right of +/- buttons */
-    float:left;
-
-    width: 14px;
-    height: 14px;
-}
-.TimelineRowExpandButton
-{
-    width: 11px;
-    height: 12px;
-
-    color: #333;
-
-    border: 1px solid;
-
-    border-top-color:#F4F4F4;
-    border-left-color:#F4F4F4;
-    border-bottom-color:#8E8F8F;
-    border-right-color:#8E8F8F;
-
-    /* Top-right to bottom-left grey background gradient */
-    background: #f6f6f6; /* Old browsers */
-    background: -moz-linear-gradient(-45deg,  #f6f6f6 0%, #abaeb2 100%); /* FF3.6+ */
-    background: -webkit-gradient(linear, left top, right bottom, color-stop(0%,#f6f6f6), color-stop(100%,#abaeb2)); /* Chrome,Safari4+ */
-    background: -webkit-linear-gradient(-45deg,  #f6f6f6 0%,#abaeb2 100%); /* Chrome10+,Safari5.1+ */
-    background: -o-linear-gradient(-45deg,  #f6f6f6 0%,#abaeb2 100%); /* Opera 11.10+ */
-    background: -ms-linear-gradient(-45deg,  #f6f6f6 0%,#abaeb2 100%); /* IE10+ */
-    background: linear-gradient(135deg,  #f6f6f6 0%,#abaeb2 100%); /* W3C */
-    filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#f6f6f6', endColorstr='#abaeb2',GradientType=1 ); /* IE6-9 fallback on horizontal gradient */
-
-    text-align: center;
-    vertical-align: center;
-}
-.TimelineRowExpandButton:hover
-{
-    border-top-color:#79C6F9;
-    border-left-color:#79C6F9;
-    border-bottom-color:#385D72;
-    border-right-color:#385D72;
-
-    /* Top-right to bottom-left blue background gradient, matching border */
-    background: #f3f3f3; /* Old browsers */
-    background: -moz-linear-gradient(-45deg,  #f3f3f3 0%, #79c6f9 100%); /* FF3.6+ */
-    background: -webkit-gradient(linear, left top, right bottom, color-stop(0%,#f3f3f3), color-stop(100%,#79c6f9)); /* Chrome,Safari4+ */
-    background: -webkit-linear-gradient(-45deg,  #f3f3f3 0%,#79c6f9 100%); /* Chrome10+,Safari5.1+ */
-    background: -o-linear-gradient(-45deg,  #f3f3f3 0%,#79c6f9 100%); /* Opera 11.10+ */
-    background: -ms-linear-gradient(-45deg,  #f3f3f3 0%,#79c6f9 100%); /* IE10+ */
-    background: linear-gradient(135deg,  #f3f3f3 0%,#79c6f9 100%); /* W3C */
-    filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#f3f3f3', endColorstr='#79c6f9',GradientType=1 ); /* IE6-9 fallback on horizontal gradient */
-}
-.TimelineRowExpandButtonActive
-{
-    /* Simple means of shifting text within a div to the bottom-right */
-    padding-left:1px;
-    padding-top:1px;
-    width:10px;
-    height:11px;
-}
-.TimelineRowLabel
-{
-    /* Pull .TimelineRowCanvas to the right of the label */
-    float:left;
-
-    width: 140px;
-    height: 14px;
-}
-.TimelineRowCanvas
-{
-}
-
-/* enable vertical scrollbar in TimelineContainer (useful for many threads) */
-.TimelineContainer
-{
-    overflow-y: scroll;
-}

+ 0 - 65
3rdparty/remotery/vis/extern/BrowserLib/Core/Code/Animation.js

@@ -1,65 +0,0 @@
-
-// 
-// Very basic linear value animation system, for now.
-//
-
-
-namespace("Anim");
-
-
-Anim.Animation = (function()
-{
-	var anim_hz = 60;
-
-	
-	function Animation(anim_func, start_value, end_value, time, end_callback)
-	{
-		// Setup initial parameters
-		this.StartValue = start_value;
-		this.EndValue = end_value;
-		this.ValueInc = (end_value - start_value) / (time * anim_hz);
-		this.Value = start_value;
-		this.Complete = false;
-		this.EndCallback = end_callback;
-
-		// Cache the update function to prevent recreating the closure
-		var self = this;
-		this.AnimFunc = anim_func;
-		this.AnimUpdate = function() { Update(self); }
-
-		// Call for the start value
-		this.AnimUpdate();
-	}
-
-
-	function Update(self)
-	{
-		// Queue up the next frame immediately
-		var id = window.setTimeout(self.AnimUpdate, 1000 / anim_hz);
-
-		// Linear step the value and check for completion
-		self.Value += self.ValueInc;
-		if (Math.abs(self.Value - self.EndValue) < 0.01)
-		{
-			self.Value = self.EndValue;
-			self.Complete = true;
-
-			if (self.EndCallback)
-				self.EndCallback();
-
-			window.clearTimeout(id);
-		}
-
-		// Pass to the animation function
-		self.AnimFunc(self.Value);
-	}
-
-
-	return Animation;
-})();
-
-
-Anim.Animate = function(anim_func, start_value, end_value, time, end_callback)
-{
-	return new Anim.Animation(anim_func, start_value, end_value, time, end_callback);
-}

+ 0 - 92
3rdparty/remotery/vis/extern/BrowserLib/Core/Code/Bind.js

@@ -1,92 +0,0 @@
-//
-// This will generate a closure for the given function and optionally bind an arbitrary number of
-// its initial arguments to specific values.
-//
-// Parameters:
-//
-//    0: Either the function scope or the function.
-//    1: If 0 is the function scope, this is the function.
-//       Otherwise it's the start of the optional bound argument list.
-//    2: Start of the optional bound argument list if 1 is the function.
-//
-// Examples:
-//
-//    function GlobalFunction(p0, p1, p2) { }
-//    function ThisFunction(p0, p1, p2) { }
-//
-//    var a = Bind("GlobalFunction");
-//    var b = Bind(this, "ThisFunction");
-//    var c = Bind("GlobalFunction", BoundParam0, BoundParam1);
-//    var d = Bind(this, "ThisFunction", BoundParam0, BoundParam1);
-//    var e = Bind(GlobalFunction);
-//    var f = Bind(this, ThisFunction);
-//    var g = Bind(GlobalFunction, BoundParam0, BoundParam1);
-//    var h = Bind(this, ThisFunction, BoundParam0, BoundParam1);
-//
-//    a(0, 1, 2);
-//    b(0, 1, 2);
-//    c(2);
-//    d(2);
-//    e(0, 1, 2);
-//    f(0, 1, 2);
-//    g(2);
-//    h(2);
-//
-function Bind()
-{
-	// No closure to define?
-	if (arguments.length == 0)
-		return null;
-
-	// Figure out which of the 4 call types is being used to bind
-	// Locate scope, function and bound parameter start index
-
-	if (typeof(arguments[0]) == "string")
-	{
-		var scope = window;
-		var func = window[arguments[0]];
-		var start = 1;
-	}
-
-	else if (typeof(arguments[0]) == "function")
-	{
-		var scope = window;
-		var func = arguments[0];
-		var start = 1;
-	}
-
-	else if (typeof(arguments[1]) == "string")
-	{
-		var scope = arguments[0];
-		var func = scope[arguments[1]];
-		var start = 2;
-	}
-
-	else if (typeof(arguments[1]) == "function")
-	{
-		var scope = arguments[0];
-		var func = arguments[1];
-		var start = 2;
-	}
-
-	else
-	{
-		// unknown
-		console.log("Bind() ERROR: Unknown bind parameter configuration");
-		return;
-	}
-
-	// Convert the arguments list to an array
-	var arg_array = Array.prototype.slice.call(arguments, start);
-	start = arg_array.length;
-
-	return function()
-	{
-		// Concatenate incoming arguments
-		for (var i = 0; i < arguments.length; i++)
-			arg_array[start + i] = arguments[i];
-
-		// Call the function in the given scope with the new arguments
-		return func.apply(scope, arg_array);
-	}
-}

File diff suppressed because it is too large
+ 0 - 204
3rdparty/remotery/vis/extern/BrowserLib/Core/Code/Convert.js


+ 0 - 20
3rdparty/remotery/vis/extern/BrowserLib/Core/Code/Core.js

@@ -1,20 +0,0 @@
-
-// TODO: requires function for checking existence of dependencies
-
-
-function namespace(name)
-{
-	// Ensure all nested namespaces are created only once
-	
-	var ns_list = name.split(".");
-	var parent_ns = window;
-
-	for (var i in ns_list)
-	{
-		var ns_name = ns_list[i];
-		if (!(ns_name in parent_ns))
-			parent_ns[ns_name] = { };
-
-		parent_ns = parent_ns[ns_name];
-	}
-}

+ 0 - 499
3rdparty/remotery/vis/extern/BrowserLib/Core/Code/DOM.js

@@ -1,499 +0,0 @@
-
-namespace("DOM.Node");
-namespace("DOM.Event");
-namespace("DOM.Applet");
-
-
-
-//
-// =====================================================================================================================
-// ----- DOCUMENT NODE/ELEMENT EXTENSIONS ------------------------------------------------------------------------------
-// =====================================================================================================================
-//
-
-
-
-DOM.Node.Get = function(id)
-{
-	return document.getElementById(id);
-}
-
-
-//
-// Set node position
-//
-DOM.Node.SetPosition = function(node, position)
-{
-	node.style.left = position[0];
-	node.style.top = position[1];
-}
-DOM.Node.SetX = function(node, x)
-{
-	node.style.left = x;
-}
-DOM.Node.SetY = function(node, y)
-{
-	node.style.top = y;
-}
-
-
-//
-// Get the absolute position of a HTML element on the page
-//
-DOM.Node.GetPosition = function(element, account_for_scroll)
-{
-	// Recurse up through parents, summing offsets from their parent
-	var x = 0, y = 0;
-	for (var node = element; node != null; node = node.offsetParent)
-	{
-		x += node.offsetLeft;
-		y += node.offsetTop;
-	}
-
-	if (account_for_scroll)
-	{
-		// Walk up the hierarchy subtracting away any scrolling
-		for (var node = element; node != document.body; node = node.parentNode)
-		{
-			x -= node.scrollLeft;
-			y -= node.scrollTop;
-		}
-	}
-
-	return [x, y];
-}
-
-
-//
-// Set node size
-//
-DOM.Node.SetSize = function(node, size)
-{
-	node.style.width = size[0];
-	node.style.height = size[1];
-}
-DOM.Node.SetWidth = function(node, width)
-{
-	node.style.width = width;
-}
-DOM.Node.SetHeight = function(node, height)
-{
-	node.style.height = height;
-}
-
-
-//
-// Get node OFFSET size:
-//    clientX includes padding
-//    offsetX includes padding and borders
-//    scrollX includes padding, borders and size of contained node
-//
-DOM.Node.GetSize = function(node)
-{
-	return [ node.offsetWidth, node.offsetHeight ];
-}
-DOM.Node.GetWidth = function(node)
-{
-	return node.offsetWidth;
-}
-DOM.Node.GetHeight = function(node)
-{
-	return node.offsetHeight;
-}
-
-
-//
-// Set node opacity
-//
-DOM.Node.SetOpacity = function(node, value)
-{
-	node.style.opacity = value;
-}
-
-
-DOM.Node.SetColour = function(node, colour)
-{
-	node.style.color = colour;
-}
-
-
-//
-// Hide a node by completely disabling its rendering (it no longer contributes to document layout)
-//
-DOM.Node.Hide = function(node)
-{
-	node.style.display = "none";
-}
-
-
-//
-// Show a node by restoring its influcen in document layout
-//
-DOM.Node.Show = function(node)
-{
-	node.style.display = "block";
-}
-
-
-//
-// Add a CSS class to a HTML element, specified last
-//
-DOM.Node.AddClass = function(node, class_name)
-{
-	// Ensure the class hasn't already been added
-	DOM.Node.RemoveClass(node, class_name);
-	node.className += " " + class_name;
-}
-
-
-//
-// Remove a CSS class from a HTML element
-//
-DOM.Node.RemoveClass = function(node, class_name)
-{
-	// Remove all variations of where the class name can be in the string list
-	var regexp = new RegExp("\\b" + class_name + "\\b");
-	node.className = node.className.replace(regexp, "");
-}
-
-
-
-//
-// Check to see if a HTML element contains a class
-//
-DOM.Node.HasClass = function(node, class_name)
-{
-	var regexp = new RegExp("\\b" + class_name + "\\b");
-	return regexp.test(node.className);
-}
-
-
-//
-// Recursively search for a node with the given class name
-//
-DOM.Node.FindWithClass = function(parent_node, class_name, index)
-{
-	// Search the children looking for a node with the given class name
-	for (var i in parent_node.childNodes)
-	{
-		var node = parent_node.childNodes[i];
-		if (DOM.Node.HasClass(node, class_name))
-		{
-			if (index === undefined || index-- == 0)
-				return node;
-		}
-
-		// Recurse into children
-		node = DOM.Node.FindWithClass(node, class_name);
-		if (node != null)
-			return node;
-	}
-
-	return null;
-}
-
-
-//
-// Check to see if one node logically contains another
-//
-DOM.Node.Contains = function(node, container_node)
-{
-	while (node != null && node != container_node)
-		node = node.parentNode;
-	return node != null;
-}
-
-
-//
-// Create the HTML nodes specified in the text passed in
-// Assumes there is only one root node in the text
-//
-DOM.Node.CreateHTML = function(html)
-{
-	var div = document.createElement("div");
-	div.innerHTML = html;
-
-	// First child may be a text node, followed by the created HTML
-	var child = div.firstChild;
-	if (child != null && child.nodeType == 3)
-		child = child.nextSibling;
-	return child;
-}
-
-
-//
-// Make a copy of a HTML element, making it visible and clearing its ID to ensure it's not a duplicate
-//
-DOM.Node.Clone = function(name)
-{
-	// Get the template element and clone it, making sure it's renderable
-	var node = DOM.Node.Get(name);
-	node = node.cloneNode(true);
-	node.id = null;
-	node.style.display = "block";
-	return node;
-}
-
-
-//
-// Append an arbitrary block of HTML to an existing node
-//
-DOM.Node.AppendHTML = function(node, html)
-{
-	var child = DOM.Node.CreateHTML(html);
-	node.appendChild(child);
-	return child;
-}
-
-
-//
-// Append a div that clears the float style
-//
-DOM.Node.AppendClearFloat = function(node)
-{
-	var div = document.createElement("div");
-	div.style.clear = "both";
-	node.appendChild(div);
-}
-
-
-//
-// Check to see that the object passed in is an instance of a DOM node
-//
-DOM.Node.IsNode = function(object)
-{
-	return object instanceof Element;
-}
-
-
-//
-// Create an "iframe shim" so that elements within it render over a Java Applet
-// http://web.archive.org/web/20110707212850/http://www.oratransplant.nl/2007/10/26/using-iframe-shim-to-partly-cover-a-java-applet/
-//
-DOM.Node.CreateShim = function(parent)
-{
-	var shimmer = document.createElement("iframe");
-
-	// Position the shimmer so that it's the same location/size as its parent
-	shimmer.style.position = "fixed";
-	shimmer.style.left = parent.style.left;
-	shimmer.style.top = parent.style.top;
-	shimmer.style.width = parent.offsetWidth;
-	shimmer.style.height = parent.offsetHeight;
-
-	// We want the shimmer to be one level below its contents
-	shimmer.style.zIndex = parent.style.zIndex - 1;
-
-	// Ensure its empty
-	shimmer.setAttribute("frameborder", "0");
-	shimmer.setAttribute("src", "");
-
-	// Add to the document and the parent
-	document.body.appendChild(shimmer);
-	parent.Shimmer = shimmer;
-	return shimmer;
-}
-
-
-
-//
-// =====================================================================================================================
-// ----- EVENT HANDLING EXTENSIONS -------------------------------------------------------------------------------------
-// =====================================================================================================================
-//
-
-
-
-//
-// Retrieves the event from the first parameter passed into an HTML event
-//
-DOM.Event.Get = function(evt)
-{
-	// Internet explorer doesn't pass the event
-	return window.event || evt;
-}
-
-
-//
-// Retrieves the element that triggered an event from the event object
-//
-DOM.Event.GetNode = function(evt)
-{
-	evt = DOM.Event.Get(evt);
-
-	// Get the target element
-	var element;
-	if (evt.target)
-		element = evt.target;
-	else if (e.srcElement)
-		element = evt.srcElement;
-
-	// Default Safari bug
-	if (element.nodeType == 3)
-		element = element.parentNode;
-
-	return element;
-}
-
-
-//
-// Stop default action for an event
-//
-DOM.Event.StopDefaultAction = function(evt)
-{
-	if (evt && evt.preventDefault)
-		evt.preventDefault();
-	else if (window.event && window.event.returnValue)
-		window.event.returnValue = false;
-}
-
-
-//
-// Stops events bubbling up to parent event handlers
-//
-DOM.Event.StopPropagation = function(evt)
-{
-	evt = DOM.Event.Get(evt);
-	if (evt)
-	{
-		evt.cancelBubble = true;
-		if (evt.stopPropagation)
-			evt.stopPropagation();
-	}
-}
-
-
-//
-// Stop both event default action and propagation
-//
-DOM.Event.StopAll = function(evt)
-{
-	DOM.Event.StopDefaultAction(evt);
-	DOM.Event.StopPropagation(evt);
-}
-
-
-//
-// Adds an event handler to an event
-//
-DOM.Event.AddHandler = function(obj, evt, func)
-{
-	if (obj)
-	{
-		if (obj.addEventListener)
-			obj.addEventListener(evt, func, false);
-		else if (obj.attachEvent)
-			obj.attachEvent("on" + evt, func);
-	}
-}
-
-
-//
-// Removes an event handler from an event
-//
-DOM.Event.RemoveHandler = function(obj, evt, func)
-{
-	if (obj)
-	{
-		if (obj.removeEventListener)
-			obj.removeEventListener(evt, func, false);
-		else if (obj.detachEvent)
-			obj.detachEvent("on" + evt, func);
-	}
-}
-
-
-//
-// Get the position of the mouse cursor, page relative
-//
-DOM.Event.GetMousePosition = function(evt)
-{
-	evt = DOM.Event.Get(evt);
-
-	var px = 0;
-	var py = 0;
-	if (evt.pageX || evt.pageY)
-	{
-		px = evt.pageX;
-		py = evt.pageY;
-	}
-	else if (evt.clientX || evt.clientY)
-	{
-		px = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
-		py = e.clientY + document.body.scrollTop + document.documentElement.scrollTop;
-	}
-
-	return [px, py];
-}
-
-
-
-//
-// =====================================================================================================================
-// ----- JAVA APPLET EXTENSIONS ----------------------------------------------------------------------------------------
-// =====================================================================================================================
-//
-
-
-
-//
-// Create an applet element for loading a Java applet, attaching it to the specified node
-//
-DOM.Applet.Load = function(dest_id, id, code, archive)
-{
-	// Lookup the applet destination
-	var dest = DOM.Node.Get(dest_id);
-	if (!dest)
-		return;
-
-	// Construct the applet element and add it to the destination
-	Debug.Log("Injecting applet DOM code");
-	var applet = "<applet id='" + id + "' code='" + code + "' archive='" + archive + "'";
-	applet += " width='" + dest.offsetWidth + "' height='" + dest.offsetHeight + "'>";
-	applet += "</applet>";
-	dest.innerHTML = applet;
-}
-
-
-//
-// Moves and resizes a named applet so that it fits in the destination div element.
-// The applet must be contained by a div element itself. This container div is moved along
-// with the applet.
-//
-DOM.Applet.Move = function(dest_div, applet, z_index, hide)
-{
-	if (!applet || !dest_div)
-		return;
-
-	// Before modifying any location information, hide the applet so that it doesn't render over
-	// any newly visible elements that appear while the location information is being modified.
-	if (hide)
-		applet.style.visibility = "hidden";
-
-	// Get its view rect
-	var pos = DOM.Node.GetPosition(dest_div);
-	var w = dest_div.offsetWidth;
-	var h = dest_div.offsetHeight;
-
-	// It needs to be embedded in a <div> for correct scale/position adjustment
-	var container = applet.parentNode;
-	if (!container || container.localName != "div")
-	{
-		Debug.Log("ERROR: Couldn't find source applet's div container");
-		return;
-	}
-
-	// Reposition and resize the containing div element
-	container.style.left = pos[0];
-	container.style.top = pos[1];
-	container.style.width = w;
-	container.style.height = h;
-	container.style.zIndex = z_index;
-
-	// Resize the applet itself
-	applet.style.width = w;
-	applet.style.height = h;
-
-	// Everything modified, safe to show
-	applet.style.visibility = "visible";
-}

+ 0 - 149
3rdparty/remotery/vis/extern/BrowserLib/Core/Code/Keyboard.js

@@ -1,149 +0,0 @@
-
-namespace("Keyboard")
-
-
-// =====================================================================================================================
-// Key codes copied from closure-library
-// https://code.google.com/p/closure-library/source/browse/closure/goog/events/keycodes.js
-// ---------------------------------------------------------------------------------------------------------------------
-// Copyright 2006 The Closure Library Authors. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS-IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-Keyboard.Codes = {
-	WIN_KEY_FF_LINUX	: 0,
-	MAC_ENTER			: 3,
-	BACKSPACE			: 8,
-	TAB					: 9,
-	NUM_CENTER			: 12,	// NUMLOCK on FF/Safari Mac
-	ENTER				: 13,
-	SHIFT				: 16,
-	CTRL				: 17,
-	ALT					: 18,
-	PAUSE				: 19,
-	CAPS_LOCK			: 20,
-	ESC					: 27,
-	SPACE				: 32,
-	PAGE_UP				: 33,	// also NUM_NORTH_EAST
-	PAGE_DOWN			: 34,	// also NUM_SOUTH_EAST
-	END					: 35,	// also NUM_SOUTH_WEST
-	HOME				: 36,	// also NUM_NORTH_WEST
-	LEFT				: 37,	// also NUM_WEST
-	UP					: 38,	// also NUM_NORTH
-	RIGHT				: 39,	// also NUM_EAST
-	DOWN				: 40,	// also NUM_SOUTH
-	PRINT_SCREEN		: 44,
-	INSERT				: 45,	// also NUM_INSERT
-	DELETE				: 46,	// also NUM_DELETE
-	ZERO				: 48,
-	ONE					: 49,
-	TWO					: 50,
-	THREE				: 51,
-	FOUR				: 52,
-	FIVE				: 53,
-	SIX					: 54,
-	SEVEN				: 55,
-	EIGHT				: 56,
-	NINE				: 57,
-	FF_SEMICOLON		: 59,	// Firefox (Gecko) fires this for semicolon instead of 186
-	FF_EQUALS			: 61,	// Firefox (Gecko) fires this for equals instead of 187
-	FF_DASH				: 173,	// Firefox (Gecko) fires this for dash instead of 189
-	QUESTION_MARK		: 63,	// needs localization
-	A					: 65,
-	B					: 66,
-	C					: 67,
-	D					: 68,
-	E					: 69,
-	F					: 70,
-	G					: 71,
-	H					: 72,
-	I					: 73,
-	J					: 74,
-	K					: 75,
-	L					: 76,
-	M					: 77,
-	N					: 78,
-	O					: 79,
-	P					: 80,
-	Q					: 81,
-	R					: 82,
-	S					: 83,
-	T					: 84,
-	U					: 85,
-	V					: 86,
-	W					: 87,
-	X					: 88,
-	Y					: 89,
-	Z					: 90,
-	META				: 91,	// WIN_KEY_LEFT
-	WIN_KEY_RIGHT		: 92,
-	CONTEXT_MENU		: 93,
-	NUM_ZERO			: 96,
-	NUM_ONE				: 97,
-	NUM_TWO				: 98,
-	NUM_THREE			: 99,
-	NUM_FOUR			: 100,
-	NUM_FIVE			: 101,
-	NUM_SIX				: 102,
-	NUM_SEVEN			: 103,
-	NUM_EIGHT			: 104,
-	NUM_NINE			: 105,
-	NUM_MULTIPLY		: 106,
-	NUM_PLUS			: 107,
-	NUM_MINUS			: 109,
-	NUM_PERIOD			: 110,
-	NUM_DIVISION		: 111,
-	F1					: 112,
-	F2					: 113,
-	F3					: 114,
-	F4					: 115,
-	F5					: 116,
-	F6					: 117,
-	F7					: 118,
-	F8					: 119,
-	F9					: 120,
-	F10					: 121,
-	F11					: 122,
-	F12					: 123,
-	NUMLOCK				: 144,
-	SCROLL_LOCK			: 145,
-
-	// OS-specific media keys like volume controls and browser controls.
-	FIRST_MEDIA_KEY		: 166,
-	LAST_MEDIA_KEY		: 183,
-
-	SEMICOLON			: 186,	// needs localization
-	DASH				: 189,	// needs localization
-	EQUALS				: 187,	// needs localization
-	COMMA				: 188,	// needs localization
-	PERIOD				: 190,	// needs localization
-	SLASH				: 191,	// needs localization
-	APOSTROPHE			: 192,	// needs localization
-	TILDE				: 192,	// needs localization
-	SINGLE_QUOTE		: 222,	// needs localization
-	OPEN_SQUARE_BRACKET	: 219,	// needs localization
-	BACKSLASH			: 220,	// needs localization
-	CLOSE_SQUARE_BRACKET: 221,	// needs localization
-	WIN_KEY				: 224,
-	MAC_FF_META			: 224,	// Firefox (Gecko) fires this for the meta key instead of 91
-	MAC_WK_CMD_LEFT		: 91,	// WebKit Left Command key fired, same as META
-	MAC_WK_CMD_RIGHT	: 93,	// WebKit Right Command key fired, different from META
-	WIN_IME				: 229,
-
-	// We've seen users whose machines fire this keycode at regular one
-	// second intervals. The common thread among these users is that
-	// they're all using Dell Inspiron laptops, so we suspect that this
-	// indicates a hardware/bios problem.
-	// http://en.community.dell.com/support-forums/laptop/f/3518/p/19285957/19523128.aspx
-	PHANTOM				: 255
-};
-// =====================================================================================================================

+ 0 - 26
3rdparty/remotery/vis/extern/BrowserLib/Core/Code/LocalStore.js

@@ -1,26 +0,0 @@
-
-namespace("LocalStore");
-
-
-LocalStore.Set = function(class_name, class_id, variable_id, data)
-{
-	if (typeof(Storage) != "undefined")
-	{
-		var name = class_name + "_" + class_id + "_" + variable_id;
-		localStorage[name] = JSON.stringify(data);
-	}
-}
-
-
-LocalStore.Get = function(class_name, class_id, variable_id, default_data)
-{
-	if (typeof(Storage) != "undefined")
-	{
-		var name = class_name + "_" + class_id + "_" + variable_id;
-		var data = localStorage[name]
-		if (data)
-			return JSON.parse(data);
-	}
-
-	return default_data;
-}

+ 0 - 83
3rdparty/remotery/vis/extern/BrowserLib/Core/Code/Mouse.js

@@ -1,83 +0,0 @@
-
-namespace("Mouse");
-
-
-Mouse.State =(function()
-{
-	function State(event)
-	{
-		// Get button press states
-		if (typeof event.buttons != "undefined")
-		{
-			// Firefox
-			this.Left = (event.buttons & 1) != 0;
-			this.Right = (event.buttons & 2) != 0;
-			this.Middle = (event.buttons & 4) != 0;
-		}
-		else
-		{
-			// Chrome
-			this.Left = (event.button == 0);
-			this.Middle = (event.button == 1);
-			this.Right = (event.button == 2);
-		}
-
-		// Get page-relative mouse position
-		this.Position = DOM.Event.GetMousePosition(event);
-
-		// Get wheel delta
-		var delta = 0;
-		if (event.wheelDelta)
-			delta = event.wheelDelta / 120;		// IE/Opera
-		else if (event.detail)
-			delta = -event.detail / 3;			// Mozilla
-		this.WheelDelta = delta;
-
-		// Get the mouse position delta
-		// Requires Pointer Lock API support
-		this.PositionDelta = [
-			event.movementX || event.mozMovementX || event.webkitMovementX || 0,
-			event.movementY || event.mozMovementY || event.webkitMovementY || 0
-		];
-	}
-
-	return State;
-})();
-
-
-//
-// Basic Pointer Lock API support
-// https://developer.mozilla.org/en-US/docs/WebAPI/Pointer_Lock
-// http://www.chromium.org/developers/design-documents/mouse-lock
-//
-// Note that API has not been standardised yet so browsers can implement functions with prefixes
-//
-
-
-Mouse.PointerLockSupported = function()
-{
-	return 'pointerLockElement' in document || 'mozPointerLockElement' in document || 'webkitPointerLockElement' in document;
-}
-
-
-Mouse.RequestPointerLock = function(element)
-{
-	element.requestPointerLock = element.requestPointerLock || element.mozRequestPointerLock || element.webkitRequestPointerLock;
-	if (element.requestPointerLock)
-		element.requestPointerLock();
-}
-
-
-Mouse.ExitPointerLock = function()
-{
-	document.exitPointerLock = document.exitPointerLock || document.mozExitPointerLock || document.webkitExitPointerLock;
-	if (document.exitPointerLock)
-		document.exitPointerLock();
-}
-
-
-// Can use this element to detect whether pointer lock is enabled (returns non-null)
-Mouse.PointerLockElement = function()
-{
-	return document.pointerLockElement || document.mozPointerLockElement || document.webkitPointerLockElement;
-}

+ 0 - 68
3rdparty/remotery/vis/extern/BrowserLib/Core/Code/MurmurHash3.js

@@ -1,68 +0,0 @@
-
-namespace("Hash");
-
-/**
- * JS Implementation of MurmurHash3 (r136) (as of May 20, 2011)
- * 
- * @author <a href="mailto:[email protected]">Gary Court</a>
- * @see http://github.com/garycourt/murmurhash-js
- * @author <a href="mailto:[email protected]">Austin Appleby</a>
- * @see http://sites.google.com/site/murmurhash/
- * 
- * @param {string} key ASCII only
- * @param {number} seed Positive integer only
- * @return {number} 32-bit positive integer hash 
- */
-
-Hash.Murmur3 = function(key, seed)
-{
-	var remainder, bytes, h1, h1b, c1, c1b, c2, c2b, k1, i;
-	
-	remainder = key.length & 3; // key.length % 4
-	bytes = key.length - remainder;
-	h1 = seed;
-	c1 = 0xcc9e2d51;
-	c2 = 0x1b873593;
-	i = 0;
-	
-	while (i < bytes) {
-	  	k1 = 
-	  	  ((key.charCodeAt(i) & 0xff)) |
-	  	  ((key.charCodeAt(++i) & 0xff) << 8) |
-	  	  ((key.charCodeAt(++i) & 0xff) << 16) |
-	  	  ((key.charCodeAt(++i) & 0xff) << 24);
-		++i;
-		
-		k1 = ((((k1 & 0xffff) * c1) + ((((k1 >>> 16) * c1) & 0xffff) << 16))) & 0xffffffff;
-		k1 = (k1 << 15) | (k1 >>> 17);
-		k1 = ((((k1 & 0xffff) * c2) + ((((k1 >>> 16) * c2) & 0xffff) << 16))) & 0xffffffff;
-
-		h1 ^= k1;
-        h1 = (h1 << 13) | (h1 >>> 19);
-		h1b = ((((h1 & 0xffff) * 5) + ((((h1 >>> 16) * 5) & 0xffff) << 16))) & 0xffffffff;
-		h1 = (((h1b & 0xffff) + 0x6b64) + ((((h1b >>> 16) + 0xe654) & 0xffff) << 16));
-	}
-	
-	k1 = 0;
-	
-	switch (remainder) {
-		case 3: k1 ^= (key.charCodeAt(i + 2) & 0xff) << 16;
-		case 2: k1 ^= (key.charCodeAt(i + 1) & 0xff) << 8;
-		case 1: k1 ^= (key.charCodeAt(i) & 0xff);
-		
-		k1 = (((k1 & 0xffff) * c1) + ((((k1 >>> 16) * c1) & 0xffff) << 16)) & 0xffffffff;
-		k1 = (k1 << 15) | (k1 >>> 17);
-		k1 = (((k1 & 0xffff) * c2) + ((((k1 >>> 16) * c2) & 0xffff) << 16)) & 0xffffffff;
-		h1 ^= k1;
-	}
-	
-	h1 ^= key.length;
-
-	h1 ^= h1 >>> 16;
-	h1 = (((h1 & 0xffff) * 0x85ebca6b) + ((((h1 >>> 16) * 0x85ebca6b) & 0xffff) << 16)) & 0xffffffff;
-	h1 ^= h1 >>> 13;
-	h1 = ((((h1 & 0xffff) * 0xc2b2ae35) + ((((h1 >>> 16) * 0xc2b2ae35) & 0xffff) << 16))) & 0xffffffff;
-	h1 ^= h1 >>> 16;
-
-	return h1 >>> 0;
-}

+ 0 - 131
3rdparty/remotery/vis/extern/BrowserLib/WindowManager/Code/Button.js

@@ -1,131 +0,0 @@
-
-namespace("WM");
-
-
-WM.Button = (function()
-{
-	var template_html = "<div class='Button notextsel'></div>";
-
-
-	function Button(text, x, y, opts)
-	{
-		this.OnClick = null;
-		this.Toggle = opts && opts.toggle;
-
-		this.Node = DOM.Node.CreateHTML(template_html);
-
-		// Set node dimensions
-		this.SetPosition(x, y);
-		if (opts && opts.w && opts.h)
-			this.SetSize(opts.w, opts.h);
-
-		// Override the default class name
-		if (opts && opts.class)
-			this.Node.className = opts.class;
-
-		this.SetText(text);
-
-		// Create the mouse press event handlers
-		DOM.Event.AddHandler(this.Node, "mousedown", Bind(OnMouseDown, this));
-		this.OnMouseOutDelegate = Bind(OnMouseUp, this, false);
-		this.OnMouseUpDelegate = Bind(OnMouseUp, this, true);
-	}
-
-
-	Button.prototype.SetPosition = function(x, y)
-	{
-		this.Position = [ x, y ];
-		DOM.Node.SetPosition(this.Node, this.Position);
-	}
-
-
-	Button.prototype.SetSize = function(w, h)
-	{
-		this.Size = [ w, h ];
-		DOM.Node.SetSize(this.Node, this.Size);
-	}
-
-
-	Button.prototype.SetText = function(text)
-	{
-		this.Node.innerHTML = text;
-	}
-
-
-	Button.prototype.SetOnClick = function(on_click)
-	{
-		this.OnClick = on_click;
-	}
-
-
-	Button.prototype.SetState = function(pressed)
-	{
-		if (pressed)
-			DOM.Node.AddClass(this.Node, "ButtonHeld");
-		else
-			DOM.Node.RemoveClass(this.Node, "ButtonHeld");
-	}
-
-
-	Button.prototype.ToggleState = function()
-	{
-		if (DOM.Node.HasClass(this.Node, "ButtonHeld"))
-			this.SetState(false);
-		else
-			this.SetState(true);
-	}
-
-
-	Button.prototype.IsPressed = function()
-	{
-		return DOM.Node.HasClass(this.Node, "ButtonHeld");
-	}
-
-
-	function OnMouseDown(self, evt)
-	{
-		// Decide how to set the button state
-		if (self.Toggle)
-			self.ToggleState();
-		else
-			self.SetState(true);
-
-		// Activate release handlers
-		DOM.Event.AddHandler(self.Node, "mouseout", self.OnMouseOutDelegate);
-		DOM.Event.AddHandler(self.Node, "mouseup", self.OnMouseUpDelegate);
-
-		DOM.Event.StopAll(evt);
-	}
-
-
-	function OnMouseUp(self, confirm, evt)
-	{
-		if (confirm)
-		{
-			// Only release for non-toggles
-			if (!self.Toggle)
-				self.SetState(false);
-		}
-		else
-		{
-			// Decide how to set the button state
-			if (self.Toggle)
-				self.ToggleState();
-			else
-				self.SetState(false);
-		}
-
-		// Remove release handlers
-		DOM.Event.RemoveHandler(self.Node, "mouseout", self.OnMouseOutDelegate);
-		DOM.Event.RemoveHandler(self.Node, "mouseup", self.OnMouseUpDelegate);
-
-		// Call the click handler if this is a button press
-		if (confirm && self.OnClick)
-			self.OnClick(self);
-
-		DOM.Event.StopAll(evt);
-	}
-
-
-	return Button;
-})();

+ 0 - 237
3rdparty/remotery/vis/extern/BrowserLib/WindowManager/Code/ComboBox.js

@@ -1,237 +0,0 @@
-
-namespace("WM");
-
-
-WM.ComboBoxPopup = (function()
-{
-	var body_template_html = "<div class='ComboBoxPopup'></div>";
-
-	var item_template_html = "																	\
-		<div class='ComboBoxPopupItem notextsel'>												\
-			<div class='ComboBoxPopupItemText'></div>											\
-			<div class='ComboBoxPopupItemIcon'><img src='BrowserLibImages/tick.gif'></div>		\
-			<div style='clear:both'></div>														\
-		</div>";
-
-
-	function ComboBoxPopup(combo_box)
-	{
-		this.ComboBox = combo_box;
-		this.ParentNode = combo_box.Node;
-		this.ValueNodes = [ ];
-
-		// Create the template node
-		this.Node = DOM.Node.CreateHTML(body_template_html);
-
-		DOM.Event.AddHandler(this.Node, "mousedown", Bind(SelectItem, this));
-		this.CancelDelegate = Bind(this, "Cancel");
-	}
-
-
-	ComboBoxPopup.prototype.SetValues = function(values)
-	{
-		// Clear existing values
-		this.Node.innerHTML = "";
-
-		// Generate HTML nodes for each value
-		this.ValueNodes = [ ];
-		for (var i in values)
-		{
-			var item_node = DOM.Node.CreateHTML(item_template_html);
-			var text_node = DOM.Node.FindWithClass(item_node, "ComboBoxPopupItemText");
-
-			item_node.Value = values[i];
-			text_node.innerHTML = values[i];
-
-			this.Node.appendChild(item_node);
-			this.ValueNodes.push(item_node);
-		}
-	}
-
-
-	ComboBoxPopup.prototype.Show = function(selection_index)
-	{
-		// Initially match the position of the parent node
-		var pos = DOM.Node.GetPosition(this.ParentNode);
-		DOM.Node.SetPosition(this.Node, pos);
-
-		// Take the width/z-index from the parent node
-		this.Node.style.width = this.ParentNode.offsetWidth;
-		this.Node.style.zIndex = this.ParentNode.style.zIndex + 1;
-
-		// Setup event handlers
-		DOM.Event.AddHandler(document.body, "mousedown", this.CancelDelegate);
-
-		// Show the popup so that the HTML layout engine kicks in before
-		// the layout info is used below
-		this.ParentNode.appendChild(this.Node);
-
-		// Show/hide the tick image based on which node is selected
-		for (var i in this.ValueNodes)
-		{
-			var node = this.ValueNodes[i];
-			var icon_node = DOM.Node.FindWithClass(node, "ComboBoxPopupItemIcon");
-
-			if (i == selection_index)
-			{
-				icon_node.style.display = "block";
-
-				// Also, shift the popup up so that the mouse is over the selected item and is highlighted
-				var item_pos = DOM.Node.GetPosition(this.ValueNodes[selection_index]);
-				var diff_pos = [ item_pos[0] - pos[0], item_pos[1] - pos[1] ];
-				pos = [ pos[0] - diff_pos[0], pos[1] - diff_pos[1] ];
-			}
-			else
-			{
-				icon_node.style.display = "none";
-			}
-		}
-
-		DOM.Node.SetPosition(this.Node, pos);
-	}
-
-
-	ComboBoxPopup.prototype.Hide = function()
-	{
-		DOM.Event.RemoveHandler(document.body, "mousedown", this.CancelDelegate);
-		this.ParentNode.removeChild(this.Node);
-	}
-
-
-	function SelectItem(self, evt)
-	{
-		// Search for which item node is being clicked on
-		var node = DOM.Event.GetNode(evt);
-		for (var i in self.ValueNodes)
-		{
-			var value_node = self.ValueNodes[i];
-			if (DOM.Node.Contains(node, value_node))
-			{
-				// Set the value on the combo box
-				self.ComboBox.SetValue(value_node.Value);
-				self.Hide();
-				break;
-			}
-		}
-	}
-
-
-	function Cancel(self, evt)
-	{
-		// Don't cancel if the mouse up is anywhere on the popup or combo box
-		var node = DOM.Event.GetNode(evt);
-		if (!DOM.Node.Contains(node, self.Node) &&
-			!DOM.Node.Contains(node, self.ParentNode))
-		{
-			self.Hide();
-		}
-
-
-		DOM.Event.StopAll(evt);
-	}
-
-
-	return ComboBoxPopup;
-})();
-
-
-WM.ComboBox = (function()
-{
-	var template_html = "																\
-		<div class='ComboBox'>															\
-			<div class='ComboBoxText notextsel'></div>									\
-			<div class='ComboBoxIcon'><img src='BrowserLibImages/up_down.gif'></div>	\
-			<div style='clear:both'></div>												\
-		</div>";
-
-
-	function ComboBox()
-	{
-		this.OnChange = null;
-
-		// Create the template node and locate key nodes
-		this.Node = DOM.Node.CreateHTML(template_html);
-		this.TextNode = DOM.Node.FindWithClass(this.Node, "ComboBoxText");
-
-		// Create a reusable popup
-		this.Popup = new WM.ComboBoxPopup(this);
-
-		// Set an empty set of values
-		this.SetValues([]);
-		this.SetValue("&lt;empty&gt;");
-
-		// Create the mouse press event handlers
-		DOM.Event.AddHandler(this.Node, "mousedown", Bind(OnMouseDown, this));
-		this.OnMouseOutDelegate = Bind(OnMouseUp, this, false);
-		this.OnMouseUpDelegate = Bind(OnMouseUp, this, true);
-	}
-
-
-	ComboBox.prototype.SetOnChange = function(on_change)
-	{
-		this.OnChange = on_change;
-	}
-
-
-	ComboBox.prototype.SetValues = function(values)
-	{
-		this.Values = values;
-		this.Popup.SetValues(values);
-	}
-
-
-	ComboBox.prototype.SetValue = function(value)
-	{
-		// Set the value and its HTML rep
-		var old_value = this.Value;
-		this.Value = value;
-		this.TextNode.innerHTML = value;
-
-		// Call change handler
-		if (this.OnChange)
-			this.OnChange(value, old_value);
-	}
-
-
-	ComboBox.prototype.GetValue = function()
-	{
-		return this.Value;
-	}
-
-
-	function OnMouseDown(self, evt)
-	{
-		// If this check isn't made, the click will trigger from the popup, too
-		var node = DOM.Event.GetNode(evt);
-		if (DOM.Node.Contains(node, self.Node))
-		{
-			// Add the depression class and activate release handlers
-			DOM.Node.AddClass(self.Node, "ComboBoxPressed");
-			DOM.Event.AddHandler(self.Node, "mouseout", self.OnMouseOutDelegate);
-			DOM.Event.AddHandler(self.Node, "mouseup", self.OnMouseUpDelegate);
-
-			DOM.Event.StopAll(evt);
-		}
-	}
-
-
-	function OnMouseUp(self, confirm, evt)
-	{
-		// Remove depression class and remove release handlers
-		DOM.Node.RemoveClass(self.Node, "ComboBoxPressed");
-		DOM.Event.RemoveHandler(self.Node, "mouseout", self.OnMouseOutDelegate);
-		DOM.Event.RemoveHandler(self.Node, "mouseup", self.OnMouseUpDelegate);
-
-		// If this is a confirmed press and there are some values in the list, show the popup
-		if (confirm && self.Values.length > 0)
-		{
-			var selection_index = self.Values.indexOf(self.Value);
-			self.Popup.Show(selection_index);
-		}
-
-		DOM.Event.StopAll(evt);
-	}
-
-
-	return ComboBox;
-})();

+ 0 - 34
3rdparty/remotery/vis/extern/BrowserLib/WindowManager/Code/Container.js

@@ -1,34 +0,0 @@
-
-namespace("WM");
-
-
-WM.Container = (function()
-{
-	var template_html = "<div class='Container'></div>";
-
-
-	function Container(x, y, w, h)
-	{
-		// Create a simple container node
-		this.Node = DOM.Node.CreateHTML(template_html);
-		this.SetPosition(x, y);
-		this.SetSize(w, h);
-	}
-
-
-	Container.prototype.SetPosition = function(x, y)
-	{
-		this.Position = [ x, y ];
-		DOM.Node.SetPosition(this.Node, this.Position);
-	}
-
-
-	Container.prototype.SetSize = function(w, h)
-	{
-		this.Size = [ w, h ];
-		DOM.Node.SetSize(this.Node, this.Size);
-	}
-
-
-	return Container;
-})();

+ 0 - 119
3rdparty/remotery/vis/extern/BrowserLib/WindowManager/Code/EditBox.js

@@ -1,119 +0,0 @@
-
-namespace("WM");
-
-
-WM.EditBox = (function()
-{
-	var template_html = "							\
-		<div class='EditBoxContainer'>				\
-			<div class='EditBoxLabel'>Label</div>	\
-			<input class='EditBox'>					\
-		</div>";
-
-
-	function EditBox(x, y, w, h, label, text)
-	{
-		this.ChangeHandler = null;
-
-		// Create node and locate its internal nodes
-		this.Node = DOM.Node.CreateHTML(template_html);
-		this.LabelNode = DOM.Node.FindWithClass(this.Node, "EditBoxLabel");
-		this.EditNode = DOM.Node.FindWithClass(this.Node, "EditBox");
-
-		// Set label and value
-		this.LabelNode.innerHTML = label;
-		this.SetValue(text);
-
-		this.SetPosition(x, y);
-		this.SetSize(w, h);
-
-		this.PreviousValue = "";
-
-		// Hook up the event handlers
-		DOM.Event.AddHandler(this.EditNode, "focus", Bind(OnFocus, this));
-		DOM.Event.AddHandler(this.EditNode, "keypress", Bind(OnKeyPress, this));
-		DOM.Event.AddHandler(this.EditNode, "keydown", Bind(OnKeyDown, this));
-	}
-
-
-	EditBox.prototype.SetPosition = function(x, y)
-	{
-		this.Position = [ x, y ];
-		DOM.Node.SetPosition(this.Node, this.Position);
-	}
-
-
-	EditBox.prototype.SetSize = function(w, h)
-	{
-		this.Size = [ w, h ];
-		DOM.Node.SetSize(this.EditNode, this.Size);
-	}
-
-
-	EditBox.prototype.SetChangeHandler = function(handler)
-	{
-		this.ChangeHandler = handler;
-	}
-
-
-	EditBox.prototype.SetValue = function(value)
-	{
-		if (this.EditNode)
-			this.EditNode.value = value;
-	}
-
-
-	EditBox.prototype.GetValue = function()
-	{
-		if (this.EditNode)
-			return this.EditNode.value;
-		
-		return null;
-	}
-
-
-	EditBox.prototype.LoseFocus = function()
-	{
-		if (this.EditNode)
-			this.EditNode.blur();
-	}
-
-
-	function OnFocus(self, evt)
-	{
-		// Backup on focus
-		self.PreviousValue = self.EditNode.value;
-	}
-
-
-	function OnKeyPress(self, evt)
-	{
-		// Allow enter to confirm the text only when there's data
-		if (evt.keyCode == 13 && self.EditNode.value != "" && self.ChangeHandler)
-		{
-			var focus = self.ChangeHandler(self.EditNode);
-			if (!focus)
-				self.EditNode.blur();
-			self.PreviousValue = "";
-		}
-	}
-
-
-	function OnKeyDown(self, evt)
-	{
-		// Allow escape to cancel any text changes
-		if (evt.keyCode == 27)
-		{
-			// On initial edit of the input, escape should NOT replace with the empty string
-			if (self.PreviousValue != "")
-			{
-				self.EditNode.value = self.PreviousValue;
-			}
-
-			self.EditNode.blur();
-		}
-	}
-
-
-	return EditBox;
-})();

+ 0 - 252
3rdparty/remotery/vis/extern/BrowserLib/WindowManager/Code/Grid.js

@@ -1,252 +0,0 @@
-
-namespace("WM");
-
-
-WM.GridRows = (function()
-{
-	function GridRows(parent_object)
-	{
-		this.ParentObject = parent_object;
-
-		// Array of rows in the order they were added
-		this.Rows = [ ];
-
-		// Collection of custom row indexes for fast lookup
-		this.Indexes = { };
-	}
-
-
-	GridRows.prototype.AddIndex = function(cell_field_name)
-	{
-		var index = { };
-
-		// Go through existing rows and add to the index
-		for (var i in this.Rows)
-		{
-			var row = this.Rows[i];
-			if (cell_field_name in row.CellData)
-			{
-				var cell_field = row.CellData[cell_field_name];
-				index[cell_field] = row;
-			}
-		}
-
-		this.Indexes[cell_field_name] = index;
-	}
-
-
-	GridRows.prototype.ClearIndex = function(index_name)
-	{
-		this.Indexes[index_name] = { };
-	}
-
-	GridRows.prototype.AddRowToIndex = function(index_name, cell_data, row)
-	{
-		this.Indexes[index_name][cell_data] = row;
-	}
-
-
-	GridRows.prototype.Add = function(cell_data, row_classes, cell_classes)
-	{
-		var row = new WM.GridRow(this.ParentObject, cell_data, row_classes, cell_classes);
-		this.Rows.push(row);
-		return row;
-	}
-
-
-	GridRows.prototype.GetBy = function(cell_field_name, cell_data)
-	{
-		var index = this.Indexes[cell_field_name];
-		return index[cell_data];
-	}
-
-
-	GridRows.prototype.Clear = function()
-	{
-		// Remove all node references from the parent
-		for (var i in this.Rows)
-		{
-			var row = this.Rows[i];
-			row.Parent.BodyNode.removeChild(row.Node);
-		}
-
-		// Clear all indexes
-		for (var i in this.Indexes)
-			this.Indexes[i] = { };
-
-		this.Rows = [ ];
-	}
-
-
-	return GridRows;
-})();
-
-
-WM.GridRow = (function()
-{
-	var template_html = "<div class='GridRow'></div>";
-
-
-	//
-	// 'cell_data' is an object with a variable number of fields.
-	// Any fields prefixed with an underscore are hidden.
-	//
-	function GridRow(parent, cell_data, row_classes, cell_classes)
-	{
-		// Setup data
-		this.Parent = parent;
-		this.IsOpen = true;
-		this.AnimHandle = null;
-		this.Rows = new WM.GridRows(this);
-		this.CellData = cell_data;
-		this.CellNodes = { }
-
-		// Create the main row node
-		this.Node = DOM.Node.CreateHTML(template_html);
-		if (row_classes)
-			DOM.Node.AddClass(this.Node, row_classes);
-
-		// Embed a pointer to the row in the root node so that it can be clicked
-		this.Node.GridRow = this;
-
-		// Create nodes for each required cell
-		for (var attr in this.CellData)
-		{
-			if (this.CellData.hasOwnProperty(attr))
-			{
-				var data = this.CellData[attr];
-
-				// Update any grid row index references
-				if (attr in parent.Rows.Indexes)
-					parent.Rows.AddRowToIndex(attr, data, this);
-
-				// Hide any cells with underscore prefixes
-				if (attr[0] == "_")
-					continue;
-
-				// Create a node for the cell and add any custom classes
-				var node = DOM.Node.AppendHTML(this.Node, "<div class='GridRowCell'></div>");
-				if (cell_classes && attr in cell_classes)
-					DOM.Node.AddClass(node, cell_classes[attr]);
-				this.CellNodes[attr] = node;
-
-				// If this is a Window Control, add its node to the cell
-				if (data instanceof Object && "Node" in data && DOM.Node.IsNode(data.Node))
-				{
-					data.ParentNode = node;
-					node.appendChild(data.Node);
-				}
-
-				else
-				{
-					// Otherwise just assign the data as text
-					node.innerHTML = data;
-				}
-			}
-		}
-
-		// Add the body node for any children
-		DOM.Node.AppendClearFloat(this.Node);
-		this.BodyNode = DOM.Node.AppendHTML(this.Node, "<div class='GridRowBody'></div>");
-
-		// Add the row to the parent
-		this.Parent.BodyNode.appendChild(this.Node);
-	}
-
-
-	GridRow.prototype.Open = function()
-	{
-		// Don't allow open while animating
-		if (this.AnimHandle == null || this.AnimHandle.Complete)
-		{
-			this.IsOpen = true;
-
-			// Kick off open animation
-			var node = this.BodyNode;
-			this.AnimHandle = Anim.Animate(
-				function (val) { DOM.Node.SetHeight(node, val) },
-				0, this.Height, 0.2);
-		}
-	}
-
-
-	GridRow.prototype.Close = function()
-	{
-		// Don't allow close while animating
-		if (this.AnimHandle == null || this.AnimHandle.Complete)
-		{
-			this.IsOpen = false;
-
-			// Record height for the next open request
-			this.Height = this.BodyNode.offsetHeight;
-
-			// Kick off close animation
-			var node = this.BodyNode;
-			this.AnimHandle = Anim.Animate(
-				function (val) { DOM.Node.SetHeight(node, val) },
-				this.Height, 0, 0.2);
-		}
-	}
-
-
-	GridRow.prototype.Toggle = function()
-	{
-		if (this.IsOpen)
-			this.Close();
-		else
-			this.Open();
-	}
-
-
-	return GridRow;
-})();
-
-
-WM.Grid = (function()
-{
-	var template_html = "					\
-		<div class='Grid'>					\
-			<div class='GridBody'></div>	\
-		</div>";
-
-
-	function Grid(x, y, width, height)
-	{
-		this.Rows = new WM.GridRows(this);
-
-		this.Node = DOM.Node.CreateHTML(template_html);
-		this.BodyNode = DOM.Node.FindWithClass(this.Node, "GridBody");
-
-		DOM.Node.SetPosition(this.Node, [ x, y ]);
-		DOM.Node.SetSize(this.Node, [ width, height ]);
-
-		DOM.Event.AddHandler(this.Node, "dblclick", OnDblClick);
-
-		var mouse_wheel_event = (/Firefox/i.test(navigator.userAgent)) ? "DOMMouseScroll" : "mousewheel";
-		DOM.Event.AddHandler(this.Node, mouse_wheel_event, Bind(OnMouseScroll, this));
-	}
-
-
-	function OnDblClick(evt)
-	{
-		// Clicked on a header?
-		var node = DOM.Event.GetNode(evt);
-		if (DOM.Node.HasClass(node, "GridRowName"))
-		{
-			// Toggle rows open/close
-			var row = node.parentNode.GridRow;
-			if (row)
-				row.Toggle();
-		}
-	}
-
-
-	function OnMouseScroll(self, evt)
-	{
-		var mouse_state = new Mouse.State(evt);
-		self.Node.scrollTop -= mouse_state.WheelDelta * 20;
-	}
-
-
-	return Grid;
-})();

+ 0 - 31
3rdparty/remotery/vis/extern/BrowserLib/WindowManager/Code/Label.js

@@ -1,31 +0,0 @@
-
-namespace("WM");
-
-
-WM.Label = (function()
-{
-	var template_html = "<div class='Label'></div>";
-
-
-	function Label(x, y, text)
-	{
-		// Create the node
-		this.Node = DOM.Node.CreateHTML(template_html);
-
-		// Allow position to be optional
-		if (x != null && y != null)
-			DOM.Node.SetPosition(this.Node, [x, y]);
-
-		this.SetText(text);
-	}
-
-
-	Label.prototype.SetText = function(text)
-	{
-		if (text != null)
-			this.Node.innerHTML = text;
-	}
-
-
-	return Label;
-})();

+ 0 - 352
3rdparty/remotery/vis/extern/BrowserLib/WindowManager/Code/Treeview.js

@@ -1,352 +0,0 @@
-
-namespace("WM");
-
-
-WM.Treeview = (function()
-{
-	var Margin = 10;
-
-
-	var tree_template_html = "																							\
-		<div class='Treeview'>																							\
-			<div class='TreeviewItemChildren' style='width:90%;float:left'></div>										\
-			<div class='TreeviewScrollbarInset'>																		\
-				<div class='TreeviewScrollbar'></div>																	\
-			</div>																										\
-			<div style='clear:both'></div>																				\
-		</div>";
-
-
-	var item_template_html = "																							\
-		<div class='TreeViewItem basicfont notextsel'>																	\
-			<img src='' class='TreeviewItemImage'>																		\
-			<div class='TreeviewItemText'></div>																		\
-			<div style='clear:both'></div>																				\
-			<div class='TreeviewItemChildren'></div>																	\
-			<div style='clear:both'></div>																				\
-		</div>";
-
-
-	// TODO: Remove parent_node (required for stuff that doesn't use the WM yet)
-	function Treeview(x, y, width, height, parent_node)
-	{
-		// Cache initialisation options
-		this.ParentNode = parent_node;
-		this.Position = [ x, y ];
-		this.Size = [ width, height ];
-
-		this.Node = null;
-		this.ScrollbarNode = null;
-		this.SelectedItem = null;
-		this.ContentsNode = null;
-
-		// Setup options
-		this.HighlightOnHover = false;
-		this.EnableScrollbar = true;
-		this.HorizontalLayoutDepth = 1;
-
-		// Generate an empty tree
-		this.Clear();
-	}
-
-
-	Treeview.prototype.SetHighlightOnHover = function(highlight)
-	{
-		this.HighlightOnHover = highlight;
-	}
-
-
-	Treeview.prototype.SetEnableScrollbar = function(enable)
-	{
-		this.EnableScrollbar = enable;
-	}
-
-
-	Treeview.prototype.SetHorizontalLayoutDepth = function(depth)
-	{
-		this.HorizontalLayoutDepth = depth;
-	}
-
-
-	Treeview.prototype.SetNodeSelectedHandler = function(handler)
-	{
-		this.NodeSelectedHandler = handler;
-	}
-
-
-	Treeview.prototype.Clear = function()
-	{
-		this.RootItem = new WM.TreeviewItem(this, null, null, null, null);
-		this.GenerateHTML();
-	}
-
-
-	Treeview.prototype.Root = function()
-	{
-		return this.RootItem;
-	}
-
-
-	Treeview.prototype.ClearSelection = function()
-	{
-		if (this.SelectedItem != null)
-		{
-			DOM.Node.RemoveClass(this.SelectedItem.Node, "TreeviewItemSelected");
-			this.SelectedItem = null;
-		}
-	}
-
-
-	Treeview.prototype.SelectItem = function(item, mouse_pos)
-	{
-		// Notify the select handler
-		if (this.NodeSelectedHandler)
-			this.NodeSelectedHandler(item.Node, this.SelectedItem, item, mouse_pos);
-
-		// Remove highlight from the old selection
-		this.ClearSelection();
-
-		// Swap in new selection and apply highlight
-		this.SelectedItem = item;
-		DOM.Node.AddClass(this.SelectedItem.Node, "TreeviewItemSelected");
-	}
-
-
-	Treeview.prototype.GenerateHTML = function()
-	{
-		// Clone the template and locate important nodes
-		var old_node = this.Node;
-		this.Node = DOM.Node.CreateHTML(tree_template_html);
-		this.ChildrenNode = DOM.Node.FindWithClass(this.Node, "TreeviewItemChildren");
-		this.ScrollbarNode = DOM.Node.FindWithClass(this.Node, "TreeviewScrollbar");
-
-		DOM.Node.SetPosition(this.Node, this.Position);
-		DOM.Node.SetSize(this.Node, this.Size);
-
-		// Generate the contents of the treeview
-		GenerateTree(this, this.ChildrenNode, this.RootItem.Children, 0);
-
-		// Cross-browser (?) means of adding a mouse wheel handler
-		var mouse_wheel_event = (/Firefox/i.test(navigator.userAgent)) ? "DOMMouseScroll" : "mousewheel";
-		DOM.Event.AddHandler(this.Node, mouse_wheel_event, Bind(OnMouseScroll, this));
-
-		DOM.Event.AddHandler(this.Node, "dblclick", Bind(OnMouseDoubleClick, this));
-		DOM.Event.AddHandler(this.Node, "mousedown", Bind(OnMouseDown, this));
-		DOM.Event.AddHandler(this.Node, "mouseup", OnMouseUp);
-
-		// Swap in the newly generated control node if it's already been attached to a parent
-		if (old_node && old_node.parentNode)
-		{
-			old_node.parentNode.removeChild(old_node);
-			this.ParentNode.appendChild(this.Node);
-		}
-
-		if (this.EnableScrollbar)
-		{
-			this.UpdateScrollbar();
-			DOM.Event.AddHandler(this.ScrollbarNode, "mousedown", Bind(OnMouseDown_Scrollbar, this));
-			DOM.Event.AddHandler(this.ScrollbarNode, "mouseup", Bind(OnMouseUp_Scrollbar, this));
-			DOM.Event.AddHandler(this.ScrollbarNode, "mouseout", Bind(OnMouseUp_Scrollbar, this));
-			DOM.Event.AddHandler(this.ScrollbarNode, "mousemove", Bind(OnMouseMove_Scrollbar, this));
-		}
-
-		else
-		{
-			DOM.Node.Hide(DOM.Node.FindWithClass(this.Node, "TreeviewScrollbarInset"));
-		}
-	}
-
-	
-	Treeview.prototype.UpdateScrollbar = function()
-	{
-		if (!this.EnableScrollbar)
-			return;
-
-		var scrollbar_scale = Math.min((this.Node.offsetHeight - Margin * 2) / this.ChildrenNode.offsetHeight, 1);
-		this.ScrollbarNode.style.height = parseInt(scrollbar_scale * 100) + "%";
-
-		// Shift the scrollbar container along with the parent window
-		this.ScrollbarNode.parentNode.style.top = this.Node.scrollTop;
-
-		var scroll_fraction = this.Node.scrollTop / (this.Node.scrollHeight - this.Node.offsetHeight);
-		var max_height = this.Node.offsetHeight - Margin;
-		var max_scrollbar_offset = max_height - this.ScrollbarNode.offsetHeight;
-		var scrollbar_offset = scroll_fraction * max_scrollbar_offset;
-		this.ScrollbarNode.style.top = scrollbar_offset;
-	}
-
-
-	function GenerateTree(self, parent_node, items, depth)
-	{
-		if (items.length == 0)
-			return null;
-
-		for (var i in items)
-		{
-			var item = items[i];
-
-			// Create the node for this item and locate important nodes
-			var node = DOM.Node.CreateHTML(item_template_html);
-			var img = DOM.Node.FindWithClass(node, "TreeviewItemImage");
-			var text = DOM.Node.FindWithClass(node, "TreeviewItemText");
-			var children = DOM.Node.FindWithClass(node, "TreeviewItemChildren");
-
-			// Attach the item to the node
-			node.TreeviewItem = item;
-			item.Node = node;
-
-			// Add the class which highlights selection on hover
-			if (self.HighlightOnHover)
-				DOM.Node.AddClass(node, "TreeviewItemHover");
-
-			// Instruct the children to wrap around
-			if (depth >= self.HorizontalLayoutDepth)
-				node.style.cssFloat = "left";
-
-			if (item.OpenImage == null || item.CloseImage == null)
-			{
-				// If there no images, remove the image node
-				node.removeChild(img);
-			}
-			else
-			{
-				// Set the image source to open
-				img.src = item.OpenImage.src;
-				img.style.width = item.OpenImage.width;
-				img.style.height = item.OpenImage.height;
-				item.ImageNode = img;
-			}
-
-			// Setup the text to display
-			text.innerHTML = item.Label;
-
-			// Add the div to the parent and recurse into children
-			parent_node.appendChild(node);
-			GenerateTree(self, children, item.Children, depth + 1);
-			item.ChildrenNode = children;
-		}
-
-		// Clear the wrap-around
-		if (depth >= self.HorizontalLayoutDepth)
-			DOM.Node.AppendClearFloat(parent_node.parentNode);
-	}
-
-
-	function OnMouseScroll(self, evt)
-	{
-		// Get mouse wheel movement
-		var delta = evt.detail ? evt.detail * -1 : evt.wheelDelta;
-		delta *= 8;
-
-		// Scroll the main window with wheel movement and clamp
-		self.Node.scrollTop -= delta;
-		self.Node.scrollTop = Math.min(self.Node.scrollTop, (self.ChildrenNode.offsetHeight - self.Node.offsetHeight) + Margin * 2);
-
-		self.UpdateScrollbar();
-	}
-
-
-	function OnMouseDoubleClick(self, evt)
-	{
-		DOM.Event.StopDefaultAction(evt);
-
-		// Get the tree view item being clicked, if any
-		var node = DOM.Event.GetNode(evt);
-		var tvitem = GetTreeviewItemFromNode(self, node);
-		if (tvitem == null)
-			return;
-
-		if (tvitem.Children.length)
-			tvitem.Toggle();
-	}
-
-
-	function OnMouseDown(self, evt)
-	{
-		DOM.Event.StopDefaultAction(evt);
-
-		// Get the tree view item being clicked, if any
-		var node = DOM.Event.GetNode(evt);
-		var tvitem = GetTreeviewItemFromNode(self, node);
-		if (tvitem == null)
-			return;
-
-		// If clicking on the image, expand any children
-		if (node.tagName == "IMG" && tvitem.Children.length)
-		{
-			tvitem.Toggle();
-		}
-
-		else
-		{
-			var mouse_pos = DOM.Event.GetMousePosition(evt);
-			self.SelectItem(tvitem, mouse_pos);
-		}
-	}
-
-
-	function OnMouseUp(evt)
-	{
-		// Event handler used merely to stop events bubbling up to containers
-		DOM.Event.StopPropagation(evt);
-	}
-
-
-	function OnMouseDown_Scrollbar(self, evt)
-	{
-		self.ScrollbarHeld = true;
-
-		// Cache the mouse height relative to the scrollbar
-		self.LastY = evt.clientY;
-		self.ScrollY = self.Node.scrollTop;
-
-		DOM.Node.AddClass(self.ScrollbarNode, "TreeviewScrollbarHeld");
-		DOM.Event.StopDefaultAction(evt);
-	}
-
-
-	function OnMouseUp_Scrollbar(self, evt)
-	{
-		self.ScrollbarHeld = false;
-		DOM.Node.RemoveClass(self.ScrollbarNode, "TreeviewScrollbarHeld");
-	}
-
-
-	function OnMouseMove_Scrollbar(self, evt)
-	{
-		if (self.ScrollbarHeld)
-		{
-			var delta_y = evt.clientY - self.LastY;
-			self.LastY = evt.clientY;
-
-			var max_height = self.Node.offsetHeight - Margin;
-			var max_scrollbar_offset = max_height - self.ScrollbarNode.offsetHeight;
-			var max_contents_scroll = self.Node.scrollHeight - self.Node.offsetHeight;
-			var scale = max_contents_scroll / max_scrollbar_offset;
-
-			// Increment the local float variable and assign, as scrollTop is of type int
-			self.ScrollY += delta_y * scale;			
-			self.Node.scrollTop = self.ScrollY;
-			self.Node.scrollTop = Math.min(self.Node.scrollTop, (self.ChildrenNode.offsetHeight - self.Node.offsetHeight) + Margin * 2);
-
-			self.UpdateScrollbar();
-		}
-	}
-
-
-	function GetTreeviewItemFromNode(self, node)
-	{
-		// Walk up toward the tree view node looking for this first item
-		while (node && node != self.Node)
-		{
-			if ("TreeviewItem" in node)
-				return node.TreeviewItem;
-
-			node = node.parentNode;
-		}
-
-		return null;
-	}
-
-	return Treeview;
-})();

+ 0 - 109
3rdparty/remotery/vis/extern/BrowserLib/WindowManager/Code/TreeviewItem.js

@@ -1,109 +0,0 @@
-
-namespace("WM");
-
-
-WM.TreeviewItem = (function()
-{
-	function TreeviewItem(treeview, name, data, open_image, close_image)
-	{
-		// Assign members
-		this.Treeview = treeview;
-		this.Label = name;
-		this.Data = data;
-		this.OpenImage = open_image;
-		this.CloseImage = close_image;
-
-		this.Children = [ ];
-
-		// The HTML node wrapping the item and its children
-		this.Node = null;
-
-		// The HTML node storing the image for the open/close state feedback
-		this.ImageNode = null;
-
-		// The HTML node storing just the children
-		this.ChildrenNode = null;
-
-		// Animation handle for opening and closing the child nodes, only used
-		// if the tree view item as children
-		this.AnimHandle = null;
-
-		// Open state of the item
-		this.IsOpen = true;
-	}
-
-
-	TreeviewItem.prototype.AddItem = function(name, data, open_image, close_image)
-	{
-		var item = new WM.TreeviewItem(this.Treeview, name, data, open_image, close_image);
-		this.Children.push(item);
-		return item;
-	}
-
-
-	TreeviewItem.prototype.Open = function()
-	{
-		if (this.AnimHandle == null || this.AnimHandle.Complete)
-		{
-			// Swap to the open state
-			this.IsOpen = true;
-			if (this.ImageNode != null && this.OpenImage != null)
-				this.ImageNode.src = this.OpenImage.src;
-			
-			// Cache for closure binding
-			var child_node = this.ChildrenNode;
-			var end_height = this.StartHeight;
-			var treeview = this.Treeview;
-
-			// Reveal the children and animate their height to max
-			this.ChildrenNode.style.display = "block";
-			this.AnimHandle = Anim.Animate(
-				function (val) { DOM.Node.SetHeight(child_node, val) },
-				0, end_height, 0.2,
-				function() { treeview.UpdateScrollbar(); });
-
-			// Fade the children in
-			Anim.Animate(function(val) { DOM.Node.SetOpacity(child_node, val) }, 0, 1, 0.2);
-		}
-	}
-
-
-	TreeviewItem.prototype.Close = function()
-	{
-		if (this.AnimHandle == null || this.AnimHandle.Complete)
-		{
-			// Swap to the close state
-			this.IsOpen = false;
-			if (this.ImageNode != null && this.CloseImage != null)
-				this.ImageNode.src = this.CloseImage.src;
-
-			// Cache for closure binding
-			var child_node = this.ChildrenNode;
-			var treeview = this.Treeview;
-
-			// Mark the height of the item for reload later
-			this.StartHeight = child_node.offsetHeight;
-
-			// Shrink the height of the children and hide them upon completion
-			this.AnimHandle = Anim.Animate(
-				function (val) { DOM.Node.SetHeight(child_node, val) },
-				this.ChildrenNode.offsetHeight, 0, 0.2,
-				function() { child_node.style.display = "none"; treeview.UpdateScrollbar(); });
-
-			// Fade the children out
-			Anim.Animate(function(val) { DOM.Node.SetOpacity(child_node, val) }, 1, 0, 0.2);
-		}
-	}
-
-
-	TreeviewItem.prototype.Toggle = function()
-	{
-		if (this.IsOpen)
-			this.Close();
-		else
-			this.Open();
-	}
-
-
-	return TreeviewItem;
-})();

+ 0 - 243
3rdparty/remotery/vis/extern/BrowserLib/WindowManager/Code/Window.js

@@ -1,243 +0,0 @@
-
-namespace("WM");
-
-
-WM.Window = (function()
-{
-	var template_html = "																								\
-		<div class='Window'>																							\
-			<div class='WindowTitleBar'>																				\
-				<div class='WindowTitleBarText notextsel' style='float:left'>Window Title Bar</div>						\
-				<div class='WindowTitleBarClose notextsel' style='float:right'>O</div>									\
-			</div>																										\
-			<div class='WindowBody'>																					\
-			</div>																										\
-		</div>";
-
-
-	function Window(manager, title, x, y, width, height, parent_node)
-	{
-		this.Manager = manager;
-		this.ParentNode = parent_node || document.body;
-		this.OnMove = null;
-		this.Visible = false;
-		this.AnimatedShow = false;
-
-		// Clone the window template and locate key nodes within it
-		this.Node = DOM.Node.CreateHTML(template_html);
-		this.TitleBarNode = DOM.Node.FindWithClass(this.Node, "WindowTitleBar");
-		this.TitleBarTextNode = DOM.Node.FindWithClass(this.Node, "WindowTitleBarText");
-		this.TitleBarCloseNode = DOM.Node.FindWithClass(this.Node, "WindowTitleBarClose");
-		this.BodyNode = DOM.Node.FindWithClass(this.Node, "WindowBody");
-
-		// Setup the position and dimensions of the window
-		this.SetPosition(x, y);
-		this.SetSize(width, height);
-
-		// Set the title text
-		this.TitleBarTextNode.innerHTML = title;
-
-		// Hook up event handlers
-		DOM.Event.AddHandler(this.Node, "mousedown", Bind(this, "SetTop"));
-		DOM.Event.AddHandler(this.TitleBarNode, "mousedown", Bind(this, "BeginMove"));
-		DOM.Event.AddHandler(this.TitleBarCloseNode, "mousedown", Bind(this, "Hide"));
-
-		// Create delegates for removable handlers
-		this.MoveDelegate = Bind(this, "Move");
-		this.EndMoveDelegate = Bind(this, "EndMove");		
-	}
-
-
-	Window.prototype.SetOnMove = function(on_move)
-	{
-		this.OnMove = on_move;
-	}
-
-
-	Window.prototype.Show = function()
-	{
-		if (this.Node.parentNode != this.ParentNode)
-		{
-			this.ShowNoAnim();
-			Anim.Animate(Bind(this, "OpenAnimation"), 0, 1, 1);
-		}
-	}
-
-
-	Window.prototype.ShowNoAnim = function()
-	{
-		// Add to the document
-		this.ParentNode.appendChild(this.Node);
-		this.AnimatedShow = false;
-		this.Visible = true;
-	}
-
-
-	Window.prototype.Hide = function()
-	{
-		if (this.Node.parentNode == this.ParentNode)
-		{
-			if (this.AnimatedShow)
-			{
-				// Trigger animation that ends with removing the window from the document
-				Anim.Animate(
-					Bind(this, "CloseAnimation"),
-					0, 1, 0.25,
-					Bind(this, "HideNoAnim"));
-			}
-			else
-			{
-				this.HideNoAnim();
-			}
-		}
-	}
-
-	
-	Window.prototype.HideNoAnim = function()
-	{
-		// Remove node
-		this.ParentNode.removeChild(this.Node);
-		this.Visible = false;
-	}
-
-
-	Window.prototype.SetTop = function()
-	{
-		this.Manager.SetTopWindow(this);
-	}
-
-
-
-	Window.prototype.SetTitle = function(title)
-	{
-		this.TitleBarTextNode.innerHTML = title;
-	}
-
-
-	// TODO: Update this
-	Window.prototype.AddControl = function(control)
-	{
-		// Get all arguments to this function and replace the first with this window node
-		var args = [].slice.call(arguments);
-		args[0] = this.BodyNode;
-
-		// Create the control and call its Init method with the modified arguments
-		var instance = new control();
-		instance.Init.apply(instance, args);
-
-		return instance;
-	}
-
-
-	Window.prototype.AddControlNew = function(control)
-	{
-		control.ParentNode = this.BodyNode;
-		this.BodyNode.appendChild(control.Node);
-		return control;
-	}
-
-
-	Window.prototype.Scale = function(t)
-	{
-		// Calculate window bounds centre/extents
-		var ext_x = this.Size[0] / 2;
-		var ext_y = this.Size[1] / 2;
-		var mid_x = this.Position[0] + ext_x;
-		var mid_y = this.Position[1] + ext_y;
-
-		// Scale from the mid-point
-		DOM.Node.SetPosition(this.Node, [ mid_x - ext_x * t, mid_y - ext_y * t ]);
-		DOM.Node.SetSize(this.Node, [ this.Size[0] * t, this.Size[1] * t ]);
-	}
-
-
-	Window.prototype.OpenAnimation = function(val)
-	{
-		// Power ease in
-		var t = 1 - Math.pow(1 - val, 8);
-		this.Scale(t);
-		DOM.Node.SetOpacity(this.Node, 1 - Math.pow(1 - val, 8));
-		this.AnimatedShow = true;
-	}
-
-
-	Window.prototype.CloseAnimation = function(val)
-	{
-		// Power ease out
-		var t = 1 - Math.pow(val, 4);
-		this.Scale(t);
-		DOM.Node.SetOpacity(this.Node, t);
-	}
-
-
-	Window.prototype.NotifyChange = function()
-	{
-		if (this.OnMove)
-		{
-			var pos = DOM.Node.GetPosition(this.Node);
-			this.OnMove(this, pos);
-		}
-	}
-
-
-	Window.prototype.BeginMove = function(evt)
-	{
-		// Calculate offset of the window from the mouse down position
-		var mouse_pos = DOM.Event.GetMousePosition(evt);
-		this.Offset = [ mouse_pos[0] - this.Position[0], mouse_pos[1] - this.Position[1] ];
-
-		// Dynamically add handlers for movement and release
-		DOM.Event.AddHandler(document, "mousemove", this.MoveDelegate);
-		DOM.Event.AddHandler(document, "mouseup", this.EndMoveDelegate);
-
-		DOM.Event.StopDefaultAction(evt);
-	}
-
-
-	Window.prototype.Move = function(evt)
-	{
-		// Use the offset at the beginning of movement to drag the window around
-		var mouse_pos = DOM.Event.GetMousePosition(evt);
-		var offset = this.Offset;
-		var pos = [ mouse_pos[0] - offset[0], mouse_pos[1] - offset[1] ];
-		this.SetPosition(pos[0], pos[1]);
-
-		if (this.OnMove)
-			this.OnMove(this, pos);
-
-		DOM.Event.StopDefaultAction(evt);
-	}
-
-
-	Window.prototype.EndMove = function(evt)
-	{
-		// Remove handlers added during mouse down
-		DOM.Event.RemoveHandler(document, "mousemove", this.MoveDelegate);
-		DOM.Event.RemoveHandler(document, "mouseup", this.EndMoveDelegate);
-
-		DOM.Event.StopDefaultAction(evt);
-	}
-
-
-	Window.prototype.SetPosition = function(x, y)
-	{
-		this.Position = [ x, y ];
-		DOM.Node.SetPosition(this.Node, this.Position);
-	}
-
-
-	Window.prototype.SetSize = function(w, h)
-	{
-		this.Size = [ w, h ];
-		DOM.Node.SetSize(this.Node, this.Size);
-	}
-
-
-	Window.prototype.GetZIndex = function()
-	{
-		return parseInt(this.Node.style.zIndex);
-	}
-
-
-	return Window;
-})();

+ 0 - 54
3rdparty/remotery/vis/extern/BrowserLib/WindowManager/Code/WindowManager.js

@@ -1,54 +0,0 @@
-
-namespace("WM");
-
-
-WM.WindowManager = (function()
-{
-	function WindowManager()
-	{
-		// An empty list of windows under window manager control
-		this.Windows = [ ];
-	}
-
-
-	WindowManager.prototype.AddWindow = function(title, x, y, width, height, parent_node)
-	{
-		// Create the window and add it to the list of windows
-		var wnd = new WM.Window(this, title, x, y, width, height, parent_node);
-		this.Windows.push(wnd);
-
-		// Always bring to the top on creation
-		wnd.SetTop();
-
-		return wnd;
-	}
-
-
-	WindowManager.prototype.SetTopWindow = function(top_wnd)
-	{
-		// Bring the window to the top of the window list
-		var top_wnd_index = this.Windows.indexOf(top_wnd);
-		if (top_wnd_index != -1)
-			this.Windows.splice(top_wnd_index, 1);
-		this.Windows.push(top_wnd);
-
-		// Set a CSS z-index for each visible window from the bottom up
-		for (var i in this.Windows)
-		{
-			var wnd = this.Windows[i];
-			if (!wnd.Visible)
-				continue;
-
-			// Ensure there's space between each window for the elements inside to be sorted
-			var z = (parseInt(i) + 1) * 10;
-			wnd.Node.style.zIndex = z;
-
-			// Notify window that its z-order has changed
-			wnd.NotifyChange();
-		}
-	}
-
-
-	return WindowManager;
-
-})();

+ 0 - 546
3rdparty/remotery/vis/extern/BrowserLib/WindowManager/Styles/WindowManager.css

@@ -1,546 +0,0 @@
-
-
-.notextsel
-{
-	/* Disable text selection so that it doesn't interfere with button-clicking */
-	user-select:none;
-
-	/* Stops the text cursor over the label */
-	cursor:default;
-}
-
-
-
-/* ------------------------------------------------------------------------------------------------------------------ */
-/* Window Styles                                                                                                      */
-/* ------------------------------------------------------------------------------------------------------------------ */
-
-
-
-.Window
-{
-	/* Allows movement of the window to exceed browser region without triggering scroll bars */
-	position:fixed;
-
-	/* Clip all contents to the window border */
-	overflow: hidden;
-
-	background: #404040;
-
-	border-radius: 5px;
-	-moz-border-radius: 5px;
-
-	-webkit-box-shadow: 3px 3px 3px #111, 1px 1px 1px #606060 inset;
-	box-shadow: 3px 3px 3px #111, 1px 1px 1px #606060 inset;
-}
-
-.Window_Transparent
-{
-	/* Set transparency changes to fade in/out */
-	opacity: 0.5;
-	transition: opacity 0.5s ease-out;
-	-moz-transition: opacity 0.5s ease-out;
-	-webkit-transition: opacity 0.5s ease-out;
-}
-
-.Window_Transparent:hover
-{
-	opacity: 1;
-}
-
-.WindowTitleBar
-{
-	height: 17px;
-	cursor: move;
-
-	border-bottom: 1px solid #303030;
-	border-radius: 5px;
-}
-
-.WindowTitleBarText
-{
-	color: #BBB;
-	font: 9px Verdana;
-
-	padding: 3px;
-	cursor: move;
-}
-
-.WindowTitleBarClose
-{
-	color: #999999;
-	font: 9px Verdana;
-
-	padding: 3px;
-	cursor: default;
-}
-
-.WindowBody
-{
-	/* Turns this node into a "positioned node" so that its children can be placed relative to it */
-	position: absolute;
-
-	/* Fill the parent window node */
-	width: 100%;
-	height: 100%;
-
-	padding:10px;
-	border-top: 1px solid #606060;
-}
-
-
-
-/* ------------------------------------------------------------------------------------------------------------------ */
-/* Container Styles                                                                                                   */
-/* ------------------------------------------------------------------------------------------------------------------ */
-
-
-
-.Container
-{
-	/* Position relative to the parent window */
-	position: absolute;
-
-	background:#2C2C2C;
-
-	border: 1px black solid;
-
-	/* Two inset box shadows to simulate depressing */
-	-webkit-box-shadow: -1px -1px 1px #222 inset, 1px 1px 1px #222 inset;
-	box-shadow: -1px -1px 1px #222 inset, 1px 1px 1px #222 inset;
-}
-
-
-
-/* ------------------------------------------------------------------------------------------------------------------ */
-/* Treeview Styles                                                                                                    */
-/* ------------------------------------------------------------------------------------------------------------------ */
-
-
-
-.Treeview
-{
-	position: absolute;
-
-	background:#2C2C2C;
-	border: 1px solid black;
-	overflow:hidden;
-
-	/* Two inset box shadows to simulate depressing */
-	-webkit-box-shadow: -1px -1px 1px #222 inset, 1px 1px 1px #222 inset;
-	box-shadow: -1px -1px 1px #222 inset, 1px 1px 1px #222 inset;
-}
-
-.TreeviewItem
-{
-	margin:1px;
-	padding:2px;
-	border:solid 1px #2C2C2C;
-	background-color:#2C2C2C;
-}
-
-.TreeviewItemImage
-{
-	float: left;
-}
-
-.TreeviewItemText
-{
-	float: left;
-	margin-left:4px;
-}
-
-.TreeviewItemChildren
-{
-	overflow: hidden;
-}
-
-.TreeviewItemSelected
-{
-	background-color:#444;
-	border-color:#FFF;
-
-	-webkit-transition: background-color 0.2s ease-in-out;
-	-moz-transition: background-color 0.2s ease-in-out;
-	-webkit-transition: border-color 0.2s ease-in-out;
-	-moz-transition: border-color 0.2s ease-in-out;
-}
-
-/* Used to populate treeviews that want highlight on hover behaviour */
-.TreeviewItemHover
-{
-}
-
-.TreeviewItemHover:hover
-{
-	background-color:#111;
-	border-color:#444;
-
-	-webkit-transition: background-color 0.2s ease-in-out;
-	-moz-transition: background-color 0.2s ease-in-out;
-	-webkit-transition: border-color 0.2s ease-in-out;
-	-moz-transition: border-color 0.2s ease-in-out;
-}
-
-.TreeviewScrollbarInset
-{
-	float: right;
-
-	position:relative;
-
-	height: 100%;
-
-	/* CRAZINESS PART A: Trying to get the inset and scrollbar to have 100% height match its container */
-	margin: -8px -8px 0 0;
-	padding: 0 1px 14px 1px;
-
-	width:20px;
-	background:#2C2C2C;
-	border: 1px solid black;
-
-	/* Two inset box shadows to simulate depressing */
-	-webkit-box-shadow: -1px -1px 1px #222 inset, 1px 1px 1px #222 inset;
-	box-shadow: -1px -1px 1px #222 inset, 1px 1px 1px #222 inset;
-}
-
-.TreeviewScrollbar
-{
-	position:relative;
-
-	background:#2C2C2C;
-	border: 1px solid black;
-
-	/* CRAZINESS PART B: Trying to get the inset and scrollbar to have 100% height match its container */
-	padding: 0 0 10px 0;
-	margin: 1px 0 0 0;
-
-	width: 18px;
-	height: 100%;
-
-	border-radius:6px;
-	border-color:#000;
-	border-width:1px;
-	border-style:solid;
-
-	/* The gradient for the button background */
-	background-color:#666;
-	background: -webkit-gradient(linear, left top, left bottom, from(#666), to(#383838));
-	background: -moz-linear-gradient(top, #666, #383838);
-	filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#666666', endColorstr='#383838');
-
-	/* A box shadow and inset box highlight */
-	-webkit-box-shadow: 1px 1px 1px #222, 1px 1px 1px #777 inset;
-	box-shadow: 1px 1px 1px #222, 1px 1px 1px #777 inset;
-}
-
-.TreeviewScrollbarHeld
-{
-	/* Reset the gradient to a full-colour background */
-	background:#383838;
-
-	/* Two inset box shadows to simulate depressing */
-	-webkit-box-shadow: -1px -1px 1px #222 inset, 1px 1px 1px #222 inset;
-	box-shadow: -1px -1px 1px #222 inset, 1px 1px 1px #222 inset;
-}
-
-
- 
-/* ------------------------------------------------------------------------------------------------------------------ */
-/* Treeview Styles                                                                                                    */
-/* ------------------------------------------------------------------------------------------------------------------ */
-
-
-
-.EditBoxContainer
-{
-	position: absolute;
-	padding:2px 10px 2px 10px;
-}
-
-.EditBoxLabel
-{
-	float:left;
-	padding: 3px 4px 4px 4px;
-	font: 9px Verdana;
-}
-
-.EditBox
-{
-	float:left;
-
-	background:#666;
-	border: 1px solid;
-	border-radius: 6px;
-	padding: 3px 4px 3px 4px;
-	height: 20px;
-
-	box-shadow: 1px 1px 1px #222 inset;
-
-	transition: all 0.3s ease-in-out;
-}
-
-.EditBox:focus
-{
-	background:#FFF;
-	outline:0;
-}
-
-
-
-/* ------------------------------------------------------------------------------------------------------------------ */
-/* Label Styles                                                                                                       */
-/* ------------------------------------------------------------------------------------------------------------------ */
-
-
-
-.Label
-{
-	/* Position relative to the parent window */
-	position:absolute;
-
-	color: #BBB;
-	font: 9px Verdana;
-}
-
-
-
-/* ------------------------------------------------------------------------------------------------------------------ */
-/* Combo Box Styles                                                                                                   */
-/* ------------------------------------------------------------------------------------------------------------------ */
-
-
-
-.ComboBox
-{
-	position:absolute;
-
-	/* TEMP! */
-	width:90px;
-
-	/* Height is fixed to match the font */
-	height:14px;
-
-	/* Align the text within the combo box */
-	padding: 1px 0 0 5px;
-
-	/* Solid, rounded border */
-	border: 1px solid #111;
-	border-radius: 5px;
-
-	/* http://www.colorzilla.com/gradient-editor/#e3e3e3+0,c6c6c6+22,b7b7b7+33,afafaf+50,a7a7a7+67,797979+82,414141+100;Custom */    
-	background: #e3e3e3;
-	background: -moz-linear-gradient(top,  #e3e3e3 0%, #c6c6c6 22%, #b7b7b7 33%, #afafaf 50%, #a7a7a7 67%, #797979 82%, #414141 100%);
-	background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#e3e3e3), color-stop(22%,#c6c6c6), color-stop(33%,#b7b7b7), color-stop(50%,#afafaf), color-stop(67%,#a7a7a7), color-stop(82%,#797979), color-stop(100%,#414141));
-	background: -webkit-linear-gradient(top,  #e3e3e3 0%,#c6c6c6 22%,#b7b7b7 33%,#afafaf 50%,#a7a7a7 67%,#797979 82%,#414141 100%);
-	background: -o-linear-gradient(top,  #e3e3e3 0%,#c6c6c6 22%,#b7b7b7 33%,#afafaf 50%,#a7a7a7 67%,#797979 82%,#414141 100%);
-	background: -ms-linear-gradient(top,  #e3e3e3 0%,#c6c6c6 22%,#b7b7b7 33%,#afafaf 50%,#a7a7a7 67%,#797979 82%,#414141 100%);
-	background: linear-gradient(top,  #e3e3e3 0%,#c6c6c6 22%,#b7b7b7 33%,#afafaf 50%,#a7a7a7 67%,#797979 82%,#414141 100%);
-	filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#e3e3e3', endColorstr='#414141',GradientType=0 );
-}
-
-.ComboBoxPressed
-{
-	/* The reverse of the default background, simulating depression */
-	background: #414141;
-	background: -moz-linear-gradient(top,  #414141 0%, #797979 18%, #a7a7a7 33%, #afafaf 50%, #b7b7b7 67%, #c6c6c6 78%, #e3e3e3 100%);
-	background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#414141), color-stop(18%,#797979), color-stop(33%,#a7a7a7), color-stop(50%,#afafaf), color-stop(67%,#b7b7b7), color-stop(78%,#c6c6c6), color-stop(100%,#e3e3e3));
-	background: -webkit-linear-gradient(top,  #414141 0%,#797979 18%,#a7a7a7 33%,#afafaf 50%,#b7b7b7 67%,#c6c6c6 78%,#e3e3e3 100%);
-	background: -o-linear-gradient(top,  #414141 0%,#797979 18%,#a7a7a7 33%,#afafaf 50%,#b7b7b7 67%,#c6c6c6 78%,#e3e3e3 100%);
-	background: -ms-linear-gradient(top,  #414141 0%,#797979 18%,#a7a7a7 33%,#afafaf 50%,#b7b7b7 67%,#c6c6c6 78%,#e3e3e3 100%);
-	background: linear-gradient(top,  #414141 0%,#797979 18%,#a7a7a7 33%,#afafaf 50%,#b7b7b7 67%,#c6c6c6 78%,#e3e3e3 100%);
-	filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#414141', endColorstr='#e3e3e3',GradientType=0 );
-}
-
-.ComboBoxText
-{
-	/* Text info */
-	color: #000;
-	font: 9px Verdana;
-
-	float:left;
-}
-
-.ComboBoxIcon
-{
-	/* Push the image to the far right */
-	float:right;
-
-	/* Align the image with the combo box */
-	padding: 2px 5px 0 0;
-}
-
-.ComboBoxPopup
-{
-	position: fixed;
-
-	background: #CCC;
-
-	border-radius: 5px;
-
-	padding: 1px 0 1px 0;
-}
-
-.ComboBoxPopupItem
-{
-	/* Text info */
-	color: #000;
-	font: 9px Verdana;
-
-	padding: 1px 1px 1px 5px;
-
-	border-bottom: 1px solid #AAA;
-	border-top: 1px solid #FFF;
-}
-
-.ComboBoxPopupItemText
-{
-	float:left;
-}
-
-.ComboBoxPopupItemIcon
-{
-	/* Push the image to the far right */
-	float:right;
-
-	/* Align the image with the combo box */
-	padding: 2px 5px 0 0;
-}
-
-.ComboBoxPopupItem:first-child
-{
-	border-top: 0px;
-}
-
-.ComboBoxPopupItem:last-child
-{
-	border-bottom: 0px;
-}
-
-.ComboBoxPopupItem:hover
-{
-	color:#FFF;
-	background: #2036E1;
-}
-
-
-
-/* ------------------------------------------------------------------------------------------------------------------ */
-/* Grid Styles                                                                                                        */
-/* ------------------------------------------------------------------------------------------------------------------ */
-
-
-
-.Grid
-{
-	/* Clip contents */
-	overflow: hidden;
-
-	position: relative;
-
-	background: #333;
-
-	border-radius: 2px;
-}
-
-.GridBody
-{
-}
-
-.GridRow
-{
-	background:#303030;
-
-	color: #BBB;
-	font: 9px Verdana;
-
-	padding: 2px;
-}
-
-.GridRow.GridGroup
-{
-	padding: 0px;
-}
-
-.GridRow:nth-child(odd)
-{
-	background:#333;
-}
-
-.GridRowCell
-{
-	float:left;
-}
-.GridRowCell.GridGroup
-{
-	color: #BBB;
-
-	/* Override default from name */
-	width: 100%;
-
-	padding: 1px 1px 1px 2px;
-	border: 1px solid;
-	border-radius: 2px;
-
-	border-top-color:#555;
-	border-left-color:#555;
-	border-bottom-color:#111;
-	border-right-color:#111;
-
-	background: #222;
-}
-
-.GridRowBody
-{
-	/* Clip all contents for show/hide group*/
-	overflow: hidden;
-
-	/* Crazy CSS rules: controls for properties don't clip if this isn't set on this parent */
-	position: relative;
-}
-
-
-
-/* ------------------------------------------------------------------------------------------------------------------ */
-/* Button Styles                                                                                                      */
-/* ------------------------------------------------------------------------------------------------------------------ */
-
-
-
-.Button
-{
-	/* Position relative to the parent window */
-	position:absolute;
-
-	border-radius:6px;
-	border-color:#000;
-	border-width:1px;
-	border-style:solid;
-
-	/* Padding at the top includes 2px for the text drop-shadow */
-	padding: 2px 5px 3px 5px;
-
-	color: #BBB;
-	font: 9px Verdana;
-	text-shadow: 1px 1px 1px black;
-	text-align: center;
-
-	/* The gradient for the button background */
-	background-color:#666;
-	background: -webkit-gradient(linear, left top, left bottom, from(#666), to(#383838));
-	background: -moz-linear-gradient(top, #666, #383838);
-	filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#666666', endColorstr='#383838');
-
-	/* A box shadow and inset box highlight */
-	-webkit-box-shadow: 1px 1px 1px #222, 1px 1px 1px #777 inset;
-	box-shadow: 1px 1px 1px #222, 1px 1px 1px #777 inset;
-}
-
-.ButtonHeld
-{
-	/* Reset the gradient to a full-colour background */
-	background:#383838;
-
-	/* Two inset box shadows to simulate depressing */
-	-webkit-box-shadow: -1px -1px 1px #222 inset, 1px 1px 1px #222 inset;
-	box-shadow: -1px -1px 1px #222 inset, 1px 1px 1px #222 inset;
-}

+ 0 - 55
3rdparty/remotery/vis/index.html

@@ -1,55 +0,0 @@
-
-<html xmlns="http://www.w3.org/1999/xhtml">
-
-	<head>
-
-		<title>Remotery Viewer</title>
-
-		<!-- Style Sheets -->
-		<link rel="stylesheet" type="text/css" href="extern/BrowserLib/WindowManager/Styles/WindowManager.css" />
-		<link rel="stylesheet" type="text/css" href="Styles/Remotery.css" />
-
-		<!-- Utilities -->
-		<script type="text/javascript" src="extern/BrowserLib/Core/Code/Core.js"></script>
-		<script type="text/javascript" src="extern/BrowserLib/Core/Code/DOM.js"></script>
-		<script type="text/javascript" src="extern/BrowserLib/Core/Code/Bind.js"></script>
-		<script type="text/javascript" src="extern/BrowserLib/Core/Code/Animation.js"></script>
-		<script type="text/javascript" src="extern/BrowserLib/Core/Code/Convert.js"></script>
-		<script type="text/javascript" src="extern/BrowserLib/Core/Code/LocalStore.js"></script>
-		<script type="text/javascript" src="extern/BrowserLib/Core/Code/Mouse.js"></script>
-		<script type="text/javascript" src="extern/BrowserLib/Core/Code/Keyboard.js"></script>
-
-		<!-- User Interface Window Manager -->
-		<script type="text/javascript" src="extern/BrowserLib/WindowManager/Code/WindowManager.js"></script>
-		<script type="text/javascript" src="extern/BrowserLib/WindowManager/Code/Window.js"></script>
-		<script type="text/javascript" src="extern/BrowserLib/WindowManager/Code/Container.js"></script>
-		<script type="text/javascript" src="extern/BrowserLib/WindowManager/Code/EditBox.js"></script>
-		<script type="text/javascript" src="extern/BrowserLib/WindowManager/Code/Grid.js"></script>
-		<script type="text/javascript" src="extern/BrowserLib/WindowManager/Code/Label.js"></script>
-		<script type="text/javascript" src="extern/BrowserLib/WindowManager/Code/Button.js"></script>
-
-		<!-- Main Application -->
-        <script type="text/javascript" src="Code/DataViewReader.js"></script>
-		<script type="text/javascript" src="Code/Console.js"></script>
-		<script type="text/javascript" src="Code/WebSocketConnection.js"></script>
-		<script type="text/javascript" src="Code/TitleWindow.js"></script>
-		<script type="text/javascript" src="Code/SampleWindow.js"></script>
-		<script type="text/javascript" src="Code/PixelTimeRange.js"></script>
-		<script type="text/javascript" src="Code/TimelineRow.js"></script>
-		<script type="text/javascript" src="Code/TimelineWindow.js"></script>
-		<script type="text/javascript" src="Code/ThreadFrame.js"></script>
-		<script type="text/javascript" src="Code/Remotery.js"></script>
-
-	</head>
-
-	<body>
-
-		<script type="text/javascript">
-
-			var remotery = new Remotery();
-
-		</script>
-
-	</body>
-
-</html>

+ 0 - 49
examples/common/entry/entry.cpp

@@ -18,9 +18,6 @@
 #include "cmd.h"
 #include "cmd.h"
 #include "input.h"
 #include "input.h"
 
 
-#define RMT_ENABLED ENTRY_CONFIG_PROFILER
-#include <remotery/lib/Remotery.h>
-
 extern "C" int32_t _main_(int32_t _argc, char** _argv);
 extern "C" int32_t _main_(int32_t _argc, char** _argv);
 
 
 namespace entry
 namespace entry
@@ -29,8 +26,6 @@ namespace entry
 	static uint32_t s_reset = BGFX_RESET_NONE;
 	static uint32_t s_reset = BGFX_RESET_NONE;
 	static bool s_exit = false;
 	static bool s_exit = false;
 
 
-	static Remotery* s_rmt = NULL;
-
 	static bx::FileReaderI* s_fileReader = NULL;
 	static bx::FileReaderI* s_fileReader = NULL;
 	static bx::FileWriterI* s_fileWriter = NULL;
 	static bx::FileWriterI* s_fileWriter = NULL;
 
 
@@ -39,21 +34,6 @@ namespace entry
 
 
 	typedef bx::StringT<&g_allocator> String;
 	typedef bx::StringT<&g_allocator> String;
 
 
-	void* rmtMalloc(void* /*_context*/, rmtU32 _size)
-	{
-		return BX_ALLOC(g_allocator, _size);
-	}
-
-	void* rmtRealloc(void* /*_context*/, void* _ptr, rmtU32 _size)
-	{
-		return BX_REALLOC(g_allocator, _ptr, _size);
-	}
-
-	void rmtFree(void* /*_context*/, void* _ptr)
-	{
-		BX_FREE(g_allocator, _ptr);
-	}
-
 	static String s_currentDir;
 	static String s_currentDir;
 
 
 	class FileReader : public bx::FileReader
 	class FileReader : public bx::FileReader
@@ -572,29 +552,6 @@ BX_PRAGMA_DIAGNOSTIC_POP();
 	{
 	{
 		//DBG(BX_COMPILER_NAME " / " BX_CPU_NAME " / " BX_ARCH_NAME " / " BX_PLATFORM_NAME);
 		//DBG(BX_COMPILER_NAME " / " BX_CPU_NAME " / " BX_ARCH_NAME " / " BX_PLATFORM_NAME);
 
 
-		if (BX_ENABLED(ENTRY_CONFIG_PROFILER) )
-		{
-			rmtSettings* settings = rmt_Settings();
-			BX_WARN(NULL != settings, "Remotery is not enabled.");
-			if (NULL != settings)
-			{
-				settings->malloc  = rmtMalloc;
-				settings->realloc = rmtRealloc;
-				settings->free    = rmtFree;
-
-				rmtError err = rmt_CreateGlobalInstance(&s_rmt);
-				BX_WARN(RMT_ERROR_NONE != err, "Remotery failed to create global instance.");
-				if (RMT_ERROR_NONE == err)
-				{
-					rmt_SetCurrentThreadName("Main");
-				}
-				else
-				{
-					s_rmt = NULL;
-				}
-			}
-		}
-
 		s_fileReader = BX_NEW(g_allocator, FileReader);
 		s_fileReader = BX_NEW(g_allocator, FileReader);
 		s_fileWriter = BX_NEW(g_allocator, FileWriter);
 		s_fileWriter = BX_NEW(g_allocator, FileWriter);
 
 
@@ -673,12 +630,6 @@ restart:
 		BX_DELETE(g_allocator, s_fileWriter);
 		BX_DELETE(g_allocator, s_fileWriter);
 		s_fileWriter = NULL;
 		s_fileWriter = NULL;
 
 
-		if (BX_ENABLED(ENTRY_CONFIG_PROFILER)
-		&&  NULL != s_rmt)
-		{
-			rmt_DestroyGlobalInstance(s_rmt);
-		}
-
 		return result;
 		return result;
 	}
 	}
 
 

+ 0 - 12
src/bgfx.cpp

@@ -4,21 +4,9 @@
  */
  */
 
 
 #include <bx/platform.h>
 #include <bx/platform.h>
-#if BX_PLATFORM_WINDOWS
-// BK - Remotery needs WinSock, but on VS2015/Win10 build
-//      fails if WinSock2 is included after Windows.h?!
-#	include <winsock2.h>
-#endif // BX_PLATFORM_WINDOWS
 
 
 #include "bgfx_p.h"
 #include "bgfx_p.h"
 #include <bgfx/embedded_shader.h>
 #include <bgfx/embedded_shader.h>
-
-#if BGFX_CONFIG_PROFILER_REMOTERY_BUILD_LIB
-#	define RMT_USE_D3D11 BGFX_CONFIG_RENDERER_DIRECT3D11
-#	define RMT_USE_OPENGL BGFX_CONFIG_RENDERER_OPENGL
-#	include <remotery/lib/Remotery.c>
-#endif // BGFX_CONFIG_PROFILER_REMOTERY_BUILD_LIB
-
 #include <bx/file.h>
 #include <bx/file.h>
 #include <bx/mutex.h>
 #include <bx/mutex.h>
 
 

+ 5 - 24
src/bgfx_p.h

@@ -45,30 +45,11 @@
 				)
 				)
 
 
 #ifndef BGFX_PROFILER_SCOPE
 #ifndef BGFX_PROFILER_SCOPE
-#	if BGFX_CONFIG_PROFILER_MICROPROFILE
-#		include <microprofile.h>
-#		define BGFX_PROFILER_SCOPE(_group, _name, _color) MICROPROFILE_SCOPEI(#_group, #_name, _color)
-#		define BGFX_PROFILER_BEGIN(_group, _name, _color) BX_NOOP()
-#		define BGFX_PROFILER_BEGIN_DYNAMIC(_namestr) BX_NOOP()
-#		define BGFX_PROFILER_END() BX_NOOP()
-#		define BGFX_PROFILER_SET_CURRENT_THREAD_NAME(_name) BX_NOOP()
-#	elif BGFX_CONFIG_PROFILER_REMOTERY
-#		define RMT_ENABLED BGFX_CONFIG_PROFILER_REMOTERY
-#		define RMT_USE_D3D11 BGFX_CONFIG_RENDERER_DIRECT3D11
-#		define RMT_USE_OPENGL BGFX_CONFIG_RENDERER_OPENGL
-#		include <remotery/lib/Remotery.h>
-#		define BGFX_PROFILER_SCOPE(_group, _name, _color) rmt_ScopedCPUSample(_group##_##_name, RMTSF_None)
-#		define BGFX_PROFILER_BEGIN(_group, _name, _color) rmt_BeginCPUSample(_group##_##_name, RMTSF_None)
-#		define BGFX_PROFILER_BEGIN_DYNAMIC(_namestr) rmt_BeginCPUSampleDynamic(_namestr, RMTSF_None)
-#		define BGFX_PROFILER_END() rmt_EndCPUSample()
-#		define BGFX_PROFILER_SET_CURRENT_THREAD_NAME(_name) rmt_SetCurrentThreadName(_name)
-#	else
-#		define BGFX_PROFILER_SCOPE(_group, _name, _color) BX_NOOP()
-#		define BGFX_PROFILER_BEGIN(_group, _name, _color) BX_NOOP()
-#		define BGFX_PROFILER_BEGIN_DYNAMIC(_namestr) BX_NOOP()
-#		define BGFX_PROFILER_END() BX_NOOP()
-#		define BGFX_PROFILER_SET_CURRENT_THREAD_NAME(_name) BX_NOOP()
-#	endif // BGFX_CONFIG_PROFILER_*
+#	define BGFX_PROFILER_SCOPE(_group, _name, _color) BX_NOOP()
+#	define BGFX_PROFILER_BEGIN(_group, _name, _color) BX_NOOP()
+#	define BGFX_PROFILER_BEGIN_DYNAMIC(_namestr) BX_NOOP()
+#	define BGFX_PROFILER_END() BX_NOOP()
+#	define BGFX_PROFILER_SET_CURRENT_THREAD_NAME(_name) BX_NOOP()
 #endif // BGFX_PROFILER_SCOPE
 #endif // BGFX_PROFILER_SCOPE
 
 
 namespace bgfx
 namespace bgfx

Some files were not shown because too many files changed in this diff